一、概述
反射,指在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法,对任意一个对象,都能调用它的任意一个方法。这种动态获取信息,以及动态调用对象方法的功能,叫做java语言的反射机制。很多框架,比如ORM映射框架Hibernate就大量运用了反射,通过反射可以获取到Entity里配置的表名,字段名,表关系等等,然后生成数据库sql、填充数据等等。
通过反射概括性的可以分为获取属性、获取注解、获取泛型、执行方法、修改属性值等几类。
二、获取属性
给定一个对象,可以获取对象内的属性值,无论是否是私有,都可以获取,示例代码如下:
public static void readAttributeValue(Object obj){
String nameVlues="";
//得到class
Class cls = obj.getClass();
//得到所有属性
Field[] fields = cls.getDeclaredFields();
for (int i=0;i<fields.length;i++){//遍历
try {
//得到属性
Field field = fields[i];
//打开私有访问
field.setAccessible(true);
//获取属性
String name = field.getName();
//获取属性值
Object value = field.get(obj);
//一个个赋值
nameVlues += field.getName()+":"+value+",";
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
}
三、获取注解
写在属性或者类上等其它地方的注解,也可以用反射获取到,示例代码如下:
public static <T> void parseMethod(Class<T> clazz) {
try {
T obj = clazz.newInstance();
for (Method method : clazz.getDeclaredMethods()) {
MyMethodAnnotation methodAnnotation = method.getAnnotation(MyMethodAnnotation.class);
if (methodAnnotation != null) {
// 通过反射调用带有此注解的方法
method.invoke(obj, methodAnnotation.uri());
}
MyClassAndMethodAnnotation myClassAndMethodAnnotation = method
.getAnnotation(MyClassAndMethodAnnotation.class);
if (myClassAndMethodAnnotation != null) {
if (EnumType.util.equals(myClassAndMethodAnnotation.classType())) {
System.out.println("this is a util method");
} else {
System.out.println("this is a other method");
}
System.out.println(Arrays.toString(myClassAndMethodAnnotation.arr()));// 打印数组
System.out.println(myClassAndMethodAnnotation.color());// 输出颜色
}
System.out.println("\t\t-----------------------");
}
} catch (Exception e) {
e.printStackTrace();
}
}
public static <T> void parseType(Class<T> clazz) {
try {
MyClassAndMethodAnnotation myClassAndMethodAnnotation = clazz
.getAnnotation(MyClassAndMethodAnnotation.class);
if (myClassAndMethodAnnotation != null) {
if (EnumType.util.equals(myClassAndMethodAnnotation.classType())) {
System.out.println("this is a util class");
} else {
System.out.println("this is a other class");
}
}
MyClassAnnotation myClassAnnotation = clazz.getAnnotation(MyClassAnnotation.class);
if (myClassAnnotation != null) {
System.err.println(" class info: " + myClassAnnotation.uri());
}
} catch (Exception e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
parseMethod(TestAnnotation.class);
parseType(TestAnnotation.class);
}
四、获取泛型
如果属性或者类有用到泛型,也可以通过反射或者到泛型,示例代码如下:
public static void getType() throws Exception {
Class<GenericTest> clazz = GenericTest.class;
Field f = clazz.getDeclaredField("score");
// 直接使用getType()取出的类型只对普通类型的成员变量有效
Class<?> a = f.getType();
// 下面将看到仅输出java.util.Map
System.out.println("score的类型是:" + a);
// 获得成员变量f的泛型类型
Type gType = f.getGenericType();
// 如果gType类型是ParameterizedType对象
if(gType instanceof ParameterizedType)
{
// 强制类型转换
ParameterizedType pType = (ParameterizedType)gType;
// 获取原始类型
Type rType = pType.getRawType();
System.out.println("原始类型是:" + rType);
// 取得泛型类型的泛型参数
Type[] tArgs = pType.getActualTypeArguments();
System.out.println("泛型信息是:");
for (int i = 0; i < tArgs.length; i++)
{
System.out.println("第" + i + "个泛型类型是:" + tArgs[i]);
}
}
else
{
System.out.println("获取泛型类型出错!");
}
}
五、执行方法
对象内的方法,也可以进行调用,示例代码如下:
public static void invokeMethod() throws NoSuchMethodException, IllegalAccessException, InvocationTargetException {
Foo foo = new Foo("这个一个Foo对象!");
Class clazz = foo.getClass();
Method m1 = clazz.getDeclaredMethod("outInfo");
Method m2 = clazz.getDeclaredMethod("setMsg", String.class);
Method m3 = clazz.getDeclaredMethod("getMsg");
m1.invoke(foo);
m2.invoke(foo, "重新设置msg信息!");
String msg = (String) m3.invoke(foo);
System.out.println(msg);
}
六、修改属性
如果对象没有类似setter、getter的方法,也可以直接修改属性值,示例代码如下:
public static void setField(){
Class<Test> aClass = =Test.class;
Field field = null;
try {
field = aClass.getDeclaredField("a");
//将私有属性开发可修改
field.setAccessible(true);
field.set(this, 1000.0);
Object o = field.get(this);
System.err.println(o);
} catch (NoSuchFieldException | IllegalAccessException e) {
e.printStackTrace();
}
}
有兴趣的大佬大神可以关注下小弟的微信公共号,一起学习交流,扫描以下二维码关注即可。
文章转载自尚浩宇,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。