java--基础--21.1--注解--Java注解,元注解、自定义注解

java–基础–21.1–注解–Java注解,元注解、自定义注解


1、Java注解

  • 注解是一种可以在Java代码中插入的注释或元数据。
  • 注解可以在编译时由预编译工具进行处理,也可以在运行时通过Java反射机制来处理。

1.1、案例说明

下面是一个类注解的示例

@MyAnnotation(name="someName",  value = "Hello World")
public class TheClass {
}

下面是MyAnnotation注解 的定义

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

2、元注解(meta-annotation)

  1. 负责注解其他注解

2.1、种类

@Target,
@Retention,
@Documented,
@Inherited

2.2、@Target

  1. 用于描述注解的使用范围(即:被描述的注解可以用在什么地方)
  2. 取值(ElementType)
    1. CONSTRUCTOR:用于描述构造器
    2. FIELD:用于描述域
    3. LOCAL_VARIABLE:用于描述局部变量
    4. METHOD:用于描述方法
    5. PACKAGE:用于描述包
    6. PARAMETER:用于描述参数
    7. TYPE:用于描述类、接口(包括注解类型) 或enum声明

2.2.1、案例

#  用于注解类、接口(包括注解类型) 或enum声明,而注解NoDBColumn仅可用于注解类的成员变量。
@Target(ElementType.TYPE)
public @interface Table {
    /**
     * 数据表名称注解,默认值为类名称
     * @return
     */
    public String tableName() default "className";
}

# 用于 字段
@Target(ElementType.FIELD)
public @interface NoDBColumn {

}

2.3、@Retention

  1. 定义了该Annotation被保留的时间长短,举例
    1. 某些Annotation 仅出现在源代码中,而被编译器丢弃
    2. 某些Annotation 被编译在class文件中,编译在class文件中的Annotation可能会被虚拟机忽略
    3. 某些Annotation 在class被装载时将被读取(请注意并不影响class的执行,因为Annotation与class在使用上是被分离的)。
  2. 作用:表示需要在什么级别保存该注释信息,用于描述注解的生命周期(即:被描述的注解在什么范围内有效)
  3. 取值(RetentionPoicy)有:
        1. SOURCE:在源文件中有效(即源文件保留)
        2. CLASS:在class文件中有效(即class保留)
        3. RUNTIME:在运行时有效(即运行时保留)

2.3.1、案例

@Target(ElementType.FIELD)

# RetentionPolicy.RUNTIME,这样注解处理器可以通过反射,获取到该注解的属性值,从而去做一些运行时的逻辑处理
@Retention(RetentionPolicy.RUNTIME)
public @interface Column {
    public String name() default "fieldName";
    public String setFuncName() default "setField";
    public String getFuncName() default "getField"; 
    public boolean defaultDBValue() default false;
}

2.4、@Documented:

  1. 用于描述其它类型的annotation应该被作为被标注的程序成员的公共API,因此可以被例如javadoc此类的工具文档化。
  2. Documented是一个标记注解,没有成员。

2.4.1、案例

@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Column {
    public String name() default "fieldName";
    public String setFuncName() default "setField";
    public String getFuncName() default "getField"; 
    public boolean defaultDBValue() default false;
}

2.5、@Inherited:

  1. 是一个标记注解
  2. 如果一个使用了@Inherited修饰的annotation类型被用于一个class,则这个annotation将被用于该class的子类。
  3. 注意:
    1. @Inherited 类型是被标注过的class的子类所继承。类并不从它所实现的接口继承annotation,方法并不从它所重载的方法继承annotation。
    2. 当@Inherited 类型标注的annotation的Retention是RetentionPolicy.RUNTIME,则反射API增强了这种继承性。如果我们使用java.lang.reflect去查询一个@Inherited 类型的annotation时,反射代码检查将展开工作:
      1. 检查class和其父类,直到发现指定的annotation类型被发现,或者到达类继承结构的顶层。

2.5.1、案例

/**
 * 
 * @author peida
 *
 */
@Inherited
public @interface Greeting {
    public enum FontColor{ BULE,RED,GREEN};
    String name();
    FontColor fontColor() default FontColor.GREEN;
}

3、自定义注解

3.1、注解格式

定义注解格式:
public @interface 注解名 {定义体}

  1. 使用@interface自定义注解时,自动继承了java.lang.annotation.Annotation接口,由编译程序自动完成其他细节。
  2. 在定义注解时,不能继承其他的注解或接口。
  3. @interface 用来声明一个注解,其中的每一个方法实际上是声明了一个配置参数。
    1. 方法的名称 就是参数的名称
    2. 返回值类型 就是参数的类型(返回值类型只能是基本类型、Class、String、enum)。
    3. 可以通过default来声明参数的默认值。

3.1.1、参数的类型

  1. 所有基本数据类型
    1. int
    2. float
    3. boolean
    4. byte
    5. double
    6. char
    7. long
    8. short
  2. String类型
  3. Class类型
  4. enum类型
  5. Annotation类型
  6. 以上所有类型的数组

3.1.2、访问权修饰

  1. 只能用public 或 默认(default)

3.1.3、注解元素的默认值:

  1. 注解元素必须有确定的值,要么在定义注解的默认值中指定,要么在使用注解时指定
  2. 非基本类型的注解元素的值不可为null。
  3. 常用默认值做法
    1. 使用 空字符串
    2. 使用 0

3.2、案例

3.2.1、自定义注解

package com.dragon.test.annotation;

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

/**
 * Created by gmq on 2015/9/10.
 */
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface MyAnnotation
{

    String hello () default "hello";
    String world();
}

3.2.2、使用注解

package com.dragon.test.annotation;

/**
 * Created by gmq on 2015/9/10.
 */
public class MyTest
{

    @MyAnnotation(hello = "Hello,Beijing",world = "Hello,world")
    public void output() {
        System.out.println("method output is running ");
    }
}

3.2.3、测试

package com.dragon.test.annotation;

import java.lang.annotation.Annotation;
import java.lang.reflect.Method;

/**
 * 用反射机制来调用注解中的内容
 * Created by gmq on 2015/9/10.
 */
public class MyReflection
{
    public static void main(String[] args) throws Exception
    {
        // 获得要调用的类
        Class<MyTest> myTestClass = MyTest.class;
        // 获得要调用的方法,output是要调用的方法名字,new Class[]{}为所需要的参数。空则不是这种
        Method method = myTestClass.getMethod("output", new Class[]{});
        // 是否有类型为MyAnnotation的注解
        if (method.isAnnotationPresent(MyAnnotation.class))
        {
            // 获得注解
            MyAnnotation annotation = method.getAnnotation(MyAnnotation.class);
            // 调用注解的内容
            System.out.println(annotation.hello());
            System.out.println(annotation.world());
        }
        System.out.println("----------------------------------");
        // 获得所有注解。必须是runtime类型的
        Annotation[] annotations = method.getAnnotations();
        for (Annotation annotation : annotations)
        {
            // 遍历所有注解的名字
            System.out.println(annotation.annotationType().getName());
        }
    }
}



输出:

Hello,Beijing
Hello,world
----------------------------------
com.dragon.test.annotation.MyAnnotation

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值