通过反射创建对象
基本介绍案例演示 通过反射访问类中的成员
访问属性
基本介绍案例演示 访问方法
基本介绍案例演示 反射作业练习
通过反射创建对象 基本介绍- 方式一:调用类中的public修饰的无参构造器方式二:调用类中的指定构造器Class类相关方法
newInstance:调用类中的无参构造器,获取对应类的对象getConstructor(class…clazz):根据参数列表,获取对应的构造器对象getDecalaredConstructor(class…clazz):根据参数列表,获取对应的所有构造器对象
- Constructor类相关方法
setAccessible:爆破newInstance(Object…obj):调用构造器 案例演示
- 测试1:通过反射创建某类的对象,要求该类中必须有public的无参构造测试2:通过调用某个特定构造器的方式,实现创建某类的对象
package com.taotao.reflection;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
@SuppressWarnings({"all"})
public class ReflecCreateInstance {
public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchMethodException, InvocationTargetException {
//1.现获取User类的Class对象
Class> aClass = Class.forName("com.taotao.reflection.User");
//2.通过public的无参构造器创建实例
Object o = aClass.newInstance();
System.out.println(o);
//3.通过public的有参构造器创建实例
//【1】.得到对应的构造器
Constructor> constructor = aClass.getConstructor(String.class);
//【2】创建实参,并传入实参
Object tao = constructor.newInstance("tao");
System.out.println("taotao = " + tao);
//4.通过【非】public的有参构造器创建实例
//【1】得到私有的构造器对象
// Constructor> constructor1 = aClass.getConstructor(int.class, String.class); //此方法只能得到public
Constructor> constructor1 = aClass.getDeclaredConstructor(int.class, String.class);
//【2】创建实例,并传入实参,因为是私有,所以还会报错,所以我们采用“爆破”
constructor1.setAccessible(true); //爆破,使用反射可以访问private构造器,反射面前,都是纸老虎
Object taotao = constructor1.newInstance(20, "刘鸿涛");
System.out.println("taotao = " + taotao);
}
}
@SuppressWarnings({"all"})
class User { //User类
private int age = 10;
private String name = "涛涛";
public User() { //public 无参
}
public User(String name) { //public 有参
this.name = name;
}
private User(int age,String name){ //private 有参
this.age = age;
this.name = name;
}
@Override
public String toString() {
return "User{" +
"age=" + age +
", name='" + name + ''' +
'}';
}
}
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-rjqx5VrW-1645953265858)(image-20220227102747966.png)]
通过反射访问类中的成员 访问属性 基本介绍- 根据属性名获取Field对象
Field f = clazzz对象.getDeclaredField(属性名);
- 爆破:f.setAccessible(true);//f 是Field访问
f.set(o,值); syso(f.get(o));
- 如果是静态属性,则set和get中的参数o,可以写成null
package com.taotao.reflection;
import java.lang.reflect.Field;
@SuppressWarnings({"all"})
public class ReflecAccessProperty {
public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchFieldException {
//1.得到Student类对应的Class对象
Class> stuClass = Class.forName("com.taotao.reflection.Student");
//2.创建对象
Object o = stuClass.newInstance(); //o的运行类型就是Student
System.out.println(o.getClass()); //Student
//3.使用反射得到age 属性对象
Field age = stuClass.getField("age");
age.set(o,88); //通过反射来操作属性
System.out.println(o); //
System.out.println(age.get(o)); //返回age属性的值
//4.使用反射操作name 属性
Field name = stuClass.getDeclaredField("name");
// name.set(null,"涛涛"); //因为name是static属性,因此 o 也可以写出null,这样也可以设置
name.setAccessible(true); //关闭访问检查
name.set(o,"涛涛");
System.out.println(o);
System.out.println(name.get(o)); //涛涛
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 + "]";
}
}
访问方法
基本介绍
- 根据方法名和参数列表获取列表获取Method方法对象:
Method m = clazz.getDeclaredMethod(方法名,XX.class);
- 获取对象:Object o = clazz.newInstance();爆破:m.setAccessible(true);访问:Object returnValue = m.invoke(o,实参列表);注意:如果是静态方法,则invoke的参数o,可以写成null
package com.taotao.reflection;
import jdk.nashorn.internal.ir.CallNode;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
@SuppressWarnings({"all"})
public class ReflecAccessMethod {
public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchMethodException, InvocationTargetException {
//1.得到Boss类对应的Class对象
Class> bossClass = Class.forName("com.taotao.reflection.Boss");
//2.创建对象
Object o = bossClass.newInstance();
//3.调用public的hi方法(getMethod获得公共的方法)
//Method hi = bossClass.getMethod("hi"); //ok
//3.1 得到hi方法对象 (getDeclaredMethod是获得所有方法)
Method hi = bossClass.getDeclaredMethod("hi",String.class); //ok
//3.2 调用
hi.invoke(o,"涛涛教育");
//4.调用private static
//4.1 得到 say方法对象
Method say = bossClass.getDeclaredMethod("say", int.class, String.class, char.class);
//4.2 因为此方法是私有的,所以我们需要爆破
say.setAccessible(true);
System.out.println(say.invoke(o, 100, "涛涛",'男'));
//4.3 因为say方法是static的,还可以这样调用
System.out.println(say.invoke(null,200,"李四",'女'));
//5.在反射中,如果方法有返回值,同一返回Object,但是他运行类型和方法定义的返回类型一致
Object reval = say.invoke(null, 300, "王五", '男');
System.out.println("reval的运行类型 = " + reval.getClass()); //String
}
}
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) {
System.out.println("hi" + s);
}
}
反射作业练习
通过反射修改私有成员变量
- 定义PrivateTest类,有私有name属性,并且属性值为hellokitty提供getName的公有方法创建PrivateTest的类,利用Class类得到私有的name属性,修改私有的name属性值,并调用getName()的方法打印name属性值
package com.taotao.reflection.homework;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
@SuppressWarnings({"all"})
public class Homework01 {
public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchFieldException, NoSuchMethodException, InvocationTargetException {
//1.得到student类对应的Class对象
Class> testClass = Class.forName("com.taotao.reflection.homework.PrivateTest");
//2.创建对象
Object o = testClass.newInstance();
//使用反射得到私有属性name,爆破
Field name = testClass.getDeclaredField("name");
name.setAccessible(true);
name.set(o,"taotao");
//使用反射得到公共方法并调用
Method method = testClass.getMethod("getName");
System.out.println(method.invoke(o));
}
}
@SuppressWarnings({"all"})
class PrivateTest {
private String name = "hellokitty";
public String getName(){
return name;
}
}



