前言
反射:将类的各个组成部分封装为其他对象,这就是反射机制。
好处:
- 可以在程序运行过程中,操作这些对象。
- 可以解耦,提高程序的可扩展性。
获取Class对象的方式
- Class.forName("全类名"):将字节码文件加载进内存,返回Class对象
多用于配置文件,将类名定义在配置文件中。读取文件,加载类
- 类名.class:通过类名的属性class获取
多用于参数的传递
- 对象.getClass():getClass()方法在Object类中定义着。
多用于对象的获取字节码的方式
结论:**同一个字节码文件(*.class)在一次程序运行过程中,只会被加载一次,不论通过哪一种方式获取的Class对象都是同一个**。
示例:
public class Person { private String name; private int age; private static String city="上海"; public String a; protected String b; String c; private String d; public Person() { } public Person(String name, int age) { this.name = name; this.age = age; } public void eat(){ System.out.println("吃饭。。。。"); } public void sleep(){ System.out.println("睡觉。。。。"); } }
public class Reflectyby6Demo1 { public static void main(String[] args) { /* 1. Class.forName("全类名"):将字节码文件加载进内存,返回Class对象 - 多用于配置文件,将类名定义在配置文件中。读取文件,加载类 2. 类名.class:通过类名的属性class获取 - 多用于参数的传递 3. 对象.getClass():getClass()方法在Object类中定义着。 - 多用于对象的获取字节码的方式 */ //1. Class.forName("全类名"):将字节码文件加载进内存,返回Class对象 try { Class<?> aClass = Class.forName("com.tuling.domain.Person"); //类名.class:通过类名的属性class获取 Class<Person> personClass = Person.class; //3. 对象.getClass():getClass()方法在Object类中定义着。 Person person = new Person(); Class<? extends Person> aClass2 = person.getClass(); System.out.println("aClass==personClass:"+(aClass==personClass)); System.out.println("aClass2==personClass:"+(aClass==personClass)); } catch (ClassNotFoundException e) { e.printStackTrace(); } } }
Class对象功能
获取成员变量
- Field[] getFields() :获取所有public修饰的成员变量
- Field getField(String name) 获取指定名称的 public修饰的成员变量
- Field[] getDeclaredFields() 获取所有的成员变量,不考虑修饰符
- Field getDeclaredField(String name)
Field:成员变量
- 设置值 void set(Object obj, Object value)
- 获取值 get(Object obj)
- 忽略访问权限修饰符的安全检查(暴力反射) setAccessible(true)
示例:
public class ReflectYby6Demo2 { @Test public void test1() throws Exception { /* - Field[] getFields() :获取所有public修饰的成员变量 - Field getField(String name) 获取指定名称的 public修饰的成员变量 - Field[] getDeclaredFields() 获取所有的成员变量,不考虑修饰符 - Field getDeclaredField(String name) */ Class<Person> personClass = Person.class; // Field[] fields = personClass.getFields(); for (Field field : fields) { System.out.println(field); } System.out.println("-----------"); Field[] declaredFields = personClass.getDeclaredFields(); for (Field declaredField : declaredFields) { System.out.println(declaredField); } /* 1. 设置值 - void set(Object obj, Object value) 2. 获取值 - get(Object obj) 3. 忽略访问权限修饰符的安全检查 - setAccessible(true):暴力反射 */ System.out.println("------------------"); Field a = personClass.getField("a"); Person p = new Person(); a.set(p,"zhongguo"); //获取值 Object o = a.get(p); System.out.println("o:"+o); //a.setAccessible(true); Field name = personClass.getDeclaredField("name"); /* Class com.qf.reflect.ReflectDemo2 can not access a member of class com.qf.domain.Person with modifiers "private" */ System.out.println("name:"+name.get(p)); } }
获取构造方法
- Constructor<?>[] getConstructors()
- Constructor<T> getConstructor(Class<?>... parameterTypes)
- Constructor<T> getDeclaredConstructor(Class<?>... parameterTypes)
- Constructor<?>[] getDeclaredConstructors()
Constructor:构造方法
创建对象:T newInstance(Object... initargs)
如果使用空参数构造方法创建对象,操作可以简化:Class对象的newInstance方法
示例:
import java.lang.reflect.Constructor; import java.lang.reflect.InvocationTargetException; public class ReflectDemo3 { public static void main(String[] args) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException { /* 2. 获取构造方法们 - Constructor<?>[] getConstructors() - Constructor<T> getConstructor(类<?>... parameterTypes) - Constructor<T> getDeclaredConstructor(类<?>... parameterTypes) - Constructor<?>[] getDeclaredConstructors() */ Class<Person> personClass = Person.class; //获取有参的构造方法 Constructor<Person> constructor = personClass.getConstructor(String.class, int.class); System.out.println(constructor); //创建对象1 Person person1 = constructor.newInstance("张三", 23); System.out.println(person1); //获取无参的构造方法 Constructor<Person> constructor2 = personClass.getConstructor(); System.out.println("constructor2:"+constructor2); //创建对象2 Person person2 = constructor2.newInstance(); System.out.println("person2:"+person2); //创建对象3 Person person3 = personClass.newInstance(); System.out.println("person3:"+person3); System.out.println("------------"); Constructor<?>[] declaredConstructors = personClass.getDeclaredConstructors(); for (Constructor<?> declaredConstructor : declaredConstructors) { System.out.println(declaredConstructor); } System.out.println("-------------"); //构造器暴力访问 //constructor2.setAccessible(true); } }
获取成员方法
- Method[] getMethods() :获取类里面所有的public方法,包括父类里面的public方法
- Method getMethod(String name, 类<?>... parameterTypes)
- Method[] getDeclaredMethods() :获取类里面声明的所有的方法,不包括父类的方法
- Method getDeclaredMethod(String name, 类<?>... parameterTypes)
Method:方法对象
执行方法:Object invoke(Object obj, Object... args)
获取方法名称:String getName
import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; public class Reflectyby6Demo4 { public static void main(String[] args) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException { /* 获取成员方法: Method[] getMethods() Method getMethod(String name, 类<?>... parameterTypes) Method[] getDeclaredMethods() Method getDeclaredMethod(String name, 类<?>... parameterTypes) */ Class<Person> personClass = Person.class; //获取指定名称的方法 Method eat = personClass.getMethod("eat"); // Person p = new Person(); //执行方法 eat.invoke(p); //获取指定名称,并且带参数的方法 Method eat2 = personClass.getMethod("eat", String.class); //执行带参数的方法 eat2.invoke(p,"wowo"); System.out.println("--------------"); //获取所有public修饰的方法 Method[] methods = personClass.getMethods(); for (Method method : methods) { System.out.println(method); //方法名 System.out.println(method.getName()); } System.out.println("-----------------"); //获取类名 String name = personClass.getName(); System.out.println("类名:"+name); } }
在程序使用(解析)注解
在程序使用(解析)注解:获取注解中定义的属性值
1获取注解定义的位置的对象 (Class,Method,Field)
2判断注解是否存在
isAnnotationPresent(Class)
3获取指定的注解
getAnnotation(Class)
4调用注解中的抽象方法获取配置的属性值
示例:
import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; @Target({ElementType.METHOD}) @Retention(RetentionPolicy.RUNTIME) public @interface MyAnno4 { int age() default 0; }
import java.lang.reflect.Method; public class Annotationyby6Demo3 { public static void main(String[] args) throws NoSuchMethodException { /* - 在程序使用(解析)注解:获取注解中定义的属性值 1. 获取注解定义的位置的对象 (Class,Method,Field) - isAnnotationPresent(Class) 1. 获取指定的注解 - getAnnotation(Class) 3. 调用注解中的抽象方法获取配置的属性值 */ Class<Person> personClass = Person.class; System.out.println("------------"); Method test = personClass.getMethod("test"); System.out.println(test.isAnnotationPresent(MyAnno4.class)); //获取方法上定义的注解 if(test.isAnnotationPresent(MyAnno4.class)){ System.out.println("test方法有定义注解"); MyAnno4 annotation2 = test.getAnnotation(MyAnno4.class); int age2 = annotation2.age(); System.out.println("age2:"+age2); } } }
最后
本期结束咱们下次再见👋~
🌊 关注我不迷路,如果本篇文章对你有所帮助,或者你有什么疑问,欢迎在评论区留言,我一般看到都会回复的。大家点赞支持一下哟~ 💗