浅析Java注解
这几天需要使用自定义注解,发现很不熟练,写此笔记总结
参考慕课网教程。
JDK1.8
前言
注解的概念
Java提供了一种原程序中的元素关联任何信息和任何数据的途径和方法。
通俗理解:注解本身没有任何实质功能,和xml用途上基本一样,都是一种元数据,一种解释数据,声明属性的方式。所以理论上注解可以取代xml配置(现在也流行这么做)。
注解的分类
1.按照运行机制分类 | 解释 |
---|---|
源码注解 | 只在源码中存在 ,编译为.class就没有了 |
编译时注解 | 在源码和.class都存在 |
运行时注解 | 在运行阶段还会起作用,会影响运行逻辑 |
2.按照来源分类 |
---|
来自JDK |
来自第三方 |
自定义 |
2.元注解 | 注解的注解(见下文) |
---|
(重点)自定义注解
语法要求
import java.lang.annotation.*;
/**
* Created by slgxmh on 16-6-8.
*/
//成员类型时受限制的,仅有String,Class,Annotation,Enumeration和基础类型
//如果注解只有一个成员,成员名约定俗成为value(),在使用时可以忽略成员名和赋值号(=)
//注解类可以没有成员,没有成员的注解成为标识注解
//下面四行称为元注解
@Target(ElementType.METHOD)//作用域
@Retention(RetentionPolicy.RUNTIME)//生命周期
@Inherited//允许子类继承
@Documented//生成javadoc时会包含注解
public @interface Description {//注解使用@interface关键字定义
String name();//成员应为无参无异常
int age() default 8;//声明默认值的方式
}
注:1.作用域包含以下声明
名称 | 解释 |
---|---|
METHOD | 方法 |
ANNOTATION_TYPE | 注解类 |
CONSTRUCTOR | 构造方法声明 |
FIELD | 字段声明 |
LOCAL_VARIABLE | 局部变量声明 |
PACKAGE | 包声明 |
PARAMETER | 参数声明 |
TYPE | 类,接口 |
注:2.生命周期包含以下声明
名称 | 解释 |
---|---|
RUNTIME | 运行时存在,可以通过反射读取 |
CLASS | 编译时记录,运行时忽略 |
SOURCE | 只在源码显示,编译时会丢弃 |
使用一个自定义注解
使用方式:
@<注解名>(<成员名1>=<成员值1>,<成员名2>=<成员名2>,…)
例(使用上面的自定义注解):
@Description(name = "小明", age = 10)//使用自己定义的注解(请注意作用域为方法)
public String sayHello() {
return "hello";
}
例(类注解)
我们有一个注解如下
@Target(ElementType.TYPE)//注意作用域为TYPE
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@Documented
public @interface Description {
String name();
int age() default 8;
}
类为下
@Description(name = "小明")
public class XiaoMing {
public String sayHello() {
return "hello";
}
}
我们运行一下
public static void main(String[] args) {
try {
//加载类
Class c = Class.forName("com.learn.annotation.XiaoMing");
//拿到注解(是否存在Description.class这个注解)
if (c.isAnnotationPresent(Description.class)) {
//拿到注解实例
Description d = (Description) c.getAnnotation(Description.class);
System.out.println(d.name() + ":" + d.age());
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
我们可以看到控制台输出小明:8
(默认age为8)
例(方法注解)
我们将上面的注解类型变为METHOD,注解使用如下
public class XiaoMing {
@Description(name = "小明")
public String sayHello() {
return "hello";
}
}
主函数如下
public static void main(String[] args) {
try {
//加载类
Class c = Class.forName("com.learn.annotation.XiaoMing");
//找到方法上的注解
Method[] methods = c.getMethods();
for (Method m : methods) {
if (m.isAnnotationPresent(Description.class)) {
Description d = (Description) m.getAnnotation(Description.class);
System.out.println(d.name() + ":" + d.age());
}
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
我们可以看到控制台输出小明:8
但是要是我们有很多注解呢?主函数如下
public static void main(String[] args) {
try {
//加载类
Class c = Class.forName("com.learn.annotation.XiaoMing");
//找到方法上的注解
Method[] methods = c.getMethods();
for (Method m : methods) {
Annotation[] annotations = m.getAnnotations();
for (Annotation a : annotations) {
if (a instanceof Description) {
Description d = (Description) a;
System.out.println(d.name() + ":" + d.age());
}
}
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
我们仍然可以看见小明:8