一篇瞭解Java反射

SecIN發表於2022-10-31

反射

image-20220322144346557


首先從執行原理了解為什麼要用反射,當我們執行一段程式碼時,程式碼經過javac編譯得到.class的位元組碼檔案,再經過類載入器的loadClass()方法建立Class類物件到堆中;當我們例項化一個物件時,該物件會自動匹配到對應堆中的Class類物件,進而呼叫方法,操作屬性等。至此程式結束。


但透過上述方式,我們寫好程式執行後,如果突然需要載入另一個類時,就需要停止執行並要寫一段程式碼去例項化新需求的類,對伺服器來說會造成一定的影響;這時就體現出了反射的優勢,反射機制可以透過修改配置檔案,而無需修改原始碼對類進行重新載入。


反射是動態獲取資訊及動態呼叫物件方法的方式,Java本身是一種靜態語言,而經過反射後讓Java有了一定的動態性,變為一種“準動態語言”。

反射例項理解

透過外部檔案配置,在不修改原始碼的情況下,來控制程式反射例項看不懂的話,後邊自Class類開始會有各方法的分佈介紹

A.java

package Sentiment.refelction;

public class A {
    private String name="refelction";
    public int age=10;
    public void a(){
        System.out.println("this is =>A");
    }
    public void b(){
        System.out.println("this is =>B");
    }
}

re.properties(配置檔案)

path=Sentiment.refelction.A
method=a

此時如果我們想呼叫a()方法,有如下幾種方法:

傳統方式

A cat = new A();
cat.a();

I/O流根據配置檔案讀取

該方式讀取後由於path型別為String,所以無法正常讀取到我們的類方法

Properties properties = new Properties();
properties.load(new FileInputStream("re.properties"));
String path = properties.get("path").toString(); //Sentiment.refelction.A
String method = properties.get("method").toString(); // a
new path().a();   //報錯

反射

這時就可以透過反射將String型別的path,轉為Class型別的物件進行呼叫

//(1) 獲取Class型別的物件c1
Class c1 = Class.forName(path);
//System.out.println(c1);
//(2) 透過c1 得到載入的類 Sentiment.refelction.A的物件例項
Object o = c1.newInstance();
System.out.println("o的執行型別是:"+o.getClass());
//(3)透過c1 得到載入的類Sentiment.refelction.A 的method的方法物件"a"
Method method1 =c1.getMethod(method); 
//(4)透過method1 呼叫方法物件來實現呼叫方法
method1.invoke(o);//傳統方法 物件.方法() ,反射 方法.invoke(物件)

此時如果使用者,想要呼叫A.java中的b()方法,就體現出了反射的優勢。

還是先看傳統方法,需要將a改為b,即修改原始碼

A cat = new A();
cat.b();

而反射機制則可以透過修改配置檔案,而無需修改原始碼。在使用者需求較大時,可以完全體現反射優勢

path=Sentiment.refelction.A
method=a

反射優缺點

優點

可以動態的建立和使用物件(也是框架底層核心).使用靈活,沒有反射機制,框架技術就失去底層支撐。

缺點

使用反射基本是解釋執行,對執行速度有影響.

執行同一內容耗時對比

image-20220322160327354

Class類

介紹

1.Class也是類,也繼承Object類

image-20220323094648819

2.Class類物件不是new出來的,而是系統建立的 (都是透過Classloader類建立的)

3.每個類的Class類物件,在記憶體中只有一份,因為類只載入一次

public class Class01 {
    public static void main(String[] args) throws ClassNotFoundException {
        //每個類的Class類物件,在記憶體中只有一份,因為類只載入一次
        Class c1 = Class.forName("Sentiment.refelction.A");
        Class c2 = Class.forName("Sentiment.refelction.A");
        System.out.println(c1.hashCode());
        System.out.println(c2.hashCode());
    }
}

image-20220323095049247

4.每個類的例項都會記得自己是由哪個Class 例項所生成(如最開始的執行原理圖所示Cat會找到對應的Cat類物件)

5.透過Class物件可以完整地得到一個類的完整結構,透過一系列API

image-20220323100818374

6.Class物件是存放在堆的

7.類的位元組碼二進位制資料,是放在方法區的,有的地方稱為類的後設資料(包括方法程式碼變數名,方法名,訪問許可權等等)

Class類常用方法

Car.java

package Sentiment.refelction;

public class Car {
    public String brand="寶馬";
    public int price = 5000000;
    public String color = "白色";

    @Override
    public String toString() {
        return "Car{" +
                "brand='" + brand + '\'' +
                ", price=" + price +
                ", color='" + color + '\'' +
                '}';
    }
}

Class02.java

package Sentiment.refelction;

import java.lang.reflect.Field;

public class Class02 {
    public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchFieldException {
        String path="Sentiment.refelction.Car";
        //1. 獲取Car類對應的Class物件
        Class c1 = Class.forName(path);
        //2. 輸出c1
        System.out.println(c1); //顯示c1物件是哪個類的Class物件 Sentiment.refelction.Car
        System.out.println(c1.getClass());//輸出c1執行型別 java.lang.Class
        //3.獲取包名
        System.out.println(c1.getPackage().getName());
        //4.得到類的全路徑
        System.out.println(c1.getName());
        //5. 透過c1建立物件例項
        Car car = (Car)c1.newInstance();
        System.out.println(car);    //輸出car時自動呼叫toString()方法
        //6. 透過反射獲取屬性
        Field brand = c1.getField("brand");
        System.out.println(brand.get(car));
        //7.透過反射給屬性賦值
        brand.set(car,"賓士");
        System.out.println(brand.get(car));
        //8.獲取所有屬性及屬性值
        Field[] fields = c1.getFields();
        for(Field f : fields){
            System.out.print(f.getName()+":");  //屬性名
            System.out.print(f.get(car)+" ");   //屬性值
        }
    }
}

獲取Class類物件

1.已知一個類的全類名,且該類在類路徑下,可透過Class類的靜態方法forName()獲取,可能跑出ClassNotFoundException

Class c1=Class.forName("Sentiment.refelction.Car")

多用於配置檔案,讀取類全路徑,載入類

2.若已知具體的類,透過類的class獲取,該方式最為安全可靠,程式效能最高

Class c2=Car.class

多用於引數傳遞,比如透過反射得到對應構造器物件

3.前提:已知某個類的例項,呼叫該例項的getClass()方法獲取Class物件

Car car = new Car();
Class c3 = car.getClass();

多用於透過建立好的物件,獲取Class物件.

4.透過類載入器來獲取Class類物件

//(1)先得到載入器
 ClassLoader classLoader = car.getClass().getClassLoader();
//(2)透過類載入器得到Class物件
 Class c4 =classLoader.loadClass(path);

5.基本資料(int, char, boolean,float,double,byte,long,short)按如下方式得到Class類物件

Class c5 = 基本資料型別.class

6.基本資料型別對應的包裝類,可以透過type得到Class類物件

Class c6 = 包裝類.type

GetClass.java

package Sentiment.refelction;

public class GetClass {
    public static void main(String[] args) throws ClassNotFoundException {
        //1.Class.forName)
        String path="Sentiment.refelction.Car"; //透過讀取配置檔案獲取
        Class c1 = Class.forName(path);
        System.out.println(c1);
        //2.類名.class,用於引數傳遞
        Class c2 = Car.class;
        System.out.println(c2);
        //3.物件.getClass(),用於有物件例項
        Car car = new Car();
        Class c3 = car.getClass();
        System.out.println(c3);
        //4.透過類載入器來獲取Class類物件
        //(1)先得到載入器car
        ClassLoader classLoader = car.getClass().getClassLoader();
        //(2)透過類載入器得到Class物件
        Class c4 =classLoader.loadClass(path);
        System.out.println(c4);
        //5.基本資料(int, char, boolean,float,double,byte,long,short)按如下方式得到Class類物件
        Class c5 = int.class;
        Class<Character> characterClass = char.class;
        //6.基本資料型別對應的包裝類,可以透過type得到Class類物件
        Class<Integer> type = Integer.TYPE;
        Class<Character> type1 = Character.TYPE;
        System.out.println(type);
    }

類載入

分類

靜態載入:編譯時載入相關的類,如果沒有該類就會報錯,依賴性很強

動態載入:執行時載入需要的類,如果執行時不用該類則不回載入,也不會報錯,降低了依賴性

先看看常規的靜態載入方法ClassLoad.java

package Sentiment.refelction;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Scanner;

public class ClassLoad {
    public static void main(String[] args) throws Exception {
        Scanner scanner = new Scanner(System.in);
        String key = scanner.next();
        switch (key){
            case "1":
                Dog dog = new Dog();
                dog.cry();
                break;
            case "2":
                System.out.println("ok");
                break;
            default:
                System.out.println("Do nothing!");
    }}
}

當編譯時,即使還沒有輸入key=1,也就是還沒有呼叫new Dog()就會報錯找不到該類

image-20220324111335291

而當使用動態載入,也就是反射機制時

package Sentiment.refelction;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Scanner;

public class ClassLoad {
    public static void main(String[] args) throws Exception {
        Scanner scanner = new Scanner(System.in);
        String key = scanner.next();
        switch (key){
        //靜態載入
            case "1":
                //Dog dog = new Dog();
                //dog.cry();
                //break;
       //反射動態載入
            case "2":
                Class c1 = Class.forName("Person"); 
                Object o = c1.newInstance();
                Method method = c1.getMethod("hi");
                method.invoke(o);
                System.out.println("ok");
                break;
            default:
                System.out.println("Do nothing!");

    }}
}

在沒有呼叫Person類和hi方法的情況下,可以直接執行

image-20220324111424482

當輸入3時會呼叫default方法,並不會載入Person類,只有在key=2需要載入Person類時,才會報錯

image-20220324114026260

類載入時機

  • 當建立物件時(new)                        //靜態載入
  • 當子類被載入時,父類也載入         //靜態載入
  • 呼叫子類中的靜態成員時******         //靜態載入**
  • 透過反射******        //動態載入**

透過反射獲取類的結構資訊

java.lang.Class類API

  • getName:獲取全類名
  • getSimpleName:獲取簡單類名
  • getFields:獲取所有pubulic修飾的屬性,包括本類以及父類的
  • getDeclaredFields:獲取本類中所有屬性
  • getMethods:獲取所有public修飾的方法,包含本類以及父類的(父類包括Object類)
  • getDeclaredMethods:獲取本類中的所有方法
  • getConstrctors:獲取所有本類的public修飾的構造器
  • getDeclaredConstructors:獲取本類中的所有構造器
  • getPackage:以Package形式返回包資訊
  • getSuperClass:以Class形式返回父類資訊
  • getInterfaces:以Class[]形式返回介面資訊
  • getAnnotations:以Annotation[] 形式返回註解資訊

上述方法應用例項:ReflectionUtils.java

package Sentiment.refelction;

import java.lang.annotation.Annotation;
import java.lang.annotation.Documented;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;

public class ReflectionUtils {
    public static void main(String[] args) throws ClassNotFoundException {
        new ReflectionUtils().api();
    }
    public  void api() throws ClassNotFoundException {
        Class c1 = Class.forName("Sentiment.refelction.Person");//獲取Class物件
        //getName:獲取全類名
        System.out.println(c1.getName());
        //getSimpleName:獲取簡單類名
        System.out.println(c1.getSimpleName());
        //getFields:獲取所有pubulic修飾的屬性,包括本類以及父類的
        Field[] fields = c1.getFields();
        for (Field field : fields) {
            System.out.println("本類以及父類的屬性="+field.getName());
        }
        //getDeclaredFields:獲取本類中所有屬性
        Field[] declaredFields = c1.getDeclaredFields();
        for (Field declaredField : declaredFields) {
            System.out.println("本類中所有屬性="+declaredField.getName());
        }
        //getMethods:獲取所有public修飾的方法,包含本類以及父類的(父類包括Object類)
        Method[] methods = c1.getMethods();
        for (Method method : methods) {
            System.out.println("本類以及父類的public方法="+method.getName());
        }
        //getDeclaredMethods:獲取本類中的所有方法
        Method[] declaredMethods = c1.getDeclaredMethods();
        for (Method declaredMethod : declaredMethods) {
            System.out.println("本類中的所有方法="+declaredMethod);
        }
        //getConstrctors:獲取所有本類的public修飾的構造器
        Constructor[] constructors = c1.getConstructors();
        for (Constructor constructor : constructors) {
            System.out.println("本類的public構造器="+constructor);
        }
        //getDeclaredConstructors:獲取本類中的所有構造器
        Constructor[] declaredConstructors = c1.getDeclaredConstructors();
        for (Constructor declaredConstructor : declaredConstructors) {
            System.out.println("本類中的所有構造器= "+declaredConstructor);
        }
        //getPackage:以Package形式返回包資訊
        System.out.println("包資訊"+c1.getPackage());
        //getSuperClass:以Class形式返回父類資訊
        System.out.println("父類的class物件= "+c1.getSuperclass());
        //getInterfaces:以Class[]形式返回介面資訊
        Class[] interfaces = c1.getInterfaces();
        for (Class anInterface : interfaces) {
            System.out.println("介面資訊= "+anInterface);
        }
        //getAnnotations:以Annotation[]形式返回註解資訊
        Annotation[] annotations = c1.getAnnotations();
        for (Annotation annotation : annotations) {
            System.out.println("註解資訊= "+annotation);
        }
    }
}
interface IA{

}
interface IB{

}
class B{
    public String hobby;
    public void hi(){

    }
    public B() {
    }
}
@Deprecated
class Person extends B implements IA,IB{
     //屬性
    public String name;
    protected int age;
    String job;
    private double sal;
    //方法
    public void m1(){

    }
    protected void m2(){

    }
    void m3(){

    }
    private void m4(){

    }
    //構造方法
    public Person() {
    }

    public Person(String name) {
        this.name = name;
    }
}

執行結果(各方法間用---分割)

Sentiment.refelction.Person
-----------------------------
Person
-----------------------------
本類以及父類的屬性=name
本類以及父類的屬性=hobby
-----------------------------
本類中所有屬性=name
本類中所有屬性=age
本類中所有屬性=job
本類中所有屬性=sal
-----------------------------
本類以及父類的public方法=m1
本類以及父類的public方法=hi
本類以及父類的public方法=wait
本類以及父類的public方法=wait
本類以及父類的public方法=wait
本類以及父類的public方法=equals
本類以及父類的public方法=toString
本類以及父類的public方法=hashCode
本類以及父類的public方法=getClass
本類以及父類的public方法=notify
本類以及父類的public方法=notifyAll
-----------------------------
本類中的所有方法=protected void Sentiment.refelction.Person.m2()
本類中的所有方法=void Sentiment.refelction.Person.m3()
本類中的所有方法=private void Sentiment.refelction.Person.m4()
本類中的所有方法=public void Sentiment.refelction.Person.m1()
-----------------------------
本類的public構造器=public Sentiment.refelction.Person()
本類的public構造器=public Sentiment.refelction.Person(java.lang.String)
-----------------------------
本類中的所有構造器= public Sentiment.refelction.Person()
本類中的所有構造器= public Sentiment.refelction.Person(java.lang.String)
-----------------------------
包資訊package Sentiment.refelction
-----------------------------
父類的class物件= class Sentiment.refelction.B
-----------------------------
介面資訊= interface Sentiment.refelction.IA
介面資訊= interface Sentiment.refelction.IB
-----------------------------
註解資訊= @java.lang.Deprecated()
-----------------------------

java.lang.feflect.Field類API

  • getModifiers:以int形式返回修飾符(預設修飾符—>0,public—>1,priva—>2,protected—>4,static—>8,final—>16。若為混合型別則相加計算 例:public+static = 1+8 = 9)
  • getType:以Class形式返回型別
  • getName:返回屬性名

java.lang.reflect.Method類API

  • getModifiers:以int形式返回修飾符
  • getReturnType:以Class形式獲取返回型別
  • getName:返回方法名
  • getParameterTypes:以Class[]返回引數型別陣列(即形參型別)

java.lang.reflect.Constructor類API

  • getModifiers:以int形式返回修飾符
  • getName:返回方法名
  • getParameterTypes:以Class[]返回引數型別陣列

上述三類API例項程式碼:ReflectionUtils02.java

package Sentiment.refelction;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;

public class ReflectionUtils02 {
    public static void main(String[] args) throws ClassNotFoundException {
        new ReflectionUtils02().api2();
    }
    public void api2() throws ClassNotFoundException {
        Class c1 = Class.forName("Sentiment.refelction.Student");//獲取Class物件
        System.out.println("------------------------------");
        System.out.println("java.lang.feflect.Field類API");
        System.out.println("------------------------------");
        //getDeclaredFields:獲取本類中所有屬性
        Field[] declaredFields = c1.getDeclaredFields();
        for (Field declaredField : declaredFields) {
            System.out.println("本類中所有屬性="+declaredField.getName()+" 該類的屬性值="+declaredField.getModifiers()+" 型別是="+declaredField.getType());
        }
        System.out.println("------------------------------");
        System.out.println("java.lang.reflect.Method類API");
        System.out.println("------------------------------");
        //getDeclaredMethods:獲取本類中的所有方法
        Method[] declaredMethods = c1.getDeclaredMethods();
        for (Method declaredMethod : declaredMethods) {
            System.out.println("本類中的所有方法="+declaredMethod.getName()+" 該方法的屬性值="+declaredMethod.getModifiers()+" 該方法的返回型別="+declaredMethod.getReturnType());
        //方法的形參型別
            Class[] parameterTypes = declaredMethod.getParameterTypes();
            for (Class parameterType : parameterTypes) {
                System.out.println("形參型別= "+parameterType);
            }
        }
        System.out.println("------------------------------");
        System.out.println("java.lang.reflect.Constructor類API");
        System.out.println("------------------------------");
        //getDeclaredConstructors:獲取本類中的所有構造器
        Constructor[] declaredConstructors = c1.getDeclaredConstructors();
        for (Constructor declaredConstructor : declaredConstructors) {
            System.out.println("本類中的所有構造器= "+declaredConstructor.getName()+" 該構造器的屬性值= "+declaredConstructor.getModifiers());
            Class[] parameterTypes = declaredConstructor.getParameterTypes();
            for (Class parameterType : parameterTypes) {
                System.out.println("形參型別= "+parameterType);
            }
        }


}}
 class Student {
    //屬性
    int age;
    public String name;
    private String grade;
    protected static double score;
    //方法
     public void m1(int age ,String name,double score){

     }
     protected String m2(){
        return null;
     }
     void m3(){

     }
     private void m4(){

     }
    //構造方法

     Student() {
     }

     public Student(int age) {
         this.age = age;
     }

     private Student(int age, String name, String grade) {
         this.age = age;
         this.name = name;
         this.grade = grade;
     }
 }

執行結果(以---做各類分割)

反射爆破

反射建立物件

  • 透過public的無參構造器建立例項
    Object o = c3.newInstance();
  • 透過pulic的有參構造建立例項
    Constructor constructor = c3.getConstructor(String.class); //先得到構造器
    Object tana = constructor.newInstance("tana");             //建立例項,傳入實參
  • 透過非public的有參構造器建立物件
    setAccessible爆破
    Constructor declaredConstructor = c3.getDeclaredConstructor(int.class,String.class);  //先得到構造器
    declaredConstructor.setAccessible(true);                            //爆破訪問private構造器/方法/屬性
    Object mumu = declaredConstructor.newInstance(100, "mumu");         //建立例項,傳入實參

例項程式碼:ReflectionCreate.java

package Sentiment.refelction;

import java.lang.reflect.Constructor;

public class ReflectionCreate {
    public static void main(String[] args) throws Exception {
        //獲取類的Class物件
        Class<?> c3 = Class.forName("Sentiment.refelction.User");
        //透過public的無參構造器建立例項
        Object o = c3.newInstance();
        System.out.println(o);
        //透過pulic的有參構造建立例項
        Constructor constructor = c3.getConstructor(String.class);
        Object tana = constructor.newInstance("tana");
        System.out.println("tana = "+tana);
        //透過非public的有參構造器建立物件
        Constructor<?> declaredConstructor = c3.getDeclaredConstructor(int.class,String.class);
        declaredConstructor.setAccessible(true);
        Object mumu = declaredConstructor.newInstance(100, "mumu");;
        System.out.println("mumu = "+mumu);
    }
}
class User{
    //屬性
    private int age=10;
    private String name="Sentiment";
    //構造方法
    public User() {
    }

    public User(String name) {
        this.name = name;
    }

    private User(int age, String name) {
        this.age = age;
        this.name = name;
    }

    public String toString() {
        return "User{" + "age=" + age + ", name='" + name + '\'' + '}';
    }
}

執行結果

User{age=10, name='Sentiment'}
tana = User{age=10, name='tana'}
mumu = User{age=100, name='mumu'}

反射訪問類成員

  • 獲取public屬性

    Field age = c4.getField("age");          //age為屬性名
    age.set(o,100);                          //修改屬性值;o為物件例項
    System.out.println(age.get(o));
    • 獲取屬性:Class類物件.getField("屬性值");
    • 修改屬性值:屬性.set(o,值);
    • 輸出屬性值:屬性.get(o);
  • 獲取private屬性

    Field name = c4.getDeclaredField("name");   //name為屬性名
    name.setAccessible(true);                   //爆破
    name.set(o,"tana");                         //修改屬性值,o為物件例項
    System.out.println(name.get(null));         //static修飾的物件,也可以用null代替
    • 獲取屬性:Class類物件.getDeclaredField("屬性值");****
    • 爆破:屬性.setAccessible(true);

例項程式碼:ReflectionCreate02.java

package Sentiment.refelction;

import java.lang.reflect.Field;

public class ReflectionCreate02 {
    public static void main(String[] args) throws Exception{
        Class c4 = Class.forName("Sentiment.refelction.human");
        Object o = c4.newInstance();
        //獲取public屬性
        Field age = c4.getField("age");
        age.set(o,100);                          //修改屬性值
        System.out.println(age.get(o));
        //獲取private屬性
        Field name = c4.getDeclaredField("name");
        name.setAccessible(true);
        name.set(o,"tana");                     //修改屬性值
        System.out.println(name.get(null));
    }
}
class human{
    //屬性
    public int age=10;
    private static String name ="Sentiment";
    //構造器
    public human() {
    }

    @Override
    public String toString() {
        return "human{" + "age=" + age +", name"+name+'}';
    }
}

執行結果

100
tana

反射呼叫方法

  • 呼叫public方法

    Method say1 = c5.getMethod("say1", String.class);       //say1為String型別的方法
    say1.invoke(o,"Sentiment");
    • 獲取方法:Class類物件.getMethod("方法名", 方法型別.class);;
    • 呼叫方法:物件.invoke(例項化物件,"實參值");
  • 呼叫private方法

    Method say2 = c5.getDeclaredMethod("say2", int.class, String.class, char.class);    //say2方法及其型別
    say2.setAccessible(true);
    System.out.println(say2.invoke(o,10,"tana",'M'));
    • 獲取方法:Class類物件.getDeclaredMethod("方法名", 方法型別.class);;
    • 呼叫方法:物件.invoke(例項化物件,"實參值");
    • 爆破:method.setAccessible(true);

例項程式碼:ReflectionCreate03.java

package Sentiment.refelction;

import java.lang.reflect.Method;

public class ReflectionCreate03 {
    public static void main(String[] args) throws Exception{
        Class c5 = Class.forName("Sentiment.refelction.man");
        Object o = c5.newInstance();
        //呼叫public方法
        Method say1 = c5.getMethod("say1", String.class);
        say1.invoke(o,"Sentiment");
        //呼叫private方法
        Method say2 = c5.getDeclaredMethod("say2", int.class, String.class, char.class);
        say2.setAccessible(true);
        System.out.println(say2.invoke(o,10,"tana",'M'));
        System.out.println(say2.invoke(null,20,"mumu",'M'));    //靜態方法可以用null代替例項物件

    }
}
class man{
    //屬性
    public int age;
    private static String name;
    //構造方法
    public man() {
    }
    //方法
    public void say1(String a){
        System.out.println("this is =>"+a);
    }
    private static String say2(int a,String b, char c){
        return a+" "+b+" "+c;
    }

}

反射練習

Work1

  • 定義個Test類,其中定義私有屬性name,賦值為"xxxxxx"
  • Test類中建立公有方法getName()內容為return name
  • 建立Test的Class類,並獲得私有屬性name,修改私有屬性name的值,並呼叫getName()方法輸出name的值

參考

Work1.java

package Sentiment.refelction;

import java.lang.reflect.Field;
import java.lang.reflect.Method;

public class Work1 {
    public static void main(String[] args) throws Exception{
        Class c1 = Class.forName("Sentiment.refelction.Test");
        Object o = c1.newInstance();
        Field name = c1.getDeclaredField("name");
        name.setAccessible(true);
        name.set(o,"tana");
        Method getName = c1.getMethod("getName");
        System.out.println(getName.invoke(o));

    }
}
class Test{
    private String name = "Sentiment";
    public String getName(){
        return name;
    }

}

Work2

  • 獲取java.io.File的class物件,並輸出該類的所有構造器方法
  • 透過newInstance建立File物件,在自己電腦中建立個a.txt

參考

Work2.java

package Sentiment.refelction;

import java.io.File;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;

public class Work2 {
    public static void main(String[] args) throws Exception{
        Class c2 = Class.forName("java.io.File");
        Constructor[] c = c2.getDeclaredConstructors();
        for (Constructor Constructor : c) {
            System.out.println(Constructor);
        }
        //獲取構造器public java.io.File(java.lang.String)
        Constructor declaredConstructor = c2.getDeclaredConstructor(String.class);
        String path="D:\\a.txt";
        //例項化類
        Object path1 = declaredConstructor.newInstance(path);
        //獲取createNewFile方法
        Method createNewFile = c2.getMethod("createNewFile");
        createNewFile.invoke(path1);
        System.out.println(path1.getClass());
        System.out.println("建立檔案成功:"+path);
    }
}


相關文章