Java 反射(Reflection)是可以让我们在运行时获取类的方法、属性、父类、接口等类的内部信息的机制。
什么是反射?
个人理解:反着来
官方理解:反射是一个机制,利用反射机制动态的实例化对象、读写属性、调用方法、构造函数
反射能干什么、有什么用?
Java Reflection功能非常强大,并且非常有用
比如:
1.获取任意类的名称、package信息、所有属性、方法、注解、类型、类加载器等
2.获取任意对象的属性,并且能改变对象的属性。
3.调用任意对象的方法
4.判断任意一个对象所属的类
5.实例化任意一个类的对象
6.通过反射我们可以实现动态装配,降低代码的耦合度,动态代理等。
如何使用反射
一切与反射相关的代码都从获取类对应的字节码对象开始
三种:
1.对象名.getClass()
Student stu=new Student(); Class stuClass = stu.getClass();
先实例化一个Student对象,再用对象名点
2.类名.class
Class<Student> stuClass = Student.class;
就是直接用类名点
3.Class.forName("类的全路径")
Class stuClass = Class.forName("com.zking.entity.Student");
然后三种都用下面这些
System.out.println("类名全路径"+stuClass.getName()); System.out.println("类名"+stuClass.getSimpleName()); System.out.println("包名"+stuClass.getPackage());
都将会出现这些东西
传统实例化与反射实例化的区别
1.传统实例化对象
Student stu = new Student();
传统的只能实例化公共的,不能实例化私有的、受保护的等等
2.反射实例化对象
Class stuClass = Class.forName("com.zking.entity.Student"); Object newInstance = stuClass.newInstance();
反射是可以使用所有的包括私有的、受保护的等等
Class.forName指定全路径名必须正确,否则将报ClassNotFoundException错误;
反射应用
类名 | 用途 |
Class类 | 代表类的实体,在运行的Java应用程序中表示类和接口 |
Field类 | 代表类的成员变量(成员变量也成为类的属性) |
Method类 | 代表类的方法 |
Constructor类 | 代表类的构造函数 |
1.读取属性(Field)
类名 | 用途 |
getField(String name) | 获取某个公共的属性对象 |
getFields() | 获取所有公共的属性对象 |
getDeclaredField(String name) | 获取某个属性对象(public和非public) |
getDeclaredFields() | 获取所有属性对象(public和非public) |
setAccessible(boolean flag) | 默认值false,设置true使私有成员允许访问 |
set(Object,Object) | 属性赋值 |
get(Object) | 获取属性 |
1.1获取单个公共的属性
Field field = stuClass.getField("age");
1.2获取单个所有的属性
Field field = stuClass.getDeclaredField("sname");
前两个可以使用下面的方法来测试
System.out.println("获取属性名"+field.getName()); System.out.println("获取属性类型"+field.getType()); System.out.println("访问修饰符"+field.getModifiers());
1.3获取所有公共的属性
Field[] fields = stuClass.getFields();
1.4获取所有属性
Field[] fields = stuClass.getDeclaredFields();
后面两个需要用到迭代器循环
for (Field field : fields) { System.out.println("获取属性名"+field.getName()); System.out.println("获取属性类型"+field.getType()); System.out.println("访问修饰符"+field.getModifiers()); System.out.println("-------------"); }
出来的效果都是差不多的
1.5属性赋值和获取属性值
先获取属性
//获取单个所有属性
Field field = stuClass.getDeclaredField("sname");
// 属性赋值
// 设置权限(在对类中私有属性赋值是必须设置访问权限)
field.setAccessible(true);
// 参数1:代表实例化对象 2:赋的值
field.set(newInstance,"张张");
// 获取属性
Object o = field.get(newInstance);
System.out.println(o);
2.调用方法(Method)
类名 | 用途 |
getMethod(String name, Class<>… parameterTypes) | 获取该类某个公共的方法 |
getMethods() | 获取该类所有公共的方法 |
getDeclaredMethods(String name,Class<>… parameterTypes) | 获取该类某个方法(public和非public) |
getDeclaredMethod() | 获取该类所有方法(public和非public) |
setAccessible(boolean flag) | 默认值false,设置true使私有方法允许访问 |
invoke(Object obj, Object… args) | 执行方法 |
那我们先回顾一下方法的类型:
有参有返回,无参无返回,有参无返回,无参有返回
2.1获取单个公共的属性
Method method = stuClass.getMethod("hello");
2.2获取单个所有的属性
Method method = stuClass.getDeclaredMethod("add",Integer.class,Integer.class);
前两个可以使用下面的方法来测试
System.out.println("方法名"+method.getName()); System.out.println("返回类型"+method.getReturnType()); System.out.println("访问修饰符"+method.getModifiers()); System.out.println("方法参数数量"+method.getParameterCount());
2.3获取所有公共的属性
Method[] methods = stuClass.getMethods();
2.4获取所有属性
Method[] methods = stuClass.getDeclaredMethods();
后面两个需要用到迭代器循环
for (Method method :methods) {
System.out.println("方法名"+method.getName());
System.out.println("返回类型"+method.getReturnType());
System.out.println("访问修饰符"+method.getModifiers());
System.out.println("方法参数数量"+method.getParameterCount());
System.out.println("------------");
}
2.5调用方法
// 获取单个所有属性
Method method = stuClass.getDeclaredMethod("add",Integer.class,Integer.class);
//设置权限
method.setAccessible(true);
// 调用方法
// 参数1:实例化对象名 2:方法本身所需参数(可变参数)
Object invoke = method.invoke(newInstance, 5, 20);
System.out.println(invoke);
3.构造函数(Constructor)
类名 | 用途 |
getConstructor(Class<>… parameterTypes) | 获取该类中与参数类型匹配的公有构造方法 |
getConstructors() | 获取该类的所有公共构造方法 |
getDeclaredConstructors(Class<>… parameterTypes) | 获取该类中与参数类型匹配的构造方法 |
getDeclaredConstructors() | 获取该类所有构造方法(public和非public) |
3.1获取该类中与参数类型匹配的公有构造方法
Constructor constructor = stuClass.getConstructor(String.class); System.out.println(constructor);
3.2获取该类的所有公共构造方法
Constructor[] constructors = stuClass.getConstructors(); for (Constructor constructor : constructors) { System.out.println(constructor); }
3.3获取该类中与参数类型匹配的构造方法
Constructor constructor = stuClass.getDeclaredConstructor(Integer.class); System.out.println(constructor);
3.4获取该类所有构造方法(public和非public)
Constructor[] constructors = stuClass.getDeclaredConstructors(); for (Constructor constructor : constructors) { System.out.println(constructor); }
3.5通过构造函数实例化对象
//getConstructor(Class<>… parameterTypes) 获取该类中与参数类型匹配的公有构造方法
Constructor constructor = stuClass.getConstructor(String.class);
//System.out.println(constructor);
//设置权限
constructor.setAccessible(true);
//通过构造函数实例化对象
Object o = constructor.newInstance("hh");
System.out.println(o);