java反射 实例属性_JAVA反射实例详解

一:反射

反射是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性。

使用java的反射,一般有下面三步:

1:获得你想操作类的Class对象

2:通过第一步获得的Class对象去取得操作类的方法或是属性名

3:操作第二步取得的方法或是属性

二:例子

Java的反射机制中类有Class对应,类的方法有Method对应,当然属性也有Field与之对应。

2.1 通过反射获取当前类和父类的相关属性

public class GetOtherClassFiled {

public static void main(String[] args) throws ClassNotFoundException {

Class> demo = Class.forName("com.tanjie.reflect.Persons");

System.out.println("获取当前类的所有属性:=========================");

Field field[] = demo.getDeclaredFields();

for(int i=0;i

int mo = field[i].getModifiers();

//修饰符

String prev = Modifier.toString(mo);

//属性类型

Class> type = field[i].getType();

System.out.println(prev + " " + type.getName() + " " + field[i].getName());

}

System.out.println("实现的父类接口属性:============================");

Field field2[] = demo.getFields();

for(int j=0;j

int mo = field2[j].getModifiers();

String prev = Modifier.toString(mo);

Class> type = field2[j].getType();

System.out.println(prev + " " + type.getName() + " " + field2[j].getName());

}

}

}

运行结果:

获取当前类的所有属性:=========================

private java.lang.String name

实现的父类接口属性:============================

public static final java.lang.String name

2.2 获取类的相关属性,构造函数,接口

public class ClassImplesWhichInterface {

public static void main(String[] args) throws Exception {

Class> demo = Class.forName("com.tanjie.reflect.Persons");

//获取接口类

Class> interfaces[] = demo.getInterfaces();

//获取父类

Class> parents = demo.getSuperclass();

//获取所有的构造函数

Constructor> constructors[] = demo.getConstructors();

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

System.out.println("实现了哪些接口类:" + interfaces[i].getName());

}

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

System.out.println("类有哪些构造函数:" + constructors[i]);

}

System.out.println("继承的父类:" + parents.getName());

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

Class> paramenter[] = constructors[i].getParameterTypes();

int mo = constructors[i].getModifiers();

System.out.println(Modifier.toString(mo) + " " + constructors[i].getName());

for(int j=0;j

System.out.println(paramenter[j].getName());

}

}

}

}

运行结果:

实现了哪些接口类:com.tanjie.reflect.Parents

类有哪些构造函数:public com.tanjie.reflect.Persons()

类有哪些构造函数:public com.tanjie.reflect.Persons(java.lang.String)

继承的父类:java.lang.Object

public com.tanjie.reflect.Persons

public com.tanjie.reflect.Persons

java.lang.String

三:实际应用

上面2个列子我们熟悉了反射常用的方式,记不住的时候,翻翻api就会使用了,反射对应的方法都简单明了,下面我们来看一个具体在项目中利用反射的例子。

假如我们有这样一个需求,在你的程序中,常常有一些定义错误码的枚举类,而错误编码怎样才能保证不会被重复定义呢,如果每次定义的时候都去手动检查一下肯定是非常麻烦的,我们可以利用反射来实现动态的错误码检测。

3.1 定义一个注解类

@Retention(RetentionPolicy.RUNTIME)

@Target(ElementType.TYPE)

public @interface EnumTag {

String name();

}

RetentionPolicy.RUNTIME:表示在源码,编译后的.class都保存信息,在执行的时候也会把这些信息加载到JVM中。

@Target里面的ElementType是用来制定Annotation可以用在那一种类型。

3.2 定义枚举类

@EnumTag(name = "errorEnum")

public enum ErrorEnum {

JAVA_TIME_OUT(1000),

ZOOKEEPER_TIME_OUT(2000);

private final int errorCode;

private final String errMessage;

/**

* 枚举类构造函数,初识化

*

* @param errorCode

* errorCode

*/

private ErrorEnum(int errorCode) {

this.errorCode = errorCode;

this.errMessage = "System Error";

}

public int getErrorCode() {

return errorCode;

}

public String getErrMessage() {

return errMessage;

}

public static List getErrorCodes() {

List errorCodeList = new ArrayList();

for (final ErrorEnum em : ErrorEnum.values()) {

int code = em.getErrorCode();

errorCodeList.add(code);

}

return errorCodeList;

}

}

3.3 定义bean

public class ValidateEnumMark implements InitializingBean {

private List errorList;

public ValidateEnumMark() {

errorList = new ArrayList();

}

/**

*

* 在初始化之前做的事情通过@PostConstruct和 @PreDestroy方法实现初始化和销毁bean之前进行的操作

*

* @throws SecurityException

* @throws NoSuchMethodException

* @throws InvocationTargetException

* @throws IllegalArgumentException

* @throws IllegalAccessException

*

*/

@SuppressWarnings("unchecked")

@PostConstruct

public void validate() throws NoSuchMethodException, SecurityException,

IllegalAccessException, IllegalArgumentException,

InvocationTargetException {

Reflections reflections = new Reflections(

"com.tanjie.reflect.application");

Set> sets = reflections.getTypesAnnotatedWith(EnumTag.class);

for (Class> demo : sets) {

// 通过反射获取指定方法

Method method = demo.getDeclaredMethod("getErrorCodes",

new Class[] {});

// 通过反射调用其它类的方法

List list = (List) method.invoke(demo,

new Object[] {});

if (null != list && !list.isEmpty()) {

for (Integer integer : list) {

if (errorList.contains(integer)) {

System.out.println("错误编码重复");

} else {

errorList.add(integer);

}

}

}

}

System.out.println("目前服务中定义的错误码有:" + errorList);

}

@Override

public void afterPropertiesSet() throws Exception {

System.out.println("校验完成.....");

}

}

在spring的配置文件里面

class="com.tanjie.reflect.application.ValidateEnumMark" />

完成上面的配置后,spring容器在启动时,首先就会检测你整个程序中是否存在重复定义的错误码了。

4:反射的性能

反射不太好的地方就是性能了,因为通过反射来获取字段或者方法比直接使用java代码要慢很多,但是这也得看反射用在什么地方,在一个大项目中,如果反射仅仅用在无关紧要的,不影响性能的地方,那么这点性能的丢失也就无关紧要了。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值