通过反射创建对象
- 方式一:调用类中的public修饰的无参构造器
- 方式二:调用类中的指定构造器
Class类相关方法
- newlnstance:调用类中的无参构造器,获取对应类的对象
- getConstructor(Class...clazz):根据参数列表,获取对应的public构造器对象
- getDecalaredConstructor(Class...clazz):根据参数列表,获取对应的所有构造器对象
Constructor类相关方法
- setAccessible:暴破
- newlnstance(Object...obj):调用构造器
通过反射创建对象—应用案例
/**
* 演示通过反射机制创建实例
*/
public class ReflectCreateInstance {
public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException, InvocationTargetException, NoSuchMethodException {
//1、先获取到User类的Class对象
Class<?> userClass = Class.forName("com.kuang.reflection.User");
//2、通过public的无参构造器创建实例
Object o = userClass.newInstance();
System.out.println(o);
//3、通过public的有参构造器创建实例
//先得到对应构造器对象,这里 constructor对象就是 public User(String name){this.name=name;}
Constructor<?> constructor = userClass.getConstructor(String.class);
//创建实例,并传入实参
Object m = constructor.newInstance("cjj");
System.out.println(m);
//4、通过非public的有参构造器创建实例
// 得到 private构造器对象
Constructor<?> declaredConstructor = userClass.getDeclaredConstructor(int.class, String.class);
//创建实例,使用爆破方法(暴力破解), 使用反射可以访问private构造器/方法/属性
declaredConstructor.setAccessible(true);
Object abc = declaredConstructor.newInstance(100, "abc");
System.out.println(abc);
}
}
class User{
private int age=10;
private String name="gyc";
public User(){ //public的无参构造器
}
public User(String name){//public的有参构造器
this.name=name;
}
private User(int age,String name){ //private有参构造器
this.name=name;
this.age=age;
}
@Override
public String toString() {
return "User{" +
"age=" + age +
", name='" + name + '\'' +
'}';
}
}
输出:
User{age=10, name='gyc'}
User{age=10, name='cjj'}
User{age=100, name='abc'}
通过反射访问类中的成员
访问属性
- 根据属性名获取Field对象:Field f = clazz对象.getDeclaredField(属性名);
- 暴破:f.setAccessible(true); //f 是Field
- 访问:f.set(o,值); syso(f.get(o)); //o表示对象
- 注意:如果是静态属性,则set和get中的参数o,可以写成null
反射操作属性—应用案例
/**
* 演示反射操作属性
*/
public class ReflectAccessProperty {
public static void main(String[] args) throws InstantiationException, IllegalAccessException, NoSuchFieldException {
//1、得到Student类对应的Class对象
Class<Student> studentClass = Student.class;
//2、创建对象
Student student = studentClass.newInstance();
System.out.println(student.getClass());
//3、通过反射得到age属性
Field age = studentClass.getField("age");
age.set(student,18);//通过反射来操作属性
System.out.println(student);
System.out.println(age.get(student));//返回age属性的值
//4、通过反射来操作name属性
Field name = studentClass.getDeclaredField("name");
//对name进行爆破
name.setAccessible(true);
name.set(student,"gyc");
//name.set(null,"gyc"); 也可以这样赋值,因为name是static属性,因此student可以写成null
System.out.println(student);
System.out.println(name.get(student)); //获取属性值
System.out.println(name.get(null));//获取属性值,要求name是static
}
}
class Student{
public int age;
private static String name ;
public Student() {//构造器
}
public String toString(){
return "Student [age=" + age + ",name=" +name + "]";
}
}
输出:
class com.kuang.reflection.Student
Student [age=18,name=null]
18
Student [age=18,name=gyc]
gyc
gyc
访问方法
- 根据方法名和参数列表获取Method方法对象:Method m = clazz.getDeclaredMethod(方法名,XX.class); //得到本类的所有方法
- 获取对象:Object o=clazz.newlnstance();
- 暴破:m.setAccessible(true);
- 访问:Object returnValue = m.invoke(o,实参列表); //o就是对象
- 注意:如果是静态方法,则invoke的参数o,可以写成null
反射调用方法—应用案例
/**
* 演示通过反射调用方法
*/
public class ReflectAccessMethod {
public static void main(String[] args) throws InstantiationException, IllegalAccessException, NoSuchMethodException, InvocationTargetException {
//1、得到Boss类对应的Class类对象
Class<?> bossClass = Boss.class;
//2、创建对象
Object boss = bossClass.newInstance();
//3、调用public的hi方法
//得到hi方法对象
//Method hi1 = bossClass.getMethod("hi", String.class);//获取public方法
Method hi = bossClass.getDeclaredMethod("hi", String.class);//获取所有的方法
//调用
hi.invoke(boss,"gyc");
//4、调用 private static方法
//得到say方法对象
Method say = bossClass.getDeclaredMethod("say", int.class, String.class, char.class);
//因为say方法是private,所以需要爆破
say.setAccessible(true);
System.out.println(say.invoke(boss,18,"zzz",'男'));
//因为say方法是static,所以还可以这样调用,可以传入null
System.out.println(say.invoke(null,20,"wz",'女'));
//5、在反射中,如果方法有返回值,统一返回Object,但运行类型和方法定义的返回类型一致
Object invoke = say.invoke(null, 50, "qq", 's');
System.out.println("invoke的运行类型:" + invoke.getClass());
}
}
class Boss{
public int age;
private static String name;
public Boss(){//构造器
}
private static String say(int n,String s,char c){ //静态方法
return n+" "+s+" "+c;
}
public void hi(String s){ //普通publi方法
System.out.println("hi "+s);
}
}
输出:
hi gyc
18 zzz 男
20 wz 女
invoke的运行类型:class java.lang.String