1.概述
反射是框架设计的灵魂
框架:半成品软件,可以在框架的基础上进行软件开发,简化代码
反射:将类的各个组成部分封装为其他对象,这就是反射机制
通过new创建实例和反射创建实例,都绕不开Class对象。
好处:
- 在程序的运行过程中,去操作这些对象
- 可以解耦,提高程序的可扩展性
2.获取字节码Class对象的三种方法
(1)class.forName("全类名"):将字节码文件加载进内存,返回class对象。多用于配置文件,将类名定义在配置文件中,读取文件,加载类
(2)类名.class:通过类名的属性class获取。多用于参数的传递
(3)对象.getClass():getClass()方法在Object类中定义着。多用于对象获取字节码的方式。
结论:
同一个字节码文件(*.class)在一次程序运行过程中,只会被加载一次,不论通过哪一种方式获取的class对象都是同一个。
Person .java
package domain; public class Person { String name; int age; public Person() { } public Person(String name, int age) { this.name = name; this.age = age; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } @Override public String toString() { return "Person{" + "name='" + name + '\'' + ", age=" + age + '}'; } }
ReflectDemo1.java
package reflect; import domain.Person; public class ReflectDemo1 { /** * 获取class对象的三种方式 */ public static void main(String[] args) throws Exception { // 1. Class.forName("全类名") Class<?> aClass = Class.forName("domain.Person"); System.out.println(aClass); // 2.类名.class Class<Person> personClass = Person.class; System.out.println(personClass); // 3.对象.getClass() Person person = new Person(); Class<? extends Person> aClass1 = person.getClass(); System.out.println(aClass1); // 用== 比较三个对象引用的在内存中的地址,如果地址值相同,说明这三个引用指的是堆内存中同一个对象 System.out.println(aClass == personClass); // true System.out.println(aClass == aClass1); // true } }
运行结果:
每一个字节码文件对应的class对象都不同
3.class对象的功能
(1)获取功能
- 获取成员变量们
Field[] getFields() 获取所有public修饰的成员变量
Field getField(String name) 获取指定名称的public修饰的成员变量
Field[] getDeclareFields() 获取所有的成员变量,不考虑修饰符
Field getDeclareField()
- 获取构造方法们
Constructor<?>[] getConstructors()
Constructor<T> getConstructor(类<?>... parameterTypes)
Constructor<?>[] getDeclaredConstructors()
Constructor<T> getDeclaredConstructor(类<?>... parameterTypes)
- 获取成员方法们
方法[] getMethods()
方法 getMethod(String name, 类<?>... parameterTypes)
方法[] getDeclaredMethods()
方法 getDeclaredMethod(String name, 类<?>... parameterTypes)
- 获取类名
String getName()
(2)Field:成员变量
操作:
设置值:
void set(Object obj, Object value)
获取值:
get(Object obj)
忽略访问权限修饰符的安全检查
setAccessible(true); 暴力反射
运行结果:
运行结果:
(3)Constructor:构造方法
创建对象:
T newInstance(Object...initargs)
import java.lang.reflect.Constructor; public class ReflectDemo3 { public static void main(String[] args) throws Exception { // 获取Person的Class对象 Class<Person> personClass = Person.class; // Constructor<T> getConstructor(类<?>...parameterTypes) Constructor<Person> constructor = personClass.getConstructor(String.class, int.class); System.out.println(constructor); // 构造器创建对象 Person person = constructor.newInstance("张三", 23); System.out.println(person); System.out.println("====================="); // 使用空参构造 Constructor<Person> constructor1 = personClass.getConstructor(); System.out.println(constructor1); // 使用空参构造器创建对象 Person person1 = constructor1.newInstance(); System.out.println(person1); } }
运行结果:
(4)Method:方法对象
Person.java
package cn.yjg.day10.demo07; public class Person { private String name; private int age; 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 String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } @Override public String toString() { return "Person{" + "name='" + name + '\'' + ", age=" + age + ", a='" + a + '\'' + ", b='" + b + '\'' + ", c='" + c + '\'' + ", d='" + d + '\'' + '}'; } public void eat() { System.out.println("eat..."); } public void eat(String food){ System.out.println("eat..." + food); } }
package cn.yjg.day10.demo07; import java.lang.reflect.Method; public class ReflectDemo4 { public static void main(String[] args) throws Exception { // 获取Person的Class对象 Class<Person> personClass = Person.class; // 获取指定名称的方法对象 Method eat_method = personClass.getMethod("eat"); Person p = new Person(); // 执行方法 eat_method.invoke(p); // 有参的成员方法 Method eat_method2 = personClass.getMethod("eat", String.class); eat_method2.invoke(p, "饭"); System.out.println("------------------"); // 获取所有public修饰的方法 Method[] methods = personClass.getMethods(); for (Method method: methods) { System.out.println(method); } } }
运行结果:
(5)获取方法名
运行结果:
(6)获取类名
运行结果: