天天看點

Java29- 反射

反射

反射就是根據位元組碼檔案,反射類的資訊,字段,方法,構造方法等類的内容,

根據位元組碼檔案建立對象,調用方法的技術

文章目錄

  • ​​反射​​
  • ​​反射的基礎,是class的對象​​
  • ​​反射類的資訊​​
  • ​​建立Class對象​​
  • ​​反射類的資訊​​
  • ​​修飾類 `Modifiers:修飾器`​​
  • ​​類名​​
  • ​​父名​​
  • ​​接口​​
  • ​​通過反射技術通路字段​​
  • ​​建立Class對象,​​
  • ​​反射name字段​​
  • ​​通過反射技術建立對象(執行個體),預設調用類的無參構造​​
  • ​​設定字段的值​​
  • ​​傳回字段的值​​
  • ​​通路私有字段 age​​
  • ​​通過反射技術調用方法​​
  • ​​代碼​​
  • ​​Person類​​
  • ​​建立Class對象的方式​​
  • ​​反射類的資訊​​
  • ​​通過反射技術通路字段​​
  • ​​通過反射技術調用方法​​

反射的基礎,是class的對象

  • 每一個類都有class屬性
  • 每個對象都有getClass() 方法
  • Class.forName(完整類名)

Class.forName 傳回Class對象時,回把參數指定的類加載到記憶體中

Class<?> class7 = Person.class;   //沒有執行Person類靜态代碼塊, 說明Person類沒有加載記憶體
Class<?> class8 = Class.forName("com.bjpowernode.chapter08.demo01.Person");  //執行了靜态代碼塊, 說明類加載了記憶體      

反射類的資訊

java.lang.reflect包中有反射相關的類

  • class1.getModifiers() 傳回類的修飾符
  • class1.getName() 傳回完整類名
  • class1.getSimpleName() 簡易類名
  • class1.getSuperClass() 父類
  • class1.getInterfaces() 接口

建立Class對象

Class<?> class1 = String.class;

反射類的資訊

修飾類 Modifiers:修飾器

class1.getModifiers();

Modifier.toString(mod);//整數轉換為字元串

類名

​Simple簡單​

class1.getName() 傳回完整類名

class1.getSimpleName() //傳回簡易類名

父名

class1.getSuperClass();

Class<?> superclass = class1.getSuperclass();
    //判斷父類是否為Object
    if ( Object.class != superclass ) {
      sb.append(" extends ");
      sb.append( superclass.getSimpleName() );      
    }      

接口

​getInterfaces()​

​傳回接口數組, 如果類沒有實作接口,傳回的數組長度為0

class1.getInterfaces();

Class<?>[] interfaces = class1.getInterfaces();
    if( interfaces.length > 0 ){     //實作了接口
      sb.append(" implements ");
      //周遊接口數組
      for( int i = 0 ;  i<interfaces.length ; i++){
        sb.append( interfaces[i].getSimpleName() );
        //接口之間使用逗号分隔
        if ( i < interfaces.length - 1) {
          sb.append(",");
        }
      }
    }       

通過反射技術通路字段

class1.getField(字段名)     傳回指定字段名的公共字段      
class1.getDeclaredField(字段名) 傳回指定名稱的字段(即使它是私有的)      
class1.newInstance()       建立一個執行個體(建立一個對象)      
field.set(對象名, 字段的值);      設定字段的值      
field.get(對象名);          傳回字段的值      
field.setAccessible(true);       設定字段的可通路性      

建立Class對象,

Class<?> class1 = Person.class;

反射name字段

Field nameF = class1.getField(“name”);

通過反射技術建立對象(執行個體),預設調用類的無參構造

Object p1 = class1.newInstance(); //相當于new Person()

設定字段的值

傳回字段的值

通路私有字段 age

Object p1 = class1.newInstance();      //相當于new Person()

Field ageF = class1.getField("age");    //隻能傳回公共字段
Field ageF = class1.getDeclaredField("age");    //傳回字段
ageF.setAccessible(true);        //設定字段的可通路性
ageF.set(p1, 18);
System.out.println( ageF.get(p1));
System.out.println( p1 );      

通過反射技術調用方法

  • class1.getMethod(方法名,參數類型清單) 反射指定方法簽名的公共方法
  • method.invoke(執行個體名, 方法的實參清單) 調用方法
public static void main(String[] args) throws NoSuchMethodException, SecurityException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
    //1) 建立Class對象
    Class<?> class1 = Person.class;
    
    //2) 反射show()方法
    Method showM = class1.getMethod("show", null);
    
    //3)通過反射技術建立執行個體
    Object obj = class1.newInstance();      //new Person()
    
    //4)調用方法
    showM.invoke(obj, null);    //obj.show()
    
    //5)反射set(String, int)方法
    Method setM = class1.getMethod("set", String.class , int.class );
    setM.invoke(obj, "lisi", 66);
    
    showM.invoke(obj);
    System.out.println( obj );
  }      

代碼

Person類

public class Person {

  static{
    System.out.println("靜态代碼塊, 在類加載記憶體後執行");
  }
  
  public String name;    
  private int age;
  
  @Override
  public String toString() {
    return "Person [name=" + name + ", age=" + age + "]";
  }
  
  public void show() {
    System.out.println("name:" + name + ",age:" + age);
  }
  
  public void set(String name, int age) {
    this.age = age;
    this.name = name;
  }
  
}      

建立Class對象的方式

public class Test01 {

  public static void main(String[] args) throws ClassNotFoundException {
    //1) 每個類都有一個Class屬性
    Class class1 = Test01.class;
    
    //2)每個 對象有getClass()
    Class class2 =  new Test01().getClass();
    
    //3) Class.forName()
    Class class3 = Class.forName("com.bjpowernode.chapter08.demo01.Test01");
    
    System.out.println( class1 );
    //
    System.out.println( class1 == class2 );
    System.out.println( class2 == class3 );
     
    //4)
    Class<?>  class4 = int.class;
    Class<?> class5 = Integer.class;
    System.out.println( class4 == class5 );   //false
    Class<?> class6 = Integer.TYPE;
    System.out.println( class4 == class6 );  //true
    
    //5) Class.forName()r傳回Class對象時, 會把參數指定的類加載到記憶體中
//    Class<?> class7 = Person.class;   //沒有執行Person類靜态代碼塊, 說明Person類沒有加載記憶體
    Class<?> class8 = Class.forName("com.bjpowernode.chapter08.demo01.Person");  //執行了靜态代碼塊, 說明類加載了記憶體
    
    
  }

}      

反射類的資訊

public class Test02 {

  public static void main(String[] args) {
    //1)建立Class對象
    Class<?> class1 = String.class;        
//    Class<?> class1 = Integer.class;        
    
    StringBuilder sb = new StringBuilder();
    //2)反射類的資訊
    //2.1 修飾符
    int mod = class1.getModifiers();    //方法傳回類的修飾符,是一個整數
    String modifier = Modifier.toString(mod);//整數轉換為字元串
    sb.append( modifier );
    //2.2 類名
    sb.append(" class  ");
//    sb.append( class1.getName() ) ;     //getName()r傳回完整類名 
    sb.append( class1.getSimpleName() ) ;  //傳回簡易類名 
    
    //2.3 父類
    Class<?> superclass = class1.getSuperclass();
    //判斷父類是否為Object
    if ( Object.class != superclass ) {
      sb.append(" extends ");
      sb.append( superclass.getSimpleName() );      
    }
    
    //2.4 接口,getInterfaces()傳回接口數組, 如果類沒有實作接口,傳回的數組長度為0
    Class<?>[] interfaces = class1.getInterfaces();
    if( interfaces.length > 0 ){    //實作了接口
      sb.append(" implements ");
      //周遊接口數組
      for( int i = 0 ;  i<interfaces.length ; i++){
        sb.append( interfaces[i].getSimpleName() );
        //接口之間使用逗号分隔
        if ( i < interfaces.length - 1) {
          sb.append(",");
        }
      }
    } 
    
    System.out.println( sb );
  }

}      

通過反射技術通路字段

public class Test03 {

  public static void main(String[] args) throws NoSuchFieldException, SecurityException, InstantiationException, IllegalAccessException {
    //1) 建立Class對象, 
    Class<?> class1 = Person.class;
    
    //2) 反射name字段
    Field nameF = class1.getField("name");
    
    //3) 通過反射技術建立對象(執行個體), 預設調用類的無參構造
    Object p1 = class1.newInstance();      //相當于new Person()
    
    //4)設定字段的值
    nameF.set(p1, "lisi");        //p1.setName("lisi")
    
    //5)傳回字段的值
    System.out.println( p1 );
    System.out.println( nameF.get(p1) );    //p1.getName()
    
    //6)通路私有字段: age
//    Field ageF = class1.getField("age");    //隻能傳回公共字段
    Field ageF = class1.getDeclaredField("age");    //傳回字段
    ageF.setAccessible(true);        //設定字段的可通路性
    ageF.set(p1, 18);
    System.out.println( ageF.get(p1));
    System.out.println( p1 );
  }

}      

通過反射技術調用方法

public class Test05 {

  public static void main(String[] args) throws NoSuchMethodException, SecurityException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
    //1) 建立Class對象
    Class<?> class1 = Person.class;
    
    //2) 反射show()方法
    Method showM = class1.getMethod("show", null);
    
    //3)通過反射技術建立執行個體
    Object obj = class1.newInstance();      //new Person()
    
    //4)調用方法
    showM.invoke(obj, null);    //obj.show()
    
    //5)反射set(String, int)方法
    Method setM = class1.getMethod("set", String.class , int.class );
    setM.invoke(obj, "lisi", 66);
    
    showM.invoke(obj);
    System.out.println( obj );
  }

}