Java - 反射機制

java的反射機制原理

一反射機制的概念:指在運行狀態(tài)中,對于任意一個類,都能夠知道這個類的所有屬性和方法,對于任意一個對象,都能調用它的任意一個方法.這種動態(tài)獲取信息,以及動態(tài)調用對象方法的功能叫java語言的反射機制.java反射機制是圍繞Class類展開的,在深入java反射原理之前,需要對類加載機制有一個大致的了解。jvm使用ClassLoader將字節(jié)碼文件(class文件)加載到方法區(qū)內存中:Class clazz = ClassLoader.getSystemClassLoader().loadClass("com.mypackage.MyClass");可見ClassLoader根據類的完全限定名加載類并返回了一個Class對象,而java反射的所有起源都是從這個class類開始的??磦€列子://1.獲取類

?Class c = Class.forName("_12_CustomerService");

//獲取某個特定的方法

//通過:方法名+形參列表

?Method m = c.getDeclaredMethod("login",String.class,String.class);

//通過反射機制執(zhí)行l(wèi)ogin方法.

Object o = c.newInstance();

//調用o對象的m方法,傳遞"admin""123"參數,方法的執(zhí)行結果是retValue

Object retValue = m.invoke(o, "admin","123");

System.out.println(retValue); //true

二.反射機制的作用

1.在運行時判斷任意一個對象所屬的類;

2.在運行時獲取類的對象;

3.在運行時訪問java對象的屬性,方法,構造方法等。

三.反射機制的優(yōu)點與缺點

首先要搞清楚為什么要用反射機制?直接創(chuàng)建對象不就可以了嗎,這就涉及到了動態(tài)與靜態(tài)的概念。靜態(tài)編譯:在編譯時確定類型,綁定對象,即通過。動態(tài)編譯:運行時確定類型,綁定對象。動態(tài)編譯最大限度發(fā)揮了java的靈活性,體現(xiàn)了多態(tài)的應用,有以降低類之間的藕合性。?

反射機制的優(yōu)點:可以實現(xiàn)動態(tài)創(chuàng)建對象和編譯,體現(xiàn)出很大的靈活性(特別是在J2EE的開發(fā)中它的靈活性就表現(xiàn)的十分明顯)。通過反射機制我們可以獲得類的各種內容,進行了反編譯。對于JAVA這種先編譯再運行的語言來說,反射機制可以使代碼更加靈活,更加容易實現(xiàn)面向對象

反射機制的缺點:對性能有影響。使用反射基本上是一種解釋操作,我們可以告訴JVM,我們希望做什么并且它 滿足我們的要求。這類操作總是慢于只直接執(zhí)行相同的操作。

1.通過一個對象獲得完整的包名和類名

添加一句:所有類的對象其實都是Class的實例。

class?Demo{?//other codes...??}?class?hello{public?static?void?main(String[] args) {Demo demo=new?Demo(); ??????System.out.println(demo.getClass().getName());}}

2.實例化Class類對象

public static void main(String[] args) {

Class<?> demo1=null;

Class<?> demo2=null;

Class<?> demo3=null;

try{

//一般盡量采用這種形式

?demo1=Class.forName("Reflect.Demo");

}catch(Exception e){

e.printStackTrace();

}

emo2=new Demo().getClass();

demo3=Demo.class;

System.out.println("類名稱 ??"+demo1.getName());

System.out.println("類名稱 ??"+demo2.getName());

System.out.println("類名稱 ??"+demo3.getName());

【運行結果】:

類名稱Reflect.Demo

類名稱Reflect.Demo

類名稱Reflect.Demo


3.通過Class實例化其他類的對象

class Person{

??????public String getName() {

??????????return name;

??????}

??????public void setName(String name) {

??????????this.name = name;

??????}

????public int getAge() {

?????????return age;

?????}

?????public void setAge(int age) {

?????????this.age = age;

?????}

?????@Override

?????public String toString(){

?????????return "["+this.name+" ?"+this.age+"]";

?????}

?????private String name;

?????private int age;

?}


?class hello{

?????public static void main(String[] args) {

?????????Class<?> demo=null;

?????????try{

????????????demo=Class.forName("Reflect.Person");

?????????}catch (Exception e) {

?????????????e.printStackTrace();

?????????}

?????????Person per=null;

?????????try {

????????????per=(Person)demo.newInstance();

?????????} catch (InstantiationException e) {

?????????????// TODO Auto-generated catch block

?????????????e.printStackTrace();

?????????} catch (IllegalAccessException e) {

?????????????// TODO Auto-generated catch block

?????????????e.printStackTrace();

?????????}

?????????per.setName("Rollen");

?????????per.setAge(20);

?????????System.out.println(per);

?????}

?}

4.通過Class調用其他類中的構造函數 (也可以通過這種方式通過Class創(chuàng)建其他類的對象)

package Reflect;


import java.lang.reflect.Constructor;


class Person{

????public Person() {


????}

????public Person(String name){

????????this.name=name;

????}

????public Person(int age){

????????this.age=age;

????}

????public Person(String name, int age) {

????????this.age=age;

????????this.name=name;

????}

????public String getName() {

????????return name;

????}

????public int getAge() {

????????return age;

????}

????@Override

????public String toString(){

????????return "["+this.name+" ?"+this.age+"]";

????}

????private String name;

????private int age;

}


class hello{

????public static void main(String[] args) {

????????Class<?> demo=null;

????????try{

????????????demo=Class.forName("Reflect.Person");

????????}catch (Exception e) {

????????????e.printStackTrace();

????????}

????????Person per1=null;

????????Person per2=null;

????????Person per3=null;

????????Person per4=null;

//取得全部的構造函數

????????Constructor<?> cons[]=demo.getConstructors();

????????try{

????????????per1=(Person)cons[0].newInstance();

????????????per2=(Person)cons[1].newInstance("Rollen");

????????????per3=(Person)cons[2].newInstance(20);

????????????per4=(Person)cons[3].newInstance("Rollen",20);

????????}catch(Exception e){

????????????e.printStackTrace();

????????}

????????System.out.println(per1);

????????System.out.println(per2);

????????System.out.println(per3);

????????System.out.println(per4);

????}

}

5.取得其他類中的父類

class hello{

????public static void main(String[] args) {

????????Class<?> demo=null;

????????try{

????????????demo=Class.forName("Reflect.Person");

????????}catch (Exception e) {

????????????e.printStackTrace();

????????}

//取得父類

????????Class<?> temp=demo.getSuperclass();

System.out.println("繼承的父類為: ??"+temp.getName());

????}

}

//【運行結果】

//繼承的父類為: ??java.lang.Object

6.通過反射操作屬性

class hello {

????public static void main(String[] args) throws Exception {

????????Class<?> demo = null;

????????Object obj = null;

????????demo = Class.forName("Reflect.Person");

????????obj = demo.newInstance();

????????Field field = demo.getDeclaredField("sex");

????????field.setAccessible(true);

field.set(obj, "男");

????????System.out.println(field.get(obj));

}

7.通過反射調用其他類中的方法

class hello {

????public static void main(String[] args) {

????????Class<?> demo = null;

????????try {

????????????demo = Class.forName("Reflect.Person");

????????} catch (Exception e) {

????????????e.printStackTrace();

????????}

????????try{

//調用Person類中的sayChina方法

????????????Method method=demo.getMethod("sayChina");

????????????method.invoke(demo.newInstance());

//調用Person的sayHello方法

????????????method=demo.getMethod("sayHello", String.class,int.class);

????????????method.invoke(demo.newInstance(),"Rollen",20);

????????}catch (Exception e) {

????????????e.printStackTrace();

????????}

????}

}

//【運行結果】:

//hello ,china

//Rollen ?20

用幾句話總結反射的實現(xiàn)原理:

1.反射類及反射方法的獲取,都是通過從列表中搜尋查找匹配的方法,所以查找性能會隨類的大小方法多少而變化;

2.每個類都會有一個與之對應的Class實例,從而每個類都可以獲取method反射方法,并作用到其他實例身上;

3.反射也是考慮了線程安全的,放心使用;

4.反射使用軟引用relectionData緩存class信息,避免每次重新從jvm獲取帶來的開銷;

5.反射調用多次生成新代理Accessor, 而通過字節(jié)碼生存的則考慮了卸載功能,所以會使用獨立的類加載器;

6.當找到需要的方法,都會copy一份出來,而不是使用原來的實例,從而保證數據隔離;

7.調度反射方法,最終是由jvm執(zhí)行invoke0()執(zhí)行;

?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

友情鏈接更多精彩內容