淺談java放射機制

java反射機制概念:

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

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


/**
* 反射:就是經過.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類:ide

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):this


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.經過放射獲取成員變量並調用atom

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類spa


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

相關文章
相關標籤/搜索