JAVA——反射
一、什么是反射
概述:Java反射是Java语言的一种特性,它允许程序在运行时自我检查并对内部成员进行操作。这种动态获取信息以及动态调用对象方法的功能称为Java语言的反射机制。具体来说,反射机制允许在运行状态中:对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意方法和属性,并且能改变它的属性。
Java反射机制的核心是在程序运行时动态加载类并获取类的详细信息,从而操作类或对象的属性和方法。其本质是JVM得到Class对象之后,再通过Class对象进行反编译,从而获取对象的各种信息。
应用场景:
a.解剖成员方法:赋值
b.解剖成员方法:调用
c.解剖构造方法:new对象
Class类
在Java编程语言中,Class类是一个特殊的类,它用于表示JVM运行时的类或接口的信息。你可以把它看作是一个普通的类,但它描述的是所有的类的公共特性。
每个类在Java中都对应着一个Class对象,这个对象保存了该类的结构信息,如类名、字段、方法等。换句话说,Class类是一个反射工具,能提供很多方法用于获取类的各种信息,比如获取类名、判断该类是否是一个接口还是普通类等等。
二、反射的应用
1.获取class对象
1.Object中的getClass方法
class<?> getClass()
2.不管是基本类型还是引用类型,jvm都提供了静态成员:class
类名.class
3.Class类中的静态方法
static Class<?> forName(String className)className:传递的是类的全限定名(包名.类名)
写类的全限定名技巧:
a.复制粘贴
b.类名回车
public class Demon01 {@Testpublic void get1() throws ClassNotFoundException {Student student = new Student();Class<? extends Student> class1=student.getClass();System.out.println(class1);Class<Student> class2=Student.class;System.out.println(class2);Class<?> class3=Class.forName("Student");System.out.println(class3);}
}
3为最通用方法,可以和properties文件结合使用
2为最常用方法
2.反射构造方法
1.获取所有public构造方法
Class中的方法:Constructor<?>[] getConstructors()->获取所有public的构造public class Demon01 {@Testpublic void get1() throws ClassNotFoundException {Class<Student> class1=Student.class;Constructor<?>[] constructors= class1.getConstructors();for (Constructor<?> constructor : constructors) {System.out.println(constructor);}}
}
2.获取空参构造
Class中的方法:Constructor<T> getConstructors(Class<?>...parameterTypes)->获取指定public的构造parameterTypes:可变参数,传递0个或多个参数a.如果获取的是空参构造:参数不用写b.如果获取的是有参构造:参数写参数类型的class对象Constructor类中的方法:T newInstance(Object...initargs)->创建对象initargs:传递构造方法的实参public class Demon01 {@Testpublic void get1() throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {Class<Student> class1=Student.class;Constructor<Student> constructor= class1.getConstructor();System.out.println(constructor);Student student=constructor.newInstance();System.out.println(student);}
}
利用空参构造创建对象的快捷方法
Class中的方法:
T newInstance()->根据空参对象创建对象前提:被反射的类中必须有public的空参构造
3.获取有参构造
Class中的方法:Constructor<T> getConstructors(Class<?>...parameterTypes)->获取指定public的构造parameterTypes:可变参数,传递0个或多个参数a.如果获取的是空参构造:参数不用写b.如果获取的是有参构造:参数写参数类型的class对象Constructor类中的方法:T newInstance(Object...initargs)->创建对象initargs:传递构造方法的实参public class Demon01 {@Testpublic void get1() throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {Class<Student> class1=Student.class;Constructor<Student> constructor= class1.getConstructor(int.class,int.class,int.class);System.out.println(constructor);Student student=constructor.newInstance(1,2,3);System.out.println(student);}
}
4.获取私有构造
1.Constructor<?>[] getDeclaredConstructors()获取所有构造方法
2.Constructor<T> getDeclaredConstructor(类<?>...parameterTypes)->获取指定构造包括privateparameterTypes:参数类型的class对象
3.Constructor有一个父类AccessibleObject,里面有一个方法void setAccessible(boolean flag)->修改访问权限flag为true:解除私有权限(暴力反射)public class Demon01 {@Testpublic void get1() throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {Class<Student> class1=Student.class;Constructor<Student> constructor= class1.getDeclaredConstructor(int.class);System.out.println(constructor);constructor.setAccessible(true);Student student=constructor.newInstance(1);System.out.println(student);}
}
3.反射成员方法
1.获取所有public成员方法
1.Class类中的方法:
Method[] getMethods()->获取所有public方法,包括父类中的public方法public static void main(String[] args) {Class<Student> clazz = Student.class;Method[] methods = clazz.getMethods();for (Method method : methods) {System.out.println(method.getName());}
}
2.获取(有参,无参)public方法
1.Class类中的方法:
Method getMethod(String name,Class<?>...parameterTypes)->获取指定的public成员方法name:方法名parameterTypes:方法参数类型的class对象
2.调用方法:Method对象中的方法Object invoke(Object obj,Object...args)->执行方法obj->根据构造new出来的对象args:方法实参->如果有参数,直接传递实参;否则不用传返回值:Object->接收被执行方法的返回值,如果方法没有返回值,不用接收
3.操作私有方法
1.Metod[] getDeclaredMethods()->获取所有的成员方法
2.Method getDeclearedMethod(String name,类<?>...parameterTypes)->获取指定成员方法
3.解除 私有权限void setAccessible(boolean flag)->修改访问权限flag为true:解除私有权限(暴力反射)
4.反射成员变量
1.获取所有属性
Class类中的方法:
1.Filed[] getFileds()->获取所有public属性
2.Filed[] getDeclaredFileds()->获取所有属性 public static void main(String[] args) throws Exception {Class<Student> clazz = Student.class;Field[] field = clazz.getFields();for (Field field1 : field) {System.out.println(field1);}Field[] fieldds=clazz.getDeclaredFields();for (Field field2 : fieldds) {System.out.println(field2);}
}
2.获取指定属性
1.Filed getFiled(String name)->获取指定public属性
2.Filed getDeclaredFiled(String name)->获取指定属性
3.Filed类中的方法:void set(Object obj,Object val)->为属性赋值obj:对象val:赋予的值Object get(Object obj)->获取属性值obj:对象public static void main(String[] args) throws Exception {Class<Student> clazz = Student.class;Student student = new Student();Field fields = clazz.getField("age");fields.set(student, 1);System.out.println(fields.get(student));
}
public class Test {
public static void main(String[] args) throws Exception {Class<Student> clazz = Student.class;Student student = new Student();Field fields = clazz.getDeclaredField("id");fields.setAccessible(true);fields.set(student, 1);System.out.println(fields.get(student));}
}
5.结合配置文件使用
步骤:
1.创建properties配置文件,配置信息
2.读取配置文件,解析配置文件
用类加载器读取配置文件
classLoader classLoader = 当前类.class.getClassLoaderO
InputStream in= classLoader.getResourceAsStream("文件名")//自动扫描resources下的文件->
可以简单理解为扫描out路径下的配置文件
3.根据解析出来的className,创建class对象
4.根据解析出来的methodName,获取对应的方法
5.执行方法
例子:
public class Demon01 {public static void main(String[] args) throws Exception {Properties properties=new Properties();InputStream in =Demon01.class.getClassLoader().getResourceAsStream("pro.properties");properties.load(in);String name = properties.getProperty("className");String methodName = properties.getProperty("methodName");Class<?> aClass=Class.forName(name);Object object=aClass.newInstance();aClass.getMethod(methodName).invoke(object);}
}