通过反射来剖析类的构成
程序员文章站
2024-01-20 16:02:46
...
类的构成:
构造方法:Constructor
成员变量:Field
成员方法:Method
获取构造方法对象;
//先获取到该类的字节码文件对象
Class clazz = Class.forName("org.westos.demo2.Student");
//getConstructors():获取该类中所有的构造方法对象,私有的除外
Constructor[] constructors = clazz.getConstructors();
for (Constructor constructor : constructors) {
System.out.println(constructor);
}
//getDeclaredConstructors(); 获取所有的构造方法对象,包括私有的
Constructor[] declaredConstructors = clazz.getDeclaredConstructors();
for (Constructor declaredConstructor : declaredConstructors) {
System.out.println(declaredConstructor);
}
//获取空参的构造方法对象
Constructor constructor = clazz.getConstructor();
//获取一个参数的构造方法对象,传入参数的class类型,不能获取私有的
Constructor constructor1 = clazz.getConstructor(String.class);
//获取私有的构造方法对象getDeclaredConstructor(String.class, int.class);
Constructor constructor2 = clazz.getDeclaredConstructor(String.class, int.class);
student类:
public class Student {
public Student(){
System.out.println("空参构造");
}
public Student(String name) {
System.out.println("有参构造"+name);
}
private Student(String name,int age) {
System.out.println("私有的有参构造" + name+"==="+age);
}
}
同上的应用:
//获取该类的字节码文件对象
Class aClass = Class.forName("org.westos.demo2.Student");
//获取空参的构造方法对象
Constructor constructor = aClass.getConstructor();
//通过构造方法对象中的 newInstance() 来创建出该类的一个实例
Student obj = (Student) constructor.newInstance();
//通过有参构造来创建该类的实例
Constructor constructor1 = aClass.getConstructor(String.class);
Object o = constructor1.newInstance("张三");
//通过私有的构造创建该类的对象
Constructor declaredConstructor = aClass.getDeclaredConstructor(String.class, int.class);
declaredConstructor.setAccessible(true); //取消语法检测
Object o1 = declaredConstructor.newInstance("王五", 25);
获取类的字段对象:
//获取该类的字节码文件对象
Class aClass = Student.class;
//获取类中的所有的字段对象
Field[] fields = aClass.getFields();
for (Field field : fields) {
System.out.println(field);
}
//getDeclaredFields() 获取类中所有的字段对象,包括私有
Field[] declaredFields = aClass.getDeclaredFields();
for (Field declaredField : declaredFields) {
System.out.println(declaredField);
}
//获取单个的字段
Field name = aClass.getField("name");
//获取私有的字段对象
Field sex = aClass.getDeclaredField("sex");
student类:
public class Student {
public String name;
public int age;
private char sex;
}
同上的应用:
//获取字节码文件对象
Class<?> aClass = Class.forName("org.westos.demo3.Student");
Field field = aClass.getField("name");
Object obj = aClass.getConstructor().newInstance();
//给字段设置值
field.set(obj,"张三");
//获取字段的值
Object o = field.get(obj);
//给私有字段设置值
Field sex = aClass.getDeclaredField("sex");
//对于私有可以取消语法检测
sex.setAccessible(true);
sex.set(obj,'男');
Object o1 = sex.get(obj);
Character character= (Character) o1;
获取方法对象:
Class<?> aClass = Class.forName("org.westos.demo4.Student");
//获取所有的方法对象,包括父类的方法对象,私有除外
Method[] methods = aClass.getMethods();
for (Method method : methods) {
System.out.println(method.getName());
}
//获取该类的所有方法对象,包括私有的方法
Method[] declaredMethods = aClass.getDeclaredMethods();
for (Method declaredMethod : declaredMethods) {
System.out.println(declaredMethod);
}
//获取单个的方法对象,参数1,方法名;参数2:这个方法上的参数的字节码类型
Method hehe = aClass.getMethod("hehe");
System.out.println(hehe);
Method haha = aClass.getMethod("haha", String.class);
System.out.println(haha);
Method test = aClass.getMethod("test", String.class,int.class);
System.out.println(test);
//获取私有的方法对象
Method method = aClass.getDeclaredMethod("method", String.class, int.class);
System.out.println(method);
public class Student {
public void test(){
System.out.println("这是一个空参方法");
}
public int test(String name) {
System.out.println("这是一个参数方法");
return 100;
}
public int test(String name,int a) {
System.out.println("这是两个参数的方法");
return 100+a;
}
private int method(String name, int a) {
System.out.println("这是一个私有的方法");
return 100 + a;
}
}
应用:
//通过反射机制,调用类中的方法执行
Class<?> aClass = Class.forName("org.westos.demo4.Student");
//获取该方法的对象
Method test = aClass.getMethod("test");
Object obj = aClass.getConstructor().newInstance();
//通过方法对象中的 invoke() 让这个方法执行
test.invoke(obj);
Method haha = aClass.getMethod("test", String.class);
//让一个参数的方法 执行 也可以拿到该方法的返回值
Object o1 = haha.invoke(obj, "王五");
//让两个参数的方法执行
Method test1 = aClass.getMethod("test", String.class, int.class);
Object o2 = test1.invoke(obj, "张三", 23);
//让私有的方法执行
Method method = aClass.getDeclaredMethod("method", String.class, int.class);
method.setAccessible(true);//取消语法检测
Object value = method.invoke(obj, "李四", 24);
应用实例:
//基于狗类开发
Properties properties = new Properties();
//从配置文件中读取全限定名和方法名,易于修改,方便维护;
properties.load(new FileInputStream("peizhi.properties"));
//属性集合读取指定键对应的类名;
String className = properties.getProperty("className");
//获取类字节码文件对象;
Class<?> aClass = Class.forName(className);
//如果你使用空参构造来创建对象
//Class对象里面newInstance()这个方法,可以创建该类的对象
Object o1 = aClass.newInstance();
Method methodName = aClass.getDeclaredMethod(properties.getProperty("methodName"));
methodName.invoke(o1);
狗类:
public class Dog {
public void eat(){
System.out.println("狗吃骨头");
}
public void sleep() {
System.out.println("狗睡觉");
}
}
下图是配置文件内容:
另外,泛型只在编译器有效,运行期就自动擦除了,应用如下:
//ArrayList<Integer> 想在这个集合中添加一个字符串数据,如何实现呢?
ArrayList<Integer> integers = new ArrayList<>();
integers.add(100);
//越过泛型检测,只能在运行期,反射在运行期的一种机制
Class<? extends ArrayList> aClass = integers.getClass(); //ArrayList.class
Method add = aClass.getDeclaredMethod("add", Object.class);
add.invoke(integers,"abc");
System.out.println(integers);
上一篇: 虚拟机的前世今生和JVM内存区域
下一篇: Edius编辑视频怎么撤销上一步操作?