程序在运行中也可以获取类的变量和方法信息,并通过获取到的信息来创建对象。程序不必再编译期就完成确定,在运行期仍然可以扩展。
示例:学生类
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></t>
包名: java.lang.Class<t></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 s1 = Student.class;
// 对象.getClass()
Student student = new Student();
Class 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
3.1、获取构造方法
修饰符和类型 方法 秒速 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 s = Student.class;
// 获取该类所有的公共构造方法
Constructor[] constructors = s.getConstructors();
for (Constructor constructor : constructors) {
System.out.println("constructor = " + constructor);
}
System.out.println("--------");
// 获取该类指定的公共构造方法
Constructor c1 = s.getConstructor();
Constructor 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 c3 = s.getDeclaredConstructor();
Constructor c4 = s.getDeclaredConstructor(String.class);
Constructor c5 = s.getDeclaredConstructor(String.class, String.class);
Constructor c6 = s.getDeclaredConstructor(String.class, String.class, String.class);
Constructor 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()
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()
name1 = public java.lang.String A_11_reflect.Student.name
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
4.2、调用成员变量
类名: 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 s = Student.class;
// 先获取所有成员变量
Field name = s.getDeclaredField("name");
Field pwd = s.getDeclaredField("pwd");
Field sex = s.getDeclaredField("sex");
Field age = s.getDeclaredField("age");
// 调用无参构造方法
Constructor 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}
method1 = public void A_11_reflect.Student.method1()
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()
5.2、调用成员方法
类名: 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 s = Student.class;
// 获取类的无参构造方法
Constructor 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
6.1、示例1
需求:往 ArrayList<integer></integer>
集合中添加字符串数据。
示例:
// 越过泛型检查
public class Test_08 {
public static void main(String[] args) throws Exception {
ArrayList arrayList = new ArrayList<>();
arrayList.add(1);
arrayList.add(2);
arrayList.add(3);
System.out.println("arrayList = " + arrayList);
Class 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, 张三, 李四, 王五]
6.2、示例2
需求:通过 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);
}
}
运行:
张三同学爱学习!
Original: https://www.cnblogs.com/bybeiya/p/16251826.html
Author: 北涯
Title: Java — 反射
原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/585897/
转载文章受原作者版权保护。转载请注明原作者出处!