Java中的反射
发布日期:2021-05-07 06:54:33 浏览次数:15 分类:精选文章

本文共 3331 字,大约阅读时间需要 11 分钟。

1. Java Reflection简介

反射机制允许程序在执行期借助于Reflection API取得任何类的内部信息

并能直接操作任意对象的内部属性及方法

在类加载之后,在堆内存的方法区中就产生了一个Class类型的对象(一个类只有一个Class对象)

这个对象包含了完整的类的结构信息,我们可以利用反射机制,通过这个对象看到类的结构

反射机制涉及JVM、classLoader(类加载器),下面的内容只探讨使用反射,不深入底层原理

2. 反射的优缺点

优点:可以实现动态创建对象和编译,体现出很大的灵活性

缺点:对性能有影响,使用反射基本上是一种解释操作,我们可以告诉JVM,我们希望做什么并且它满足我们的要求,这类操作总是慢于直接执行相同的操作。

3. 获取Class对象的方法

首先定义一个User对象(并加上get set 有参无参构造函数)

class User{       int id;    String name;}

①已知具体的类,通过类的class属性获取,该方法最安全可靠,性能最高

Class c1 = User.class; //通过类的class属性去获取Class对象

②已知某个类的实例, 调用该实例的getClass()方法获取Class对象

User user = new User();Class c2 = user.getClass(); //通过类的一个实例获取Class对象

③已知一个类的全类名,且该类在类路径下,可通过Class类的静态方法forName()获取Class对象

Class c3 = Class.forName("com.Reflection.User"); //通过类的路径和类名获取对象

4. 通过Class对象获取类的信息

Class c = Class.forName("com.Reflection.User");

① 获得类的名字

System.out.println(c.getName());//包名+类名System.out.println(c.getSimpleName()); //类名

② 获得类的属性

Field fields[] = c.getFields(); //获得类的所有public属性fields = c.getDeclaredFields(); //获得类的所有属性  Field field = c.getField("id"); //获得指定的属性,传入参数为属性名

③ 获得类的方法

Method methods[] = c.getMethods(); //获得类的所有方法Method method1 = c.getMethod("getName"); //获得类的指定方法Method method2 = c.getMethod("setName", String.class);

④ 获得类的构造器方法

Constructor constructors[] = c.getConstructors(); //获得所有的构造器方法Constructor constructor1 = c.getConstructor(); //获得类的无参构造器Constructor constructor2 = c.getConstructor(int.class,String.class); //获得类的有参构造器

5. 通过反射机制构造一个类的对象

User user = (User) c.getDeclaredConstructor().newInstance(); // 本质是调用无参构造器user = (User) constructor2.newInstance(123,"小明"); // 通过有参构造器创建对象

6. 通过反射调用函数方法

invoke : 激活

invoke()参数 (对象,方法的值) ,返回值为Object

user = (User) constructor2.newInstance(123,"小明"); // 通过有参构造器创建对象Method setName = c.getMethod("setName", String.class);setName.invoke(user,"小丑");System.out.println(user.getName()); // 输出为小丑

7. 通过反射操作属性

Field userName = c.getDeclaredField("name");//不能直接操作私有属性,但是可以通过setAccessible(true)关闭权限userName.setAccessible(true);userName.set(user,"打工人"); //调用set方法修改属性(obj,value)System.out.println(user.getName()); //输出为打工人

8. 通过反射操作注解信息

1.先创建自定义注解

//自定义类的注解@Target(ElementType.TYPE)@Retention(RetentionPolicy.RUNTIME)@interface ClassAnnotation {       String value() default "";}//自定义属性的注解@Target(ElementType.FIELD)@Retention(RetentionPolicy.RUNTIME)@interface FieldAnnotation{       String columnName(); //列名    String type(); //类型    int length(); //长度}

2.创建一个User类并使用注解

@ClassAnnotation("db_User")class User {       @FieldAnnotation(columnName = "编号",type = "int",length = 10)    int id;    @FieldAnnotation(columnName = "年龄",type = "int",length = 2)    int age;    @FieldAnnotation(columnName = "姓名",type = "String",length = 4)    String name;}

3.通过反射获取类的注解信息

Class c = Class.forName("com.ReToAnno.User"); Annotation[] annotations = c.getAnnotations(); // 通过反射获得类所有的注解 // 获得指定的类的注解 ClassAnnotation classAnnotation = (ClassAnnotation) c.getDeclaredAnnotation(ClassAnnotation.class); // 获得注解的value值 String value = classAnnotation.value(); System.out.println(value); //输出为"db_User" // 获得指定的类的属性注解 Field id = c.getDeclaredField("id"); // 通过反射获得id属性 FieldAnnotation IdAnnotation = id.getAnnotation(FieldAnnotation.class); //获得了指定属性的注解 // 输出id属性的注解内的值 System.out.println(IdAnnotation.columnName()); //输出为"编号" System.out.println(IdAnnotation.type()); //输出为"int" System.out.println(IdAnnotation.length()); //输出为"10"
上一篇:Java中的注解
下一篇:括号序列

发表评论

最新留言

感谢大佬
[***.8.128.20]2025年03月28日 08时05分28秒