javaSE_反射

以你之姓@ 2022-05-25 03:17 210阅读 0赞

反射就是可以通过程序动态的去修改jvm虚拟机已经加载好的方法区里面的属性、成员变量。

通过反射获取类:

Class clz = Class.forName(“com.gary.model.Student”);

  1. 创建对象

通过类创建对象:

Student obj = (Student) clz.newInstance();// 通过类创建对象

通过构造函数创建对象:

System.out.println(“—————获取不带参构造函数-—————“);

Constructor constructor1 = clz.getDeclaredConstructor();

Student object1 = (Student) constructor1.newInstance();// 通过构造函数创建对象

System.out.println(object1.getName());

System.out.println(“—————获取带参构造函数-—————“);

Constructor constructor2 = clz.getDeclaredConstructor(String.class, Integer.class);

Student object2 = (Student) constructor2.newInstance(“gary”, 20);

System.out.println(object2.getName());

System.out.println(“—————封装泛型,通过类创建对象-—————“);

Student object3 = ReflectUtils.getObject(clz, “mary”, 22);

System.out.println(object3.getName());

输出:

-————-获取不带参构造函数-—————

null

-————-获取带参构造函数-—————

gary

-————-封装泛型,通过类创建对象-—————

mary

public class ReflectUtils {

// 通过包名创建class

public static Class getClass(String className){

try {

return Class.forName(className);

} catch (ClassNotFoundException e) {

e.printStackTrace();

}

return null;

}

// 通过class创建对象

public static T getObject(Class clz, Object…params){

try {

Class[] types = new Class[params.length];

for (int i = 0; i < params.length; ++i){

types[i] = params[i].getClass();

}

Constructor constructor = clz.getDeclaredConstructor(types);

return (T) constructor.newInstance(params);

} catch (Exception e) {

e.printStackTrace();

}

return null;

}

}

  1. 解析构造函数

获取所有构造函数:

//Constructor[] constructors = clz.getConstructors();// 只能访问public的构造函数

Constructor[] constructors = clz.getDeclaredConstructors();// 访问所有修饰符的构造函数

for (Constructor constructor : constructors){

System.out.println(“构造函数名称:” + constructor.getName());

System.out.println(“构造函数修饰符:” + constructor.getModifiers());

Class[] types = constructor.getParameterTypes();

for (Class class1 : types){

System.out.print(class1.getName() + “\t”);

}

}

输出:

构造函数名称:com.gary.model.Student

构造函数修饰符:1

构造函数名称:com.gary.model.Student

构造函数修饰符:1

java.lang.Stringjava.lang.Integer

可见有两个构造函数,一个无参一个有参。

获取单个构造函数:

Constructor constructor1 = clz.getDeclaredConstructor();

Constructor constructor2 = clz.getDeclaredConstructor(String.class, Integer.class);

  1. 解析属性

public static void Reflect_Field(){

System.out.println(“—————field—————“);

try {

Class clz = Class.forName(“com.gary.model.Student”);

Student stu = (Student) clz.newInstance();

stu.setAge(31);

// 获取所有属性

Field[] fields = clz.getDeclaredFields();

for (Field field : fields){

System.out.println(“修饰符:” + field.getModifiers());

System.out.println(“类型:” + field.getType());

System.out.println(“名称:” + field.getName());

System.out.println(“————————————“);

}

// 通过属性名获取属性

Field field = clz.getDeclaredField(“age”);

System.out.println(“通过名称获取的属性名:” + field.getName());

field.setAccessible(true);// 获取私有成员必须添加此设置

System.out.println(“获取对象的值:” + field.get(stu));

} catch (Exception e) {

e.printStackTrace();

}

}

其中student类属性如下:

public class Student {

private Integer age;

protected String name;

}

输出:

-————-field—————

修饰符:2

类型:class java.lang.Integer

名称:age

-———————————-

修饰符:4

类型:class java.lang.String

名称:name

-———————————-

通过名称获取的属性名:age

获取对象的值:31

// 获取对象的某一成员变量值(一般都是通过方法获取,很少直接获取变量的)

public static Object getPropertyValue(Object obj, String fieldName){

Class clz = obj.getClass();

try {

Field field = clz.getDeclaredField(fieldName);

field.setAccessible(true);

return field.get(obj);

} catch (Exception e) {

e.printStackTrace();

}

return null;

}

  1. 解析方法

public static void Reflect_Method(){

System.out.println(“—————method—————“);

try {

Class clz = Class.forName(“com.gary.model.Student”);

// 获取所有方法

Method[] methods = clz.getDeclaredMethods();

for (Method method : methods){

System.out.println(“修饰符:” + method.getModifiers());

System.out.println(“名称:” + method.getName());

System.out.println(“返回类型:” + method.getReturnType());

Class[] parameters = method.getParameterTypes();

for (Class parameter : parameters){

System.out.println(“参数类型:” + parameter.getName());

}

System.out.println(“————————————“);

}

// 获取某一具体方法

Method method = clz.getDeclaredMethod(“setAge”, Integer.class);

System.out.println(“获取具体方法名:” + method.getName());

Student student = (Student) clz.newInstance();

// 执行方法

method.invoke(student, 22);

System.out.println(student.getAge());

} catch (Exception e) {

e.printStackTrace();

}

}

封装一下获取函数:

public class ReflectUtils {

// 通过方法名获取方法

public static Method getMethod(Class clz, String methodName, Class…parameterTypes){

try {

return clz.getDeclaredMethod(methodName, parameterTypes);

} catch (Exception e) {

e.printStackTrace();

}

return null;

}

// 通过成员变量名获取其et方法

public static Method getMethod_FieldGet(Class clz, String fieldName){

try {

Field field = clz.getDeclaredField(fieldName);

String methodName = fieldName.substring(0,1).toUpperCase() + fieldName.substring(1);

return getMethod(clz, “get”+methodName);

} catch (Exception e) {

e.printStackTrace();

}

return null;

}

// 通过成员变量名获取其set方法

public static Method getMethod_FieldSet(Class clz, String fieldName){

try {

Field field = clz.getDeclaredField(fieldName);

String methodName = fieldName.substring(0,1).toUpperCase() + fieldName.substring(1);

return getMethod(clz, “set”+methodName, field.getType());

} catch (Exception e) {

e.printStackTrace();

}

return null;

}

}

  1. 解析注解

自定义一个注解类,将此注解添加到类上、属性上、方法上等等,就可以通过类拿到注解的信息。

创建一个自定义类:

// @Documented说明该注解将被包含在javadoc中

@Documented

// @Retention指定编译器对自定义注解的策略

@Retention(value=RetentionPolicy.RUNTIME)

// @Target指定此注解的使用范围

@Target({

ElementType.TYPE,// 接口、类、枚举、注解

ElementType.FIELD,// 字段、枚举的常量

ElementType.METHOD,// 方法

ElementType.PARAMETER,//方法参数

ElementType.CONSTRUCTOR,// 构造函数

ElementType.LOCAL_VARIABLE,// 局部变量

ElementType.ANNOTATION_TYPE,// 注解

ElementType.PACKAGE // 包

})

public @interface LogMapping {

String value() default “”;// 值

String desc() default “”;// 描述

boolean mark() default true;// 标记

}

在user类上添加注解:

@LogMapping(desc=”用户类”)

public class User {

private String id;

@LogMapping(value=”name”, desc=”姓名”)

private String name;

@LogMapping(value=”age”, desc=”年龄”)

private Integer age;

@LogMapping(desc=”构造函数”)

public User() {

}

@LogMapping(value=”getId”, desc=”获取主键”)

public String getId() {

return id;

}

@LogMapping(value=”setId”, desc=”设置主键”)

public void setId(@LogMapping(desc=”id参数”) String id) {

this.id = id;

}

}

测试代码,解析注解:

// 注解

public static void Reflect_Annotation(){

System.out.println(“————— 注解-————-“);

try {

Class clz = Class.forName(“com.gary.model.User”);

// 获取类的注解

LogMapping logMapping = (LogMapping) clz.getAnnotation(LogMapping.class);

if (logMapping != null){

System.out.println(“类上注解:” + logMapping.desc());

}

// 构造函数的注解

Constructor[] constructors = clz.getDeclaredConstructors();

for (Constructor constr : constructors){

logMapping = (LogMapping) constr.getAnnotation(LogMapping.class);

if (logMapping != null){

System.out.println(“构造函数注解:” + logMapping.desc());

}

}

// 方法上的注解

Method[] methods = clz.getDeclaredMethods();

for (Method method : methods){

logMapping = (LogMapping) method.getAnnotation(LogMapping.class);

if (logMapping != null){

System.out.println(“方法上的注解:” + logMapping.desc());

}

// 参数里的注解

Annotation[][] annotations = method.getParameterAnnotations();

for (Annotation[] annotation : annotations){

for (Annotation anno : annotation){

logMapping = (LogMapping) anno;

if (logMapping != null){

System.out.println(“参数里的注解:” + logMapping.desc());

}

}

}

}

// 属性上的注解

Field[] fields = clz.getDeclaredFields();

for (Field field : fields){

logMapping = (LogMapping) field.getAnnotation(LogMapping.class);

if (logMapping != null){

System.out.println(“属性上的注解:” + logMapping.desc());

}

}

}catch (Exception e){

e.printStackTrace();

}

}

输出:

-————- 注解-————-

类上注解:用户类

构造函数注解:构造函数

方法上的注解:获取主键

方法上的注解:设置主键

参数里的注解:id参数

属性上的注解:姓名

属性上的注解:年龄

发表评论

表情:
评论列表 (有 0 条评论,210人围观)

还没有评论,来说两句吧...

相关阅读

    相关 JavaSE——反射内容大全

    一、类加载 当程序要使用某个类时,如果该类还未被加载到内存中,则系统会通过类的加载,类的连接,类的初始化这三个步骤来对类进行初始化。 不出现意外情况,JVM将会连续完成

    相关 JavaSE反射

    一、概念 反射是在运行期间,动态获取对象的属性和方法 二、相关的类 在Java的反射里主要有以下几个类:Class类,这是反射的起源,反射必须要先获取Class对

    相关 javaSE--7反射机制

    一、反射机制 1.反射机制的作用 通过java语言中的反射机制可以操作字节码文件(类似于黑客,可以读和写字节码文件) 可以操作代码片段(class文件) 反射机

    相关 JavaSE 反射机制

    反射机制是什么 反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调

    相关 javaSE_反射

    反射就是可以通过程序动态的去修改jvm虚拟机已经加载好的方法区里面的属性、成员变量。 通过反射获取类: Class clz = Class.forName("com.gar