javaSE_反射

反射就是可以通过程序动态的去修改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> 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;

}

}

2. 解析构造函数

获取所有构造函数:

//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);

 

3. 解析属性

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;

}

 

4. 解析方法

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;

}

}

 

5. 解析注解

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

创建一个自定义类:

// @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
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值