程序在运行中也可以获取类的变量和方法信息,并通过获取到的信息来创建对象。程序不必再编译期就完成确定,在运行期仍然可以扩展。
示例:学生类
public class Student { // 成员变量:公共、受保护、默认、私有各一个 public String name; protected String pwd; String sex; private int age; // 构造方法:公共两个,受保护、默认、私有各一个 public Student() { } protected Student(String name) { this.name = name; } Student(String name, String pwd) { this.name = name; this.pwd = pwd; } private Student(String name, String pwd, String sex) { this.name = name; this.pwd = pwd; this.sex = sex; } public Student(String name, String pwd, String sex, int age) { this.name = name; this.pwd = pwd; this.sex = sex; this.age = age; } // 成员方法:公共、受保护、默认、私有各一个 public void method1() { System.out.println("public成员方法:method1"); } protected void method2() { System.out.println("protected成员方法:method2"); } void method3() { System.out.println("default成员方法:method3"); } private void method4() { System.out.println("private成员方法:method4"); } @Override public String toString() { return "Student{" + "name='" + name + '\'' + ", pwd='" + pwd + '\'' + ", sex=" + sex + ", age=" + age + '}'; } }
类名:Class<T>
包名:java.lang.Class<T>
Class 类和 Class 文件的关系:java.lang.Class 类用于表示一个类的字节码(.class)文件
通过反射获取对象的方式有以下三种:
方式 | 描述 |
---|---|
类名.class | 当该类被加载成 .class 文件时,此时该类变成了 .class,再获取该字节码文件对象,也就是获取自己, 该类处于字节码阶段 |
对象.getClass() | 通过类的实例获取该类的字节码文件对象,该类处于创建对象阶段 |
Class.forName("全限定类名") | 通过 Class 类中的静态方法 forName 直接获取到该类的字节码文件对象,此时该类还是源文件阶段,并没有变为字节码文件 |
测试:
public class Test_01 { public static void main(String[] args) throws ClassNotFoundException { // 类名.class Class<Student> s1 = Student.class; // 对象.getClass() Student student = new Student(); Class<? extends Student> s2 = student.getClass(); // Class.forName("包名.类名") Class<?> s3 = Class.forName("A_11_reflect.Student"); System.out.println(s1 + "\n" + s2 + "\n" + s3); System.out.println(s1 == s2 && s1 == s3 && s2 == s3); } }
运行:
class A_11_reflect.Student class A_11_reflect.Student class A_11_reflect.Student true
修饰符和类型 | 方法 | 秒速 |
---|---|---|
Constructor<?>[] | getConstructors() | 返回该类所有的公共构造方法 |
Constructor |
getConstructor(Class<?>... parameterTypes) | 返回该类指定的公共构造方法 |
Constructor<?>[] | getDeclaredConstructors() | 返回该类所有的构造方法 |
Constructor |
getDeclaredConstructor(Class<?>... parameterTypes) | 返回该类指定的构造方法 |
测试:
public class Test_02 { public static void main(String[] args) throws NoSuchMethodException { Class<Student> s = Student.class; // 获取该类所有的公共构造方法 Constructor<?>[] constructors = s.getConstructors(); for (Constructor constructor : constructors) { System.out.println("constructor = " + constructor); } System.out.println("--------"); // 获取该类指定的公共构造方法 Constructor<Student> c1 = s.getConstructor(); Constructor<Student> c2 = s.getConstructor(String.class, String.class, String.class, int.class); System.out.println("c1 = " + c1); System.out.println("c2 = " + c2); System.out.println("--------"); // 获取该类所有的构造方法 Constructor<?>[] declaredConstructors = s.getDeclaredConstructors(); for (Constructor declaredConstructor : declaredConstructors) { System.out.println("declaredConstructor = " + declaredConstructor); } System.out.println("--------"); // 获取该类指定的构造方法 Constructor<Student> c3 = s.getDeclaredConstructor(); Constructor<Student> c4 = s.getDeclaredConstructor(String.class); Constructor<Student> c5 = s.getDeclaredConstructor(String.class, String.class); Constructor<Student> c6 = s.getDeclaredConstructor(String.class, String.class, String.class); Constructor<Student> c7 = s.getDeclaredConstructor(String.class, String.class, String.class, int.class); System.out.println("c3 = " + c3 + "\nc4 = " + c4 + "\nc5 = " + c5 + "\nc6 = " + c6 + "\nc7 = " + c7); } }
运行:
constructor = public A_11_reflect.Student(java.lang.String,java.lang.String,java.lang.String,int) constructor = public A_11_reflect.Student() -------- c1 = public A_11_reflect.Student() c2 = public A_11_reflect.Student(java.lang.String,java.lang.String,java.lang.String,int) -------- declaredConstructor = public A_11_reflect.Student(java.lang.String,java.lang.String,java.lang.String,int) declaredConstructor = private A_11_reflect.Student(java.lang.String,java.lang.String,java.lang.String) declaredConstructor = A_11_reflect.Student(java.lang.String,java.lang.String) declaredConstructor = protected A_11_reflect.Student(java.lang.String) declaredConstructor = public A_11_reflect.Student() -------- c3 = public A_11_reflect.Student() c4 = protected A_11_reflect.Student(java.lang.String) c5 = A_11_reflect.Student(java.lang.String,java.lang.String) c6 = private A_11_reflect.Student(java.lang.String,java.lang.String,java.lang.String) c7 = public A_11_reflect.Student(java.lang.String,java.lang.String,java.lang.String,int)
类名:Constructor<T>
包名:java.lang.reflect.Constructor<T>
修饰符和类型 | 构造方法 | 描述 |
---|---|---|
T | newInstance(Object... initargs) | 根据指定的构造方法创建对象 |
void | setAccessible(boolean flag) | 值设为 true,取消访问检查(访问私有属性时会被检查) |
测试:
public class Test_03 { public static void main(String[] args) throws Exception { Class<Student> s = Student.class; // 调用公共的无参构造方法创建对象 Constructor<Student> c0 = s.getConstructor(); Student student0 = c0.newInstance(); System.out.println("student0 = " + student0); // 调用公共的有参构造方法创建对象 Constructor<Student> c1 = s.getConstructor(String.class, String.class, String.class, int.class); Student student1 = c1.newInstance("张三", "123", "男", 23); System.out.println("student1 = " + student1); // 调用受保护的有参构造方法创建对象 Constructor<Student> c2 = s.getDeclaredConstructor(String.class); Student student2 = c2.newInstance("李四"); System.out.println("student2 = " + student2); // 调用默认的有参构造方法创建对象 Constructor<Student> c3 = s.getDeclaredConstructor(String.class, String.class); Student student3 = c3.newInstance("王五", "123"); System.out.println("student3 = " + student3); // 调用私有的有参造方法创建对象 Constructor<Student> c4 = s.getDeclaredConstructor(String.class, String.class, String.class); c4.setAccessible(true); // 取消访问检查 Student student4 = c4.newInstance("赵六", "123", "男"); System.out.println("student4 = " + student4); } }
运行:
student0 = Student{name='null', pwd='null', sex=null, age=0} student1 = Student{name='张三', pwd='123', sex=男, age=23} student2 = Student{name='李四', pwd='null', sex=null, age=0} student3 = Student{name='王五', pwd='123', sex=null, age=0} student4 = Student{name='赵六', pwd='123', sex=男, age=0}
修饰符和类型 | 成员方法 | 描述 |
---|---|---|
Field[] | getFields() | 返回该类所有的公共成员变量 |
Field | getField(String name) | 返回该类指定的公共成员变量 |
Field[] | getDeclaredFields() | 返回该类所有的成员变量 |
Field | getDeclaredField(String name) | 返回该类指定的成员变量 |
测试:
public class Test_04 { public static void main(String[] args) throws NoSuchFieldException { Class<Student> s = Student.class; // 获取该类所有的公共成员变量 Field[] fields = s.getFields(); for (Field field : fields) { System.out.println("field = " + field); } System.out.println("--------"); // 获取该类指定的公共成员变量 Field name1 = s.getField("name"); System.out.println("name1 = " + name1); System.out.println("--------"); // 获取该类所有的成员变量 Field[] declaredFields = s.getDeclaredFields(); for (Field declaredField : declaredFields) { System.out.println("declaredField = " + declaredField); } System.out.println("--------"); // 获取该类指定的成员变量 Field name = s.getDeclaredField("name"); Field pwd = s.getDeclaredField("pwd"); Field sex = s.getDeclaredField("sex"); Field age = s.getDeclaredField("age"); System.out.println("name = " + name + "\npwd = " + pwd + "\nsex = " + sex + "\nage = " + age); } }
运行:
field = public java.lang.String A_11_reflect.Student.name -------- name1 = public java.lang.String A_11_reflect.Student.name -------- declaredField = public java.lang.String A_11_reflect.Student.name declaredField = protected java.lang.String A_11_reflect.Student.pwd declaredField = java.lang.String A_11_reflect.Student.sex declaredField = private int A_11_reflect.Student.age -------- name = public java.lang.String A_11_reflect.Student.name pwd = protected java.lang.String A_11_reflect.Student.pwd sex = java.lang.String A_11_reflect.Student.sex age = private int A_11_reflect.Student.age
类名:Field
包名:java.lang.reflect.Field
修饰符和类型 | 成员方法 | 描述 |
---|---|---|
Object | set(Object obj, Object value) | 将 value 赋值给 obj 对象的成员变量 |
Object | get(Object obj) | 返回 obj 对象的成员变量值 |
测试:
public class Test_05 { public static void main(String[] args) throws Exception { Class<Student> s = Student.class; // 先获取所有成员变量 Field name = s.getDeclaredField("name"); Field pwd = s.getDeclaredField("pwd"); Field sex = s.getDeclaredField("sex"); Field age = s.getDeclaredField("age"); // 调用无参构造方法 Constructor<Student> c = s.getConstructor(); // 实例化 Student student = c.newInstance(); // 成员变量赋值 name.set(student, "张三"); pwd.set(student, "123"); sex.set(student, "男"); age.setAccessible(true); // 私有成员需取消访问检查 age.set(student, 23); System.out.println("student = " + student); System.out.println("--------"); // 获取成员变量值 System.out.println(name.get(student)); System.out.println(pwd.get(student)); System.out.println(sex.get(student)); System.out.println(age.get(student)); } }
运行:
student = Student{name='张三', pwd='123', sex=男, age=23} -------- 张三 123 男 23
修饰符和类型 | 成员方法 | 描述 |
---|---|---|
Method[] | getMethods() | 返回该类所有的公共成员方法(包括继承的) |
Method | getMethod(String name, Class<?>... parameterTypes) | 返回该类指定的公共成员方法 |
Method[] | getDeclaredMethods() | 返回该类所有的成员方法(不包括继承的) |
Method | getDeclaredMethod(String name, Class<?>... parameterTypes) | 返回该类指定的成员方法 |
测试:
public class Test_06 { public static void main(String[] args) throws Exception { Class<Student> s = Student.class; // 获取该类所有的公共成员方法(包括继承的) Method[] methods = s.getMethods(); for (Method method : methods) { System.out.println("method = " + method); } System.out.println("--------"); // 获取该类指定的公共成员方法 Method method = s.getMethod("method1"); System.out.println("method1 = " + method); System.out.println("--------"); // 获取该类所有的成员方法(不包括继承的) Method[] declaredMethods = s.getDeclaredMethods(); for (Method declaredMethod : declaredMethods) { System.out.println("declaredMethod = " + declaredMethod); } System.out.println("--------"); // 获取该类指定的成员方法 Method method1 = s.getDeclaredMethod("method1"); Method method2 = s.getDeclaredMethod("method2"); Method method3 = s.getDeclaredMethod("method3"); Method method4 = s.getDeclaredMethod("method4"); System.out.println("method1 = " + method1 + "\nmethod2 = " + method2 + "\nmethod3 = " + method3 + "\nmethod4 = " + method4); } }
运行:
method = public java.lang.String A_11_reflect.Student.toString() method = public void A_11_reflect.Student.method1() method = public final void java.lang.Object.wait() throws java.lang.InterruptedException method = public final void java.lang.Object.wait(long,int) throws java.lang.InterruptedException method = public final native void java.lang.Object.wait(long) throws java.lang.InterruptedException method = public boolean java.lang.Object.equals(java.lang.Object) method = public native int java.lang.Object.hashCode() method = public final native java.lang.Class java.lang.Object.getClass() method = public final native void java.lang.Object.notify() method = public final native void java.lang.Object.notifyAll() -------- method1 = public void A_11_reflect.Student.method1() -------- declaredMethod = public java.lang.String A_11_reflect.Student.toString() declaredMethod = public void A_11_reflect.Student.method1() declaredMethod = protected void A_11_reflect.Student.method2() declaredMethod = void A_11_reflect.Student.method3() declaredMethod = private void A_11_reflect.Student.method4() -------- method1 = public void A_11_reflect.Student.method1() method2 = protected void A_11_reflect.Student.method2() method3 = void A_11_reflect.Student.method3() method4 = private void A_11_reflect.Student.method4()
类名:Method
包名:java.lang.reflect.Method
修饰符和类型 | 成员方法 | 描述 |
---|---|---|
Object | invoke(Object obj, Object... args) | obj:调用方法的对象,args:方法的参数 |
测试:
public class Test_07 { public static void main(String[] args) throws Exception { Class<Student> s = Student.class; // 获取类的无参构造方法 Constructor<Student> constructor = s.getConstructor(); // 实例化 Student student = constructor.newInstance(); // 调用方法 Method[] declaredMethods = s.getDeclaredMethods(); for (Method declaredMethod : declaredMethods) { declaredMethod.setAccessible(true); // 取消私有成员方法访问检查 declaredMethod.invoke(student); } } }
运行:
protected成员方法:method2 default成员方法:method3 private成员方法:method4 public成员方法:method1
需求:往 ArrayList<Integer>
集合中添加字符串数据。
示例:
// 越过泛型检查 public class Test_08 { public static void main(String[] args) throws Exception { ArrayList<Integer> arrayList = new ArrayList<>(); arrayList.add(1); arrayList.add(2); arrayList.add(3); System.out.println("arrayList = " + arrayList); Class<? extends ArrayList> arrayListClass = arrayList.getClass(); Method add = arrayListClass.getMethod("add", Object.class); add.invoke(arrayList, "张三"); add.invoke(arrayList, "李四"); add.invoke(arrayList, "王五"); System.out.println("arrayList = " + arrayList); } }
运行:
arrayList = [1, 2, 3] arrayList = [1, 2, 3, 张三, 李四, 王五]
需求:通过 properties.txt 配置文件运行类中的方法。
示例:
className=A_11_reflect/demo/Student methodName=study parameter=张三
public class Student { public void study(String name) { System.out.println(name + "同学爱学习!"); } }
public class Teacher { public void study(String name) { System.out.println(name + "老师爱学习!"); } }
测试:
public class Test_01 { public static void main(String[] args) throws Exception { // 加载数据 Properties p = new Properties(); // 读取配置 FileReader fr = new FileReader(".\\properties.txt"); p.load(fr); fr.close(); // 获取类名 String className = p.getProperty("className"); // 获取方法名 String methodName = p.getProperty("methodName"); // 获取参数 String parameter = p.getProperty("parameter"); // 反射获取类的实例 Class<?> clazz = Class.forName(className); // 获取类的构造方法 Constructor<?> con = clazz.getConstructor(); // 类实例化 Object o = con.newInstance(); // 获取方法对象,指定参数类型 Method m = clazz.getMethod(methodName, String.class); // o对象调用m方法传入parameter参数 m.invoke(o, parameter); System.out.println("o = " + o); } }
运行:
张三同学爱学习!