?
反射机制是指在运行时动态地获取类的信息,并能够通过这些信息对类的对象进行操作。Java中的反射机制包括获取类信息、获取成员信息、创建对象、调用方法等操作。通过反射机制,我们可以在运行时动态地了解类的结构、属性和方法等信息,从而实现对类的动态操作。通俗来讲,实例化号对象之后,反过来获取Class对象(一个类只有一个Class对象),这个对象包含了完整的类的结构信息,这个对象就像一个镜子,通过这个镜子看到类的结构,所以就就要反射。
上面介绍反射机制的时候,多次提到动态,这也是反射的一个重要存在的意义。反射的动态性体现在可以在运行时根据需要动态地获取和操作类的信息,使得程序更加灵活、可扩展和可维护。比如:
对于第一次听到这个反射可以动态获取对象,是有点抽象的,包括我本人,可以这样通俗理解: 传统如果实例化一个类的对象,常规是使用new操作符,但这样就意味着创建的对象是固定的,要修改成别的就需要更改源代码。比如:
Person person = new Person();
而反射则可以通过Class实例在运行时实例化对象。如果要修改实例化的对象只需要修改配置文件就行了,极大地增加了程序灵活性,避免修改代码然后重新编译。比如上面获取对象:
???????Class aClasss = Class.forName("com.meeting.bishi2.Peason");
这样就可以将“com.meeting.bishi2.Peason”放到配置文件,如果要改创建其他类,就可以直接修改配置文件,程序都不用重新启动。
这就是反射动态的体现。
Java中实现反射机制的常用API包括:
反射基本使用主要通过以下三部曲进行操作:
a.已知具体类,通过类的class属性获取,这个方法最安全可靠,程序性能最高
Class pclass = Peason.class;
b.已知某个类的实例,已经实例化了,调用该实例的getClass方法获取class对象
Class class = peason.getClass();
c.通过全类名,用Class类的静态方法forNema()获取,之后还能通过newInstance调用无参构造器去实例化一个对象
Class aClasss = Class.forName("com.meeting.bishi2.Peason");
以上三种反射获取的都是通过Class对象,他们的hashcode都是一样的。
获取Class类对象之后就可以调用对应的方法,比如获取类方法,属性等等。
实例说明,比如Person类中有getAll()方法,
public void addAll(){
}
可以通过反射获取该方法:
Class c3 = Class.forName("com.meeting.bishi2.Peason");
Method add = c3.getMethod("addAll");
System.out.println(add);
可以正确获取到这个getAll方法
上面获取到方法之后,接下来就可以通过反射调用该方法进行执行了。格式如下:
Method method= 类.getMethod(方法名);
method.invoke(实例对象名, 参数....);
或者
Method.invoke(实例对象名, 方法, 参数....);
安装格式,运用反射调用addAll方法如下:
Class c3 = Class.forName("com.meeting.bishi2.Peason");
Method add = c3.getMethod("addAll");
add.invoke(c3);
但是运行结果报错,通过报错提示也可以看到,对象需要被实例
所以invoke的对象必须先实现,可以调用 c3.newInstance() 实例:
Method add = c3.getMethod("addAll");
add.invoke(c3.newInstance());
最终可以真确调用addAll方法,运行结果如下,
1)spring底层创建对象,其实spring框架初始化bean,也是运用反射的,大致如下
Class c4 = Class.forName("com.meeting.bishi2.Peason");
// 1)通过newInstance调用无参构造器去实例化一个对象。类必须包含有无参构造器
Peason person3 = (Peason) c4.newInstance();
System.out.println(person3);
// 2)通过构造器创建对象,指定构造器创建对象
Constructor constructor = c4.getConstructor(String.class, String.class);
Peason person4 = (Peason) constructor.newInstance("aaa","123");
System.out.println(person4);
2)不同类型的集合进行复制,比如将List数据拷贝到A仍然有List
// 利用反射,不用关心类型,内部直接调用方法
List<String> numbers = new ArrayList<String>();
numbers.add("1");
numbers.add("2");
numbers.add("3");
ArrayList<Integer> integers = new ArrayList<Integer>();
Method addMethod = integers.getClass().getMethod("add", Object.class);
for (String number : numbers) {
// 给integers这个对象invoke,addMethod方法执行,入参是number
addMethod.invoke(integers,number);
}
System.out.println(integers);
反射可以能在运行时获取类指定信息,可以增加程序灵活性。在框架中就大量通过反射来增加程序灵活性,避免程序写死在源代码中。但是在使用中也是要注意的,或者说反射也有缺点:
?
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。