java的反射和注解
好记性不如烂笔头
- 反射就是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法,对于任意一个对象,都能够调用它的任意一个方法和属性,这种动态获取的信息以及动态调用对象的方法的功能。
- 注解就是一种代码级别的说明,它是JDK1.5及以后版本引入的一个特性,与类、接口、枚举是在同一个层次。它可以声明在包、类、字段、方法、局部变量、方法参数等的前面,用来对这些元素进行说明,注释。
反射
- 首先要通过对象获得类。java中提供了Class类(其对象表示正在运行的 Java 应用程序中的类和接口,Class 没有公共构造方法。Class 对象是在加载类时由 Java 虚拟机以及通过调用类加载器中的 defineClass 方法自动构造的。
1. Class<?> c=Class.forName("java.lang.Integer");参数为完整的包名+类名。
2. Class<?> c=Integer.class;
3. Class<?> c=integer.getClass();integer为对象
- 接着通过Class中的方法获得相应的类Field,MMethod,Constructor。
方法 | 解释 |
---|---|
getFields() | 获得类的所有属性除了private返回Field[] |
getDeclaredFields() | 获得类的所有属性返回Field[] |
…..其他的都是相似的查询API
通过Class类的newInstance()方法重新获得对象。
通过反射得到相应的属性值时,如field.get(people);获得People类中所有的属性,但是当有属性为private时(前提是是通getDeclaredFields()),就会报错。这是因为了java有封装性是通过java语言检查的。为了将这个检查关闭,可使用f.setAccessiable(true);将反射的对象标记为在使用时取消默认Java 语言访问控制检查的能力。Field,Method,Constructor类都继承自AccessibleObject;
注解
元注解用来注释其他注解的。
@Targe是可以注释类,方法,等等。规定类的作用范围。(ElementType.Field)
- CONSTRUCTOR:用于描述构造器
- FIELD:用于描述域
- LOCAL_VARIABLE:用于描述局部变量
- METHOD:用于描述方法
- PACKAGE:用于描述包
- PARAMETER:用于描述参数
- TYPE:用于描述类、接口(包括注解类型)
@Retention用来注释annotation保留时间。
- SOURCE:在源文件中有效(即源文件保留)
- CLASS:在class文件中有效(即class保留)
- RUNTIME:在运行时有效(即运行时保留)
- @Document。Documented是一个标记注解,没有成员。
- @Inherited阐述了某个被标注的类型是被继承的。如果一个使用了@Inherited修饰的annotation类型被用于一个class,则这个annotation将被用于该class的子类。
自定义注解接口
/**
* 元注解,用来注释其他注解的。
* @Targe是可以注释类,方法,等待。规定类的作用范围
* @Retention用来注释 annotation保留时间
* @author wulei
*
*/
@Target(ElementType.FIELD) //作用范围是,属性
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface MyAnnotation {
String value() default "example";
}
测试代码
package com.wulei.reflect;
import java.lang.reflect.Field;
public class Test {
public static void main(String[] args){
People p=new People("levi",21,"男");//实例化一个对象
//Class<?> c=p.getClass();//获得class对象
Class<?> c=com.wulei.reflect.People.class;
try {
//getFields()是获得可访问的public字段,
//而getDeclaredFields返回的是所有字段(public default protected,private)
Field[] field=c.getDeclaredFields();
for(Field f:field){
System.out.println(f.isAccessible()+"");//false表示不可访问,如serializable持久化的类
//提供了将反射的对象标记为在使用时取消默认 Java 语言访问控制检查的能力。
f.setAccessible(true);
//判断是否是被myAnnotation标记的类
if(f.isAnnotationPresent(MyAnnotation.class) && f.getType()==String.class){
//System.err.println(f.getAnnotation(MyAnnotation.class).value());
//使用注解来标记打印,想要打印的值
if(f.getAnnotation(MyAnnotation.class).value().equals("sex")){
String name=(String) f.get(p);
System.out.println("name---"+name);
}
}else{
int i=f.getInt(p);
System.out.println("age--"+i);
}
}
People p1=(People) c.newInstance();
p1.setAge(21);
p1.setName("levi");
System.out.println(p1.toString()+"......"+p.toString());
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}