作用:注解是附加在代码中的一些信息,用于编译、运行时解析和使用,起到说明配置作用
主要学习两方面1 元注解,2 自定义注解
一、元注解
包括:1.@Target, 2.@Retention 3.@Documented, 4.@Inherited 几种
1 @Target
作用:用于描述注解的使用范围(即 注解是描述:包、类、字段、方法、参数、接口等)
取值:1.CONSTRUCTOR:用于描述构造器
2.FIELD:用于描述域
3.LOCAL_VARIABLE:用于描述局部变量
4.METHOD:用于描述方法
5.PACKAGE:用于描述包
6.PARAMETER:用于描述参数
7.TYPE:用于描述类、接口(包括注解类型) 或enum声明
@Target(ElementType.TYPE) //注解用于描述类的
public @interface Table {
/**
* 数据表名称注解,默认值为类名称
* @return
*/
public String tableName() default "className";
}
@Target(ElementType.FIELD) //注解用在字段上
public @interface NoDBColumn {
}
2.@Retention
作用:描述注解的生命周期(1 仅存在源码中,不会被编译 2 存在编译器中,不会在运行中取到 3 存在与类运行期,运行时可以通过反射读取)
取值(RetentionPoicy)有:
1.SOURCE:在源文件中有效(即源文件保留)
2.CLASS:在class文件中有效(即class保留)
3.RUNTIME:在运行时有效(即运行时保留)
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)//注解可以在运行期通过反射取得
public @interface Column {
public String name() default "fieldName";
}
3.@Documented,
@Documented用于描述其它类型的annotation应该被作为被标注的程序成员的公共API,因此可以被例如javadoc此类的工具文档化。Documented是一个标记注解,没有成员。
4.@Inherited
@Inherited 元注解是一个标记注解,@Inherited阐述了某个被标注的类型是被继承的。如果一个使用了@Inherited修饰的annotation类型被用于一个class,则这个annotation将被用于该class的子类
二、自定义注解
使用@interface自定义注解,自动继承了java.lang.annotation.Annotation接口,其中每一个方法声明一个配置参数,方法名称就是参数名称,
返回值就是参数的类型(返回值类型只能是基本类型、Class、String、enum)。可以通过default来声明参数的默认值。
例子:两个注解,分别标识实体对应的表和数据库中字段
1 类注解
- @Target(value=ElementType.TYPE)//表示该注解用于类上面
- @Retention(RetentionPolicy.RUNTIME) //运行时可以通过反射取得
- public @interface Table {
- public String name() default "";
- }
2 属性注解,并且注解有两个属性
- <span style="color: #ff6600;">@Target(value=ElementType.FIELD)
- @Retention(RetentionPolicy.RUNTIME)</span>
- public @interface Column {
- public String value() default "";
- public boolean isKey() default false;
- }
3 实体
- package anotation;
- @Table(name="s_user")
- public class User {
- @Column(value="id",isKey=true)
- private Integer id;
- @Column("s_name") /<span style="color: #ff6600;">/没有指定注解的name 则默认name为value 等同于 value="s_name"</span>
- private String name;
- @Column(value="s_age")
- private Integer age;
- public Integer getId() {
- return id;
- }
- public void setId(Integer id) {
- this.id = id;
- }
- public String getName() {
- return name;
- }
- public void setName(String name) {
- this.name = name;
- }
- public Integer getAge() {
- return age;
- }
- public void setAge(Integer age) {
- this.age = age;
- }
- }
4 测试类,通过反射得到类的各种信息
- public class Test {
- public static void main(String[] args) throws Exception {
- User user = new User();
- user.setId(1);
- user.setName("wang");
- user.setAge(89);
- // Class<User> userClazz = (Class<User>) Class.forName( "anotation.User");
- Class userClazz = user.getClass();
- Table table = (Table) userClazz.getAnnotation(Table.class); //得到类的注解
- System.out.println("表名称 : "+table.name() ); //取得注解的名称 属性
- Field[] fields = userClazz.getDeclaredFields(); //得到所有的 对象的属性
- for(int i=0;i<fields.length;i++ ){
- Field field = fields[i];
- Column column = field.getAnnotation(Column.class );//得到属性上的注解
- System.out.println( "column的注解名称:"+column.value()+" 注解:isKey=== "+column.isKey() );//打印属性上的注解
- String fieldName = field.getName(); //得到属性名称
- Class clazz = field.getType();//得到属性类型
- System.out.println(fieldName + " 字段类型 "+clazz );
- field.setAccessible(true);//可以访问私有变量
- System.out.println( fieldName + " 调用字段变量取得字段值 "+ field.get(user ) );//打印对象的该属性的值
- Method method = userClazz.getMethod("get"+toUpperCaseFirstOne(fieldName) );//调用get取得该对象的值
- System.out.println( fieldName + " 调用字段get方法取出字段值 "+ method.invoke(user) );
- System.out.println("判断字段类型是否为整形:"+( clazz==Integer.class));//判断一个字段的类型
- System.out.println( "============");
- }
- // Object name = 1;
- // System.out.println( name.getClass().equals( Integer.class) );
- }
- /**
- * 首字母转大写
- * @param s
- * @return
- */
- public static String toUpperCaseFirstOne(String s)
- {
- if(Character.isUpperCase(s.charAt(0)))
- return s;
- else
- return (new StringBuilder()).append(Character.toUpperCase(s.charAt(0))).append(s.substring(1)).toString();
- }
- }