目录
1.2.2.1 Class类的newInstance()方法
1.2.2.2 Constructor类的newInstance()方法
1.1 概述
Java反射机制是指在运行状态中,对于任意一个类,都能知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法,修改它的任意属性;这种动态获取的信息以及动态调用对象成员的功能称为Java语言的反射机制。
为什么需要反射机制?比如超市经常推出打折活动,由于每次促销的商品不同,策略不同,导致程序需要经常变动,但能否在不修改原代码的基础上进行功能扩充呢?首先定义一个接口Discounter,这个接口中有一个公开的抽象方法discount(int price),传入的参数为原有商品的单价,所有基础接口Discounter的类都拥有打折的功能。接着写一个配置文件,这个文件中记录了有什么打着策略,然后让程序读取整个配置文件,列出打着策略列表让用户选择,如果再新增一个策略只需要写一个类继承Discounter接口,然后在配置文件中增加一条记录就可以了。但配置文件记录的只是类的全类名,要根据这个类名字符串来获取类的实例,Java反射机制提供了技术支撑。
上面的例子只是一个简单的应有,类似于设计模式中的策略模式。在Java的其他领域(如信息获取、动态代理、动态执行方法等),反射也起着重要的作用。反射机制能让程序更加灵活动态,Java对反射提供支持的类主要包括Class类,java.lang.reflect类库。架构如下图所示:
1.2 深入反射
下面通过一个简单的例子深入探索反射机制,在例运行的过程中,获取一个字符串practice.Chapter4.Section1.Teacher,并被告知这个字符串表示一个类,而且继承了抽象的Person类
public abstract class Person {
public abstract String toString();
}
public class Teacher extends Person{
public String position;
private int salary;
public void speak(String message){
System.out.println("Speak: "+message);
}
@Override
public String toString(){
return "[Position:"+position+"Salary:"+salary+"]";
}
private int getSalary(){
return this.salary;
}
}
要求:
- 显示的将这个类载入内存
- 实例化这个类
- 执行方法speak(String message)
- 修改属性position
- 修改受保护属性salary,以及执行私有方法getSalary()。
这个例子只获取了一个字符串要对这个字符串进行以上操作,该如何操作?
1.2.1 显示加载指定类
Java的Class类提供了显示加载的方法forName(String name)
public class Bootstrap {
public static String className="practice.Chapter4.Section1.Teacher";
public static void main(String[] args) {
try {
System.out.println("开始加载类");
Class clazz=Class.forName(className);
System.out.println("类加载完成");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
}
开始加载类
类加载完成
此例定义了一个静态字符串className,在main()函数中显示的加载了指定的类Teacher,并将加载后的该类的类型信息记录在clazz属性中,当找不到指定的类时,会抛出异常,指定类的类名必须为全路径类名,包括完整的包名和类文件名。