实现步骤:
- 获取类的class文件对象(反射(一)中的任意一种方式)
- 使用class文件对象中的方法getConstructor / getConstructors获取类中的构造方法Constructor
- 使用构造方法Constructor类中的方法newInstance实例化对象(创建对象)
现在拆分开详细描述:
第一步:获取类的class文件对象
详见:https://blog.csdn.net/qq_45083975/article/details/91959244
第二步:使用class文件对象中的方法getConstructor / getConstructors获取类中的构造方法Constructor
- Constructor<?>[] getConstructors() 获取类中所有公共构造方法。
- Constructor<?>[] getDeclaredConstructors() 获取类声明的(私有,默认,受保护,公共)所有构造方法。
- Constructor getConstructor(Class<?>… parameterTypes) 获取类的指定公共构造方法。
- Constructor getDeclaredConstructor(Class<?>… parameterTypes) 获取类的指定(私有,默认,受保护,公共)构造方法。
参数说明:
Class<?>… parameterTypes:传递构造方法参数的class文件对象,
比如:int.class,double.class,String.class,Student.class
可以理解为是可变参数:参数可以是任意个(不传,1个,多个)
第三步:使用构造方法Constructor类中的方法newInstance实例化对象(创建对象)
java.lang.reflect.Constructor类中的方法
Constructor T newInstance(Object… initargs) 用于实例化对象
参数:
Object… initargs:调用构造方法创建对象传递的实际参数 比如:张三 18
返回值:
T:返回的就是创建好的对象,类型使用Object
那么假如需要获取私有的构造方法:private Person(String name, int age)呢?
私有的构造方法我们没有权限运行,运行私有的构造方法,会抛出IllegalAccessException:非法访问异常
解决(了解):
使用Constructor父类AccessibleObject里边的方法
java.lang.reflect.AccessibleObject类中的方法
Constructor void setAccessible(boolean flag) 将此对象的 accessible 标志设置为指示的布尔值。
值为 true 则指示反射的对象在使用时应该取消 Java 语言访问检查。
值为 false 则指示反射的对象应该实施 Java 语言访问检查。
(上面的这种获取私有的构造方法的方式属于暴力反射,不推荐使用,因为它破坏了类的封装性)
下面我们举例说明:(使用了@Test,可换为main方法)
package com.ccc.demo02Reflect;
import org.junit.Test;
import java.lang.reflect.Constructor;
public class Demo02Reflect {
@Test
public void demo01() throws Exception {
//1.获取类的class文件对象(手术刀)
Class clazz = Class.forName("com.ccc.demo03domain.Person");
//2.使用class文件对象中的方法getConstructor/getConstructors获取类中的构造方法Constructor
/*
Constructor<?>[] getConstructors() 获取类中所有公共构造方法。
Constructor<?>[] getDeclaredConstructors()
获取类声明的(私有,默认,受保护,公共)所有构造方法。
*/
Constructor[] cons = clazz.getConstructors();
for(Constructor con : cons){
System.out.println(con);
}
System.out.println("===============================");
Constructor[] declaredCons = clazz.getDeclaredConstructors();
for (Constructor declaredCon : declaredCons){
System.out.println(declaredCon);
}
System.out.println("===============================");
/*
Constructor<T> getConstructor(Class<?>... parameterTypes)
获取类的指定公共构造方法。
Constructor<T> getDeclaredConstructor(Class<?>... parameterTypes)
获取类的指定(私有,默认,受保护,公共)构造方法。
参数:
Class<?>... parameterTypes:传递构造方法参数的class文件对象
比如:int.class,double.class,String.class,Student.class
可变参数:参数可以是任意个(不传,1个,多个)
*/
//获取 public Person()
Constructor con1 = clazz.getConstructor();
System.out.println(con1); //输出 public com.ccc.demo03domain.Person()
System.out.println("===============================");
//获取 public Person(String name, int age, String sex)
Constructor con2 = clazz.getConstructor(String.class, int.class, String.class);
System.out.println(con2);
//输出 public com.ccc.demo03domain.Person(java.lang.String,int,java.lang.String)
System.out.println("===============================");
//获取 private Person(String name, int age)
Constructor con3 = clazz.getDeclaredConstructor(String.class, int.class);
System.out.println(con3);
//输出 private com.itheima.demo03domain.Person(java.lang.String,int)
System.out.println("===============================");
//3.使用构造方法Constructor类中的方法newInstance实例化对象(创建对象)
//获取 public Person()
Object obj1 = con1.newInstance();//就相当于 new Person();
System.out.println(obj1); //输出 Person{name='null', age=0, sex='null'}
System.out.println("===============================");
//获取 public Person(String name, int age, String sex)
Object obj2 = con2.newInstance("张三", 18, "男");
//上面这一句就相当于 new Person("张三", 18, "男");
System.out.println(obj2); //输出 Person{name='张三', age=18, sex='男'}
System.out.println("===============================");
/*
获取 private Person(String name, int age)
私有的构造方法我们没有权限运行,运行私有的构造方法,
会抛出IllegalAccessException:非法访问异常
解决:
使用Constructor父类AccessibleObject里边的方法
java.lang.reflect.AccessibleObject
void setAccessible(boolean flag)
将此对象的 accessible 标志设置为指示的布尔值。
值为 true 则指示反射的对象在使用时应该取消 Java 语言访问检查。
值为 false 则指示反射的对象应该实施 Java 语言访问检查。
注意:
暴力反射不推荐,破坏了类的封装性
*/
//获取 private Person(String name, int age)
con3.setAccessible(true);//取消访问的权限检查-->暴力反射
Object obj3 = con3.newInstance("李四", 20);
System.out.println(obj3); //输出 Person{name='李四', age=20, sex='null'}
}
}
Person类:
package com.ccc.demo03domain;
public class Person {
private String name;
private int age;
private String sex;
public Person() {
System.out.println("Person类的空参数构造方法");
}
public Person(String name, int age, String sex) {
this.name = name;
this.age = age;
this.sex = sex;
System.out.println("Person类的全参数构造方法");
}
private Person(String name, int age) {
this.name = name;
this.age = age;
System.out.println("Person类的私有构造方法");
}
//私有方法
private void method(){
System.out.println("Person类的私有方法");
}
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age=" + age +
", sex='" + sex + '\'' +
'}';
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
}