java進階(41)--反射機制

Mrwhite86發表於2021-04-05

文件目錄:

一、反射機制的作用

二、反射機制相關類

三、獲取class的三種方式

四、通過反射例項化物件

五、通過讀屬性檔案例項化物件

六、通過反射機制訪問物件屬性

七、通過反射機制呼叫方法

---------------------------------------分割線:正文--------------------------------------------------------

一、反射機制的作用

1、通過java語言中反射機制可以操作位元組碼檔案

2、通過反射機制可以操作程式碼片段(class檔案)

 

二、反射機制相關類

1、對應的包:java.lang.reflect.*

2、有哪些重要的類:

java.lang.class --> 代表整個位元組碼檔案,程式碼一個型別,程式碼整個類

java.lang.reflect.Method --> 代表位元組碼中的方法位元組碼,程式碼類中構造方法

java.lang.reflect.Constructor --> 代表位元組碼中構造方法位元組碼,代表類中構造方法

java.lang.reflect.Field -->代表類中屬性

 

三、獲取class的三種方式

1、forName()

 1 package com.bk.java.Test41.reflect01;
 2 
 3 public class ReflectTest01 {
 4     public static void main(String[] args) throws ClassNotFoundException {
 5         Class c1=Class.forName("java.lang.String");
 6         Class c2=Class.forName("java.util.Date");
 7         Class c3=Class.forName("java.lang.Integer");
 8         System.out.println(c1);
 9         System.out.println(c2);
10         System.out.println(c3);
11     }
12 }

檢視執行結果:

class java.lang.String
class java.util.Date
class java.lang.Integer

 

2、getClass()

 1 package com.bk.java.Test41.reflect01;
 2 
 3 public class ReflectTest02 {
 4     public static void main(String[] args) throws ClassNotFoundException {
 5         String s="abc";
 6         Class c1=Class.forName("java.lang.String");
 7         Class x=s.getClass();
 8         //記憶體地址一致,都指向方法區中的位元組碼
 9         System.out.println(x==c1);
10     }
11 }

執行結果為true

 

3、.class屬性

 1 package com.bk.java.Test41.reflect01;
 2 
 3 public class ReflectTest03 {
 4     public static void main(String[] args) {
 5         String s="123";
 6         Class y=s.getClass();
 7         Class z=String.class;
 8         System.out.println(y==z);
 9     }
10 }

執行結果為true

 

四、通過反射例項化物件

 1 package com.bk.java.Test41.reflect01;
 2 
 3 public class ReflectTest04 {
 4     public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException {
 5         Class c=Class.forName("com.bk.java.Test41.reflect01.User");
 6         //必須保證User類包含無參構造的方法,呼叫User類的無參構造方法,完成例項物件的建立
 7         Object obj= c.newInstance();
 8         System.out.println(obj);
 9     }
10 }

檢視執行結果

呼叫了User類的無參構造方法
com.bk.java.Test41.reflect01.User@1b6d3586

 

五、通過讀屬性檔案例項化物件

1、通過i/o流讀取classinfo.properties

 配置檔案:

classinfo.properties:

className=com.bk.java.Test41.reflect01.User
 1 package com.bk.java.Test41.reflect01;
 2 
 3 import java.io.FileNotFoundException;
 4 import java.io.FileReader;
 5 import java.io.IOException;
 6 import java.util.Properties;
 7 
 8 public class ReflectTest05 {
 9     public static void main(String[] args) throws IOException, ClassNotFoundException, IllegalAccessException, InstantiationException {
10         //通過I/O流讀取classinfo.properties檔案
11         FileReader reader=new FileReader("src/com/bk/java/Test41/reflect01/classinfo.properties");
12         //建立屬性類物件
13         Properties pro=new Properties();
14         pro.load(reader);
15         //關閉流
16         reader.close();
17         //通過key獲取value
18         String className=pro.getProperty("className");
19         System.out.println(className);
20         //通過反射機制例項化物件
21         Class c=Class.forName(className);
22         Object obj=c.newInstance();
23         System.out.println(obj);
24     }
25 }

檢視執行結果:

com.bk.java.Test41.reflect01.User
呼叫了User類的無參構造方法
com.bk.java.Test41.reflect01.User@1b6d3586

修改配置檔案後再次呼叫檢視結果

className=java.util.Date
java.util.Date
Mon Apr 05 17:21:25 CST 2021

 

2、以流的形式直接返回

 1 package com.bk.java.Test41.reflect01;
 2 
 3 import java.io.FileNotFoundException;
 4 import java.io.FileReader;
 5 import java.io.IOException;
 6 import java.util.Properties;
 7 
 8 public class ReflectTest06 {
 9     public static void main(String[] args) throws IOException {
10         String path=Thread.currentThread().getContextClassLoader().getResource("com/bk/java/Test41/reflect01/classinfo.properties").getPath();
11         FileReader reader=new FileReader(path);
12         Properties pro=new Properties();
13         pro.load(reader);
14         reader.close();
15         //通過key獲取value
16         String className=pro.getProperty("className");
17         System.out.println(className);
18     }
19 }

檢視返回結果:返回結果同上

java.util.Date

改進程式碼如下:

package com.bk.java.Test41.reflect01;
import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;

public class ReflectTest07 {
    public static void main(String[] args) throws IOException {
        InputStream in=Thread.currentThread().getContextClassLoader().getResourceAsStream("com/bk/java/Test41/reflect01/classinfo.properties");
        Properties pro=new Properties();
        pro.load(in);
        in.close();
        //通過key獲取value
        String className=pro.getProperty("className");
        System.out.println(className);
    }
}

3、使用資源繫結器:

package com.bk.java.Test41.reflect01;

import java.util.ResourceBundle;

public class ResourceBundleTest {
    public static void main(String[] args) {
        ResourceBundle bundle=ResourceBundle.getBundle("com/bk/java/Test41/reflect01/classinfo");
        String className=bundle.getString("className");
        System.out.println(className);
    }
}

檢視執行結果:

java.util.Date

 

六、通過反射機制訪問物件屬性

建立一個Student類

 1 package com.bk.java.Test41.reflect02;
 2 
 3 public class Student {
 4     public int no;
 5     private String name;
 6     protected int age;
 7     boolean sex;
 8 
 9     public Student() {
10     }
11 
12     public int getNo() {
13         return no;
14     }
15 
16     public void setNo(int no) {
17         this.no = no;
18     }
19 
20     public String getName() {
21         return name;
22     }
23 
24     public void setName(String name) {
25         this.name = name;
26     }
27 
28     public int getAge() {
29         return age;
30     }
31 
32     public void setAge(int age) {
33         this.age = age;
34     }
35 
36     public boolean isSex() {
37         return sex;
38     }
39 
40     public void setSex(boolean sex) {
41         this.sex = sex;
42     }
43 }

通過反射機制訪問物件屬性

 1 package com.bk.java.Test41.reflect02;
 2 
 3 import java.lang.reflect.Field;
 4 
 5 public class ReflectTest01 {
 6     public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchFieldException {
 7         Class studentClass=Class.forName("com.bk.java.Test41.reflect02.Student");
 8         Object obj=studentClass.newInstance();
 9         //獲取no屬性通過屬性name
10         Field noField=studentClass.getDeclaredField("no");
11         //給obj物件的no屬性賦值
12         noField.set(obj,11111);
13         //讀取屬性的值
14         System.out.println(noField.get(obj));
15     }
16 }

檢視輸出結果

11111

 

七、通過反射機制呼叫方法

原始方法:

package com.bk.java.Test41.reflect03;

public class ReflectTest {
    public static void main(String[] args) {
        //原始方法呼叫UserSevice.login方法
        UserService userService=new UserService();
        boolean loginSuccess=userService.login("admin","123");
        System.out.println(loginSuccess?"登入成功":"登入失敗");
    }
}

通過反射機制呼叫:

 1 package com.bk.java.Test41.reflect03;
 2 
 3 import java.lang.reflect.InvocationTargetException;
 4 import java.lang.reflect.Method;
 5 
 6 public class ReflectTest {
 7     public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException {
 8 //        //原始方法呼叫UserSevice.login方法
 9 //        UserService userService=new UserService();
10 //        boolean loginSuccess=userService.login("admin","123");
11 //        System.out.println(loginSuccess?"登入成功":"登入失敗");
12         Class userServiceClass =Class.forName("com.bk.java.Test41.reflect03.UserService");
13         //建立例項物件
14         Object obj=userServiceClass.newInstance();
15         //獲取Method
16         Method loginMethod=userServiceClass.getDeclaredMethod("login", String.class, String.class);
17         //呼叫方法
18         Object retvalue=loginMethod.invoke(obj,"admin","123");
19         System.out.println(retvalue);
20     }
21 }

檢視執行結果:

true

相關文章