ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

反射机制

2022-05-20 20:03:02  阅读:150  来源: 互联网

标签:反射 String System Person println 机制 public out


指在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法,对于任意一个对象,都能调用它的任意一个方法.这种动态获取信息,以及动态调用对象方法的功能叫java语言的反射机制.

 

反射机制常用的类:

Java.lang.Class;  //代表一个类

Java.lang.reflect.Constructor;  //代表类的构造器

Java.lang.reflect.Field;  //代表类的成员变量

Java.lang.reflect.Method;  //代表类的方法

Java.lang.reflect.Modifier;

 

反射的基本使用:

不使用反射的处理:





 1 public class Person {
 2     private String name;
 3     public int age;
 4 
 5     public String getName() {
 6         return name;
 7     }
 8 
 9     public void setName(String name) {
10         this.name = name;
11     }
12 
13     public int getAge() {
14         return age;
15     }
16 
17     public void setAge(int age) {
18         this.age = age;
19     }
20 
21     public Person(String name, int age) {
22         this.name = name;
23         this.age = age;
24     }
25 
26     private Person(String name) {
27         this.name = name;
28     }
29     public Person(){
30 
31     }
32 
33     @Override
34     public String toString() {
35         return "Person{" +
36                 "name='" + name + '\'' +
37                 ", age=" + age +
38                 '}';
39     }
40     public void show(){
41         System.out.println("hello");
42     }
43     private String showNation(String nation){
44         System.out.println("中国");
45         return nation;
46     }
47 }

 




 

使用反射机制:

 1 import java.lang.reflect.Constructor;
 2 import java.lang.reflect.Field;
 3 import java.lang.reflect.Method;
 4 
 5 public class ReflectTest {
 6     /**
 7      * 不使用反射的情况
 8      */
 9     @Test
10     public void test01(){
11         Person person = new Person("jack",20);
12         person.age=15;
13         System.out.println(person.toString());
14         person.show();
15         //在Person类的外部,不可以通过Person类的对象调用其内部私有的结构。
16         //比如:name、showNation以及私有的构造器。
17     }
18 
19     /**
20      * 使用反射的情况
21      */
22     @Test
23     public void test02() throws Exception {
24         //1.通过反射,创建Person类的对象
25         Class clazz = Person.class;
26         Constructor cons = clazz.getConstructor(String.class,int.class);
27         Object obj = cons.newInstance("john",21);
28         Person person = (Person) obj;
29         System.out.println(person.toString());
30         //2.通过反射,调用对象指定的属性和方法
31         //调用属性
32         Field age = clazz.getDeclaredField("age");
33         age.set(person,11);
34         System.out.println(person.toString());
35         //调用方法
36         Method show = clazz.getDeclaredMethod("show");
37         show.invoke(person);
38         System.out.println("============");
39         //通过反射,是可以调用Person类的私有结构的。比如:私有的构造器、方法、属性
40         //调用私有的构造器
41         Constructor constructor = clazz.getDeclaredConstructor(String.class);
42         constructor.setAccessible(true);
43         Person p = (Person) constructor.newInstance("kk");
44         System.out.println(p);
45         //调用私有的属性
46         Field name = clazz.getDeclaredField("name");
47         name.setAccessible(true);
48         name.set(p,"zz");
49         System.out.println(p);
50 
51         //调用私有的方法
52         Method showNation = clazz.getDeclaredMethod("showNation",String.class);
53         showNation.setAccessible(true);
54         String nation = (String) showNation.invoke(p,"china");
55 //        相当于String nation = p1.showNation("FaceBook")
56         System.out.println(nation);
57 
58     }
59 
60 }

 

 

 

理解Class类并获取Class实例

 

关于java.lang.Class类的理解

类的加载过程:
1.程序经过Javac.exe命令后,会生成一个或多个字节码文件(.class结尾)。接着我们使用java.exe命令对某个字节码文件进行解释运行。相当于将某个字节码文件加载到内存中。此过程就称为类的加载。加载到内存中的类,我们就称为运行时类,此运行时类,就作为Class的一个实例。
2.换句话说,Class的实例就对应着一个运行时类。
3.加载到内存中的运行时类,会缓存一定的个时间。在此时间内,我们可以通过不同的方式来获取此运行时类。

 

获取class实例的方式

 1 import org.junit.Test;
 2 
 3 import java.lang.annotation.ElementType;
 4 import java.lang.reflect.Constructor;
 5 import java.lang.reflect.Field;
 6 import java.lang.reflect.Method;
 7 
 8 public class ReflectionTest {
 9 
10     @Test
11     public void test3() throws ClassNotFoundException {
12         //方式一:调用运行时类的属性
13         Class c1 = Person.class;
14         System.out.println(c1);
15 
16         //方式二:通过运行时类的对象,调用getClass()
17         Person p1 = new Person();
18         Class c2 = p1.getClass();
19         System.out.println(c2);
20 
21         //方式三:调用Class的静态方法:forName(String classPath)
22         Class c3 = Class.forName("java.lang.String");
23         System.out.println(c3);
24 
25         System.out.println(c1 == c2);
26         System.out.println(c1 == c3);
27 
28         //方式四:使用类的加载器:ClassLoader  (了解)
29         ClassLoader classLoader = ReflectionTest.class.getClassLoader();
30         Class c4 = classLoader.loadClass("java.lang.String");
31         System.out.println(c4);
32 
33         System.out.println(c1 == c4);
34     }
35 }

 

 

 

哪些类型可以有Class对象

  1. class:外部类, 成员(成员内部类, 静态内部类), 局部内部类, 匿名内部类
  2. interface: 接口
  3. []:数组
  4. enum:枚举
  5. annotation:注解@interface
  6. primitive type:基本数据类型
  7. void

 

 

 使用ClassLoader加载配置文件

 1 import org.junit.Test;
 2 
 3 import java.io.FileInputStream;
 4 import java.io.InputStream;
 5 import java.util.Properties;
 6 
 7 public class PropertiesTest {
 8     @Test
 9     public void test01() throws Exception{
10         Properties properties = new Properties();
11         //读取配置文件的方式一,此时文件路径默认在当前的module下
12         //FileInputStream fileInputStream = new FileInputStream("jdbc.properties");
13         //FileInputStream fileInputStream = new FileInputStream("src/jdbc1.properties");
14         //properties.load(fileInputStream);
15 
16         //读取配置文件的方式2,此时文件路径默认识别为当前module下的src
17         ClassLoader classLoader = ClassLoadingTest.class.getClassLoader();
18         InputStream resourceAsStream = classLoader.getResourceAsStream("jdbc1.properties");
19         properties.load(resourceAsStream);
20 
21         String user = properties.getProperty("user");
22         String password = properties.getProperty("password");
23         System.out.println("user=:"+user+";passward:"+password);
24     }
25 }

 

 

 

通过Class对象,创建运行时类的对象,通过调用Class对象的newInstance()方法

 1 import org.junit.Test;
 2 import pers.chh3213.reflectionDemo.Person;
 3 
 4 public class NewInstanceTest {
 5 
 6     @Test
 7     public void test() throws Exception{
 8         Class<Person> clazz = Person.class;
 9         /**
10          * newInstance():调用此方法,创建对应的运行时类的对象。内部调用了运行时类的空参的构造器。
11          *
12          * 要想此方法正常的创建运行时类的对象,要求:
13          * 1.运行时类必须提供空参的构造器
14          * 2.空参的构造器的访问权限得够。通常,设置为public。
15          *
16          * 在javabean中要求提供一个public的空参构造器。原因:
17          * 1.便于通过反射,创建运行时类的对象
18          * 2.便于子类继承此运行时类时,默认调用super()时,保证父类有此构造器
19          */
20         Person obj = clazz.newInstance();
21         System.out.println(obj);
22     }
23 
24 }

 

 

反射机制的动态性体现

 

 1 import org.junit.Test;
 2 
 3 import java.util.Random;
 4 
 5 public class NewInstanceTest2 {
 6     @Test
 7     public void test2(){
 8         for (int i = 0; i < 100; i++) {
 9             int num = new Random().nextInt(3);
10             String classpath = "";
11             switch (num){
12                 case 0:
13                     classpath = "java.util.Date";
14                     break;
15                 case 1:
16                     classpath = "java.lang.Object";
17                     break;
18                 case 2:
19                     classpath = "pers.chh3213.reflectionDemo.Person";
20                     break;
21             }
22             try {
23                 Object obj = getInstance(classpath);
24                 System.out.println(obj);
25             }catch (Exception e){
26                 e.printStackTrace();
27             }
28         }
29 
30     }
31     /**
32      * 创建一个指定类的对象。
33      * classPath:指定类的全类名
34      *
35      * @param classPath
36      * @return
37      * @throws Exception
38      */
39     public Object getInstance(String classPath) throws Exception {
40         Class clazz =  Class.forName(classPath);
41         return clazz.newInstance();
42     }
43 }

 

 

具体创建哪个类的对象,直到运行时才能确定

 

 

 

 

 

 

 

 

 

 

 

 

参考博客:https://blog.csdn.net/weixin_42301220/article/details/122639224

标签:反射,String,System,Person,println,机制,public,out
来源: https://www.cnblogs.com/zyx9710/p/16293572.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有