Java基础——注解(Annotation)

一、什么是注解

注解(Annontation)是Java5开始引入的新特征,中文名称叫注解它提供了一种安全的类似注释的机制,用来将任何的信息或元数据(metadata)与程序元素(类、方法、成员变量等)进行关联。为程序的元素(类、方法、成员变量)加上更直观更明了的说明,这些说明信息是与程序的业务逻辑无关,并且供指定的工具或框架使用。注解(Annontation)像一种修饰符一样,应用于包、类型、构造方法、方法、成员变量、参数及本地变量的声明语句中。

Java注解是附加在代码中的一些元信息,用于一些工具在编译、运行时进行解析和使用,起到说明、配置的功能。注解不会也不能影响代码的实际逻辑,仅仅起到辅助性的作用。包含在 java.lang.annotation 包中。

二、注解的用处

1、生成文档。
2、跟踪代码依赖性,实现替代配置文件功能。
3、在编译时进行格式检查。如@override 放在方法前,如果你这个方法并不是覆盖了超类方法,则编译时就能检查出。

三、注解的原理

注解本质是一个继承了Annotation的特殊接口,其具体实现类是Java运行时生成的动态代理类。而我们通过反射获取注解时,返回的是Java运行时生成的动态代理对象$Proxy1。通过代理对象调用自定义注解(接口)的方法,会最终调用AnnotationInvocationHandler的invoke方法。该方法会从memberValues这个Map中索引出对应的值。而memberValues的来源是Java常量池。

四、JDK自带注解

@Override,表示当前的方法定义将覆盖超类中的方法。

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.SOURCE)
public @interface Override {
}

@Deprecated,表示该方法已经过时了。使用了注解为它的元素编译器将发出警告,因为注解@Deprecated是不赞成使用的代码,被弃用的代码。

@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(value={CONSTRUCTOR, FIELD, LOCAL_VARIABLE, METHOD, PACKAGE, PARAMETER, TYPE})
public @interface Deprecated {
}

@SuppressWarnings,关闭不当编译器警告信息。

@Target({TYPE, FIELD, METHOD, PARAMETER, CONSTRUCTOR, LOCAL_VARIABLE})
@Retention(RetentionPolicy.SOURCE)
public @interface SuppressWarnings {
    String[] value();
}

五、元注解

元注解是由java提供的基础注解,负责注解其它注解,如上面的 Override被@Target和@Retention修饰,它们用来说明解释其它注解,位于sdk/sources/android-25/java/lang/annotation路径下。

元注解有:
@Retention:注解保留的生命周期。
@Target:注解对象的作用范围。
@Inherited:@Inherited标明所修饰的注解,在所作用的类上,是否可以被继承。
@Documented:如其名,javadoc的工具文档化,一般不关心。

@TargetTarget标明了注解的适用范围,对应ElementType枚举,明确了注解的有效范围。可能的ElementType参数有:

TYPE:类、接口、枚举、注解类型。
FIELD:类成员(构造方法、方法、成员变量)。
METHOD:方法。
PARAMETER:参数。
CONSTRUCTOR:构造器。
LOCAL_VARIABLE:局部变量。
ANNOTATION_TYPE:注解。
PACKAGE:包声明。
TYPE_PARAMETER:类型参数。
TYPE_USE:类型使用声明。

@RetentionRetention说标明了注解被生命周期,对应RetentionPolicy的枚举,表示注解在何时生效:

SOURCE:只在源码中有效,编译时抛弃,如上面的@Override。
CLASS:编译class文件时生效。
RUNTIME:运行时才生效。

@Inherited:注解所作用的类,在继承时默认无法继承父类的注解。除非注解声明了 @Inherited。同时Inherited声明出来的注解,只对类有效,对方法/属性无效。
如果一个使用了@Inherited修饰的annotation类型被用于一个class,则这个annotation将被用于该class的子类。

@Documented:一个简单的Annotations标记注解,表示是否将注解信息添加在java文档中。

六、自定义注解

自定义注解类编写的一些规则:
1、 Annotation型定义为@interface, 所有的Annotation会自动继承java.lang.Annotation这一接口,并且不能再去继承别的类或是接口。

2、参数成员只能用public或默认(default)这两个访问权修饰。

3、 参数成员只能用基本类型byte,short,char,int,long,float,double,boolean八种基本数据类型和String、Enum、Class、annotations等数据类型,以及这一些类型的数组。

4、要获取类方法和字段的注解信息,必须通过Java的反射技术来获取 Annotation对象,因为你除此之外没有别的获取注解对象的方法。

下面通过一个简单的对象关系映射(ORM)程序来学习一下自定义注解(Object Relational Mapping)。

一、定义两个注解类

MyTable

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;



@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface MyTable {
    String value();
}

MyField

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface MyField {
    String column();
    String type();
}
二、在User类上使用注解
@MyTable(value = "tbl_user")
public class User {
    @MyField(column = "id", type = "int")
    private int id;
    @MyField(column = "age", type = "int")
    private int age;
    @MyField(column = "name", type = "varchar")
    private String name;
    
    public User() {
    }

    public User(int id, int age, String name) {
        super();
        this.id = id;
        this.age = age;
        this.name = name;
    }

    public int getId() {
        return id;
    }
    public void setId(int id) {
        this.id = id;
    }
    public int getAge() {
        return age;
    }
    public void setAge(int age) {
        this.age = age;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    
}


三、利用反射读取解析注解
public class Annocation {
    public static void main(String[] args) {
        String path = "com.cczhang.annocation.User";

        try {
            Class<User> clazz = (Class<User>) Class.forName(path);

//            User user = clazz.newInstance();

            //获取类的所有有效注解
            Annotation[] annocations = clazz.getAnnotations();
            for (Annotation a:annocations) {
                System.out.println(a);
            }
            //获取类的指定的注解
            MyTable table = clazz.getAnnotation(MyTable.class);
            System.out.println(table.value());

            //获取类的属性的注解
            Field field = clazz.getDeclaredField("name");
            MyField myField = field.getAnnotation(MyField.class);
            System.out.println(myField.column()+"--"+myField.type());

            System.out.println("所有属性:");
            Field[] fields = clazz.getDeclaredFields();
            for (Field f :fields) {
                MyField mf = f.getAnnotation(MyField.class);
                System.out.println(mf.column()+"--"+mf.type());
            }
            
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

@com.cczhang.annocation.MyTable(value=tbl_user)
tbl_user
name--varchar
所有属性:
id--int
age--int
name--varchar
四、根据获得的表名,字段的信息拼出DDL语句,然后使用JDBC执行这个SQL,在数据库中生成相关的表

DDL(Data Definition Language),数据库模式定义语言,是用于描述数据库中要存储的现实世界实体的语言。

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值