1. 程式人生 > >淺談java放射機制

淺談java放射機制

bject bootstrap pan voc get set class文件 獲得 訪問

java反射機制概念:

  1. 用途:JAVA反射機制是在運行狀態中,對於任意一個類,都能夠知道這個類的所有屬性和方法;對於任意一個對象,都能夠調用它的任意方法和屬性;這種動態獲取信息以及動態調用對象方法的功能稱為java語言的反射機制。

  2. JAVA反射(放射)機制 :程序運行時,允許改變程序結構或變量類型,這種語言稱為動態語言。從這個觀點看,Perl,Python,Ruby是動態語言,C++,Java,C#不是動態語言。但是JAVA有著一個非常突出的動態相關機制:Reflection,用在Java身上指的是我們可以於運行時加載、探知、使用編譯期間完全未知的classes。換句話說,Java程序可以加載一個運行時才得知名稱的class,獲悉其完整構造(但不包括methods定義),並生成其對象實體、或對其fields設值、或喚起其methods。


/**
* 反射:就是通過.class文件對象,去使用該類的成員變量,構造方法,成員方法.
*
* Person p1=new Person();
* p1.使用;
* 這個就不是反射
* @author Administrator
*
*要這樣使用就必須獲得class文件對象,也就是得到class類對象.
*獲取class類對象的方法
* 1.getClass();
* 2.數據類型的靜態屬性class
* 3.class類中的靜態方法,className要是全限定名
* public static Class<?> forName(String className)
?
*選擇那種方法;
* 自己隨便,開發選擇第三種,因為這種方式是一個字符串,而不是一個具體的類名,這樣我們就可以把字串
*配置到配置文件中
*/
public class ReflectDemo {
public static void main(String[] args) throws ClassNotFoundException {
//方式一
Person p1 = new Person();
Class c1 = p1.getClass();

Person p2=new Person();
Class c2 = p2.getClass();

System.out.println(p1==p2);//false
System.out.println(c1==c2);//true

//方式二
Class c3=Person.class;
//int.class;
//String.class;
System.out.println(c3==c2);//true;

//方式三,
Class c4=Class.forName("day13.Person");
System.out.println(c4==c3);
}
}

反射是框架設計的靈魂:

[我還不懂,沒去看過框架的源碼,以後有機會回去看]

1.通過反射獲取成員變量並使用:


public class Reflect1 {
public static void main(String[] args) throws Exception{
//獲取字節碼對象
Class c=Class.forName("day13.Person");

/*//獲取所有成員變量
java.lang.reflect.Field[] fields=c.getDeclaredFields();
for (java.lang.reflect.Field field : fields) {
System.out.println(field);
}*/

//通過無參構造方法創建對象
Constructor cons = c.getConstructor();
Object obj=cons.newInstance();

//獲取單個成員變量
//並對其賦值
java.lang.reflect.Field addressFiled=c.getField("address");
addressFiled.set(obj, "北京");//給obj對象的addressFiled設置值.
System.out.println(obj);
}
}

Person類:

public class Person {
private String name;
private int age;
public String address;

//構造方法
public Person(){

}
//成員方法
Person(String name,Integer age){
this.name=name;
this.age=age;
}
public Person(String name,int age,String address){
this.name=name;
this.age=age;
this.address=address;
}
public void show(){
System.out.println("show");
}
public void method(String s){
System.out.println("method"+s);
}
public String method(String s,int i){
return s+"---"+i;
}
private void function(){
System.out.println("function");
}

@Override
public String toString() {
return "Person [name=" + name + ", age=" + age + ", address=" + address
+ "]";
}

}

2.通過反射獲取無參構造方法:


public class ReflectDemo {
public static void main(String[] args) throws ClassNotFoundException, SecurityException, NoSuchMethodException, IllegalArgumentException, InstantiationException, IllegalAccessException, InvocationTargetException {
//獲取字節碼對象
Class c=Class.forName("day13.Person");

//獲取構造方法
//public Constructor[] getConstructors(),獲取的是public修飾的構造方法
//public Constructor[] getDeclaredConstructors()返回所有

/*Constructor[] cons=c.getDeclaredConstructors();
for (Constructor constructor : cons) {
System.out.println(constructor);
}*/

//獲取單個構造方法
Constructor cons=c.getConstructor();
Object obj=cons.newInstance();
System.out.println(obj);
}
}

2.通過反射獲取有參構造方法:

public static void main(String[] args) throws Exception{
//獲取字節碼對象
Class c=Class.forName("day13.Person");
//獲取帶參構造參數
//public Constructor getConstructor(Class<?>... parameterTypes)
Constructor con = c.getConstructor(String.class,int.class,String.class);

//通過帶參構造方法對象創建對象
//public T newInstance(Object... initargs)
Object obj=con.newInstance("海燕",23,"成都");
System.out.println(obj);

}
}

3.通過放射獲取私有構造方法(加一個Declared):


public class ReflectDemo3 {
public static void main(String[] args) throws Exception{
//獲取字節碼對象
Class c=Class.forName("day13.Person");
//獲取帶參構造函數
Constructor cons = c.getDeclaredConstructor(String.class,Integer.class);

cons.setAccessible(true);//值為 true則指示反射的對象在使用時應該取消 Java語言訪問檢查
Object obj=cons.newInstance("海燕",23);
System.out.println(obj);
}
}

4.通過放射獲取成員變量並調用

package fanshe.field;
import java.lang.reflect.Field;
/*
* 獲取成員變量並調用:
*
* 1.批量的
* 1).Field[] getFields():獲取所有的"公有字段"
* 2).Field[] getDeclaredFields():獲取所有字段,包括:私有、受保護、默認、公有;
* 2.獲取單個的:
* 1).public Field getField(String fieldName):獲取某個"公有的"字段;
* 2).public Field getDeclaredField(String fieldName):獲取某個字段(可以是私有的)
*
* 設置字段的值:
* Field --> public void set(Object obj,Object value):
* package fanshe.field;
import java.lang.reflect.Field;
/*
* 獲取成員變量並調用:
*
* 1.批量的
* 1).Field[] getFields():獲取所有的"公有字段"
* 2).Field[] getDeclaredFields():獲取所有字段,包括:私有、受保護、默認、公有;
* 2.獲取單個的:
* 1).public Field getField(String fieldName):獲取某個"公有的"字段;
* 2).public Field getDeclaredField(String fieldName):獲取某個字段(可以是私有的)
*
* 設置字段的值:
* Field --> public void set(Object obj,Object value):
* 參數說明:
* 1.obj:要設置的字段所在的對象;
* 2.value:要為字段設置的值;
*
*/
public class Fields {

public static void main(String[] args) throws Exception {
//1.獲取Class對象
Class stuClass = Class.forName("fanshe.field.Student");
//2.獲取字段
System.out.println("************獲取所有公有的字段********************");
Field[] fieldArray = stuClass.getFields();
for(Field f : fieldArray){
System.out.println(f);
}
System.out.println("************獲取所有的字段(包括私有、受保護、默認的)********************");
fieldArray = stuClass.getDeclaredFields(); for(Field f : fieldArray){ System.out.println(f); } System.out.println("*************獲取公有字段**並調用***********************************"); Field f = stuClass.getField("name"); System.out.println(f); //獲取一個對象 Object obj = stuClass.getConstructor().newInstance();//產生Student對象--》Student stu = new Student(); //為字段設置值 f.set(obj, "劉德華");//為Student對象中的name屬性賦值--》stu.name = "劉德華" //驗證 Student stu = (Student)obj; System.out.println("驗證姓名:" + stu.name); System.out.println("**************獲取私有字段****並調用********************************"); f = stuClass.getDeclaredField("phoneNum"); System.out.println(f); f.setAccessible(true);//暴力反射,解除私有限定 f.set(obj, "18888889999"); System.out.println("驗證電話:" + stu); } }

對應的student類


package fanshe.field;

public class Student {
public Student(){

}
//**********字段*************//
public String name;
protected int age;
char sex;
private String phoneNum;

@Override
public String toString() {
return "Student [name=" + name + ", age=" + age + ", sex=" + sex
+ ", phoneNum=" + phoneNum + "]";
}


}

反射方法的其它使用之---通過反射越過泛型檢查

泛型用在編譯期,編譯過後泛型擦除(消失掉)。所以是可以通過反射越過泛型檢查的 ,其實也就是在.class文件中沒有泛型的概念的.


public static void main(String[] args) throws Exception{
ArrayList<String> strList = new ArrayList<>();
strList.add("aaa");
strList.add("bbb");

// strList.add(100);
//獲取ArrayList的Class對象,反向的調用add()方法,添加數據
Class listClass = strList.getClass(); //得到 strList 對象的字節碼 對象
//獲取add()方法
Method m = listClass.getMethod("add", Object.class);
//調用add()方法
m.invoke(strList, 100);

//遍歷集合
for(Object obj : strList){
System.out.println(obj);
}
}

學習反射必須明白類加載:

啟動(Bootstrap)類加載器:java中jre中的類.

擴展(Extension)類加載器:java擴展的api類ext好像是

系統(System)類加載器:自己寫的類

https://www.2cto.com/uploadfile/Collfiles/20160126/2016012609242889.jpg

淺談java放射機制