文章目录
Class对象可以获得该类里的方法(由Method对象表示)、构造器(由Constructor对象表示)、Field(由 Field 对象表示),这 3个类都位于java.lang.reflect 包下,并实现了java.lang.reflect.Member 接口。程序可以通过Method 对象来执行对应的方法,通过Constructor对象来调用对应的构造器创建实例,能通过Field对象直接访问并修改对象的属性值。
通过反射来生成对象有如下两种方式。
- 使用Class对象的newInstance()方法来创建该Class对象对应类的实例,这种方式要求该 Class 对象的对应类有默认构造器,而执行 newInstance()方法时实际上是利用默认构造器来创建该类的实例
- 先使用 Class 对象获取指定的 Constructor 对象,再调用 Constructor 对象的newInstance()方法来创建该Class对象对应类的实例。通过这种方式可以选择使用指定的构造器来创建实例。
通过第一种方式来创建对象是比较常见的情形,因为在很多Java EE框架中都需要根据配置文件信息来创建Java对象,从配置文件读取的只是某个类的字符串类名,程序需要根据该字符串来创建对应的实例,就必须使用反射。
public class Person {
//私有的成员变量
private String name;
//默认的
int age;
//公共的
public String address;
public Person() {
super();
}
//没有用public修饰的构造方法
Person(int age, String address) {
super();
this.age = age;
this.address = address;
}
//私有的构造方法
private Person(String name) {
super();
this.name = name;
this.age = age;
}
//公共的构造方法
public Person(String name, int age, String address) {
super();
this.name = name;
this.age = age;
this.address = address;
}
public void show() {
System.out.println("show");
}
public void method(String s) {
System.out.println("method"+s);
}
public String getString(String s,int i) {
return s+"....."+i;
}
public void function() {
System.out.println("function");
}
@Override
public String toString() {
return "Person [name=" + name + ", age=" + age + ", address=" + address + "]";
}
}
1. 利用默认构造器来创建对象
public class Main {
public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException {
Class clazz = Class.forName("com.example.redislock.reflect.Person");
// 使用默认的构造方法创建对象
Object object = clazz.newInstance();
// Person [name=null, age=0, address=null]
if(object instanceof Person){
Person person = (Person) object;
System.out.println(person);
}
}
}
2. 使用带参构造器创建对象
如果不想利用默认构造器来创建Java对象,而想利用指定的构造器来创建Java对象,则需要利用Constructor对象,每个Constructor对应一个构造器。为了利用指定的构造器来创建Java对象,需要如下3个步骤。
(1)获取该类的Class对象。
(2)利用Class对象的getConstructor()方法来获取指定的构造器。
(3)调用Constructor的newInstance()方法来创建Java对象。
public class Main {
public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException {
Class clazz = Class.forName("com.example.redislock.reflect.Person");
// Constructor类,也是java.lang.reflect包下的类
// 获取代用3个参数,类型分别为int和String的构造器
Constructor constructor = clazz.getConstructor(String.class,int.class, String.class);
// 使用带有3个参数的构造方法创建对象
Object obj = constructor.newInstance("zhangsan", 18 , "安徽省");
if(obj instanceof Person){
Person person = (Person) obj;
// Person [name=zhangsan, age=18, address=安徽省]
System.out.println(person);
}
}
}
当调用Constructor对象的newInstance()方法时通常需要传入参数,因为调用Constructor的newInstance()方法实际上等于调用它对应的构造器,传给newInstance()方法的参数将作为对应构造器的参数。
public class Main {
public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException {
Class c = Class.forName("com.example.redislock.reflect.Person");
//获取无参构造函数
Constructor con = c.getDeclaredConstructor();
//通过无参Constructor对象创建Person类的新实例
// T newInstance(Object... initargs)
Object obj = con.newInstance();
System.out.println(obj);
//获取带参构造函数对象
Constructor con1 = c.getDeclaredConstructor(String.class,int.class,String.class);
//通过带参构造函数对象
Object obj1 = con1.newInstance("林青霞",23,"北京");
System.out.println(obj1);
//获取私有的带参构造函数
Constructor con2 = c.getDeclaredConstructor(int.class,String.class);
//通过带参构造函数创建对象
//打破封装,暴力访问
con2.setAccessible(true);
Object o = con2.newInstance( 23,"安徽省");
System.out.println(o);
}
}
通常没有必要使用反射来创建该对象,毕竟通过反射创建对象时性能要稍低一些。实际上,只有当程序需要动态创建某个类的对象时才会考虑使用反射,通常在开发通用性比较广的框架、基础平台时可能会大量使用反射。
通过Class类对象获取对应类的构造方法的四种情况:
3. getConstructors() - 获取所有的公共构造方法
public class Main {
public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException {
Class clazz = Class.forName("com.example.redislock.reflect.Person");
// 获取所有的public修饰的构造方法
Constructor[] constructors = clazz.getConstructors();
for (Constructor constructor : constructors) {
System.out.println(constructor);
}
}
}
4. getDeclaredConstructors() - 获取所有构造方法
public class Main {
public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException {
Class clazz = Class.forName("com.example.redislock.reflect.Person");
// 获取所有的构造方法
Constructor[] constructors = clazz.getDeclaredConstructors();
for (Constructor constructor : constructors) {
System.out.println(constructor);
}
}
}
5. getConstructor(Class<?>… parameterTypes) - 获取指定公共构造方法
public class Main {
public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException {
Class clazz = Class.forName("com.example.redislock.reflect.Person");
// 获取指定公共构造方法
Constructor constructor = clazz.getConstructor(String.class,int.class, String.class);
System.out.println(constructor);
}
}
6. getDeclaredConstructor(Class<?>… parameterTypes) - 获取指定构造方法
public class Main {
public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException {
Class clazz = Class.forName("com.example.redislock.reflect.Person");
// // 获取指定构造方法
Constructor constructor = clazz.getDeclaredConstructor(int.class, String.class);
System.out.println(constructor);
}
}