黑马程序员_java注解

注解(Annotation)简介

Annotation(注解)是JDK5.0及以后版本引入的一个特性。注解是java的一个新的类型(与接口很相似),它与类、接口、枚举 是在同一个层次,它们都称作为java的一个类型(TYPE)。它可以声明在包、类、字段、方法、局部变量、方法参数等 的前面,用来对这些元素进行说明,注释。它的作用非常的多,例如:进行编译检查、生成说明文档、代码分析等。

注解的作用

注解可以看成是一个接口,注解实例就是一个实现了该接口的动态代理类。 注解大多是用做对某个类、方法、字段进行说 明,标识的。以便在程序运行期间我们通过反射获得该字段或方法的注解的实例,来决定该做些什么处理或不该进行什 么处理。

JDK提供的几个基本注解 

a. @SuppressWarnings

该注解的作用是阻止编译器发出某些警告信息。

它可以有以下参数:

deprecation:过时的类或方法警告。

unchecked:执行了未检查的转换时警告。

fallthrough:当Switch程序块直接通往下一种情况而没有Break时的警告。

path:在类路径、源文件路径等中有不存在的路径时的警告。

serial:当在可序列化的类上缺少serialVersionUID定义时的警告。

finally:任何finally子句不能完成时的警告。

all:关于以上所有情况的警告。

[email protected] 该注解的作用是标记某个过时的类或方法。

c. @Override 该注解用在方法前面,用来标识该方法是重写父类的某个方法。

元注解

元注解是指注解的注解。包括  @Retention @Target @Document @Inherited四种。

a. @Retention 它是被定义在一个注解类的前面,用来说明该注解的生命周期。

@Retention 表示在什么级别保存该注解信息。可选的参数值在枚举类型 RetentionPolicy 中,

它有以下参数:

@Retention(RetentionPolicy.SOURCE)//注解仅存在于源码中,在class字节码文件中不包含

@Retention(RetentionPolicy.CLASS)// 默认的保留策略,注解会在class字节码文件中存在,但运行时无法获得,

@Retention(RetentionPolicy.RUNTIME) // 注解会在class字节码文件中存在,在运行时可以通过反射获取到

@Documented 将此注解包含在 javadoc 中 ,它代表着此注解会被javadoc工具提取成文档。在doc文档中的内容 会因为此注解的信息内容不同而不同。相当与@see,@param 等。

@Inherited 允许子类继承父类中的注解

思考:@Override、@SuppressWarnings和@Deprecated这三个注解的属性值分别是什么?

@Override、@SuppressWarnings的属性值是SOURCE。

@Deprecated的属性值是RUNTIME。

b. @Target 它是被定义在一个注解类的前面,用来说明该注解可以被声明在哪些元素,可能的值在枚举类

ElemenetType中。

它有以下参数:

@Target(ElementType.TYPE)   //接口、类、枚举、注解

@Target(ElementType.FIELD) //字段、枚举的常量

@Target(ElementType.METHOD) //方法

@Target(ElementType.PARAMETER) //方法参数

@Target(ElementType.CONSTRUCTOR)  //构造函数

@Target(ElementType.LOCAL_VARIABLE)//局部变量

@Target(ElementType.ANNOTATION_TYPE)//注解

@Target(ElementType.PACKAGE) //包 packag注解必须在package-info.java 中声明

注解的生命周期

一个注解可以有三个生命周期,它默认的生命周期是保留在一个CLASS文件,但它也可以由一个@Retetion的元注解指定它 的生命周期。

a.java源文件 当在一个注解类前定义了一个@Retetion(RetentionPolicy.SOURCE)的注解,那么说明该注解只保留在一个源文 件当中,当编译器将源文件编译成class文件时,它不会将源文件中定义的注解保留在class文件中。

b. class文件中 当在一个注解类前定义了一个@Retetion(RetentionPolicy.CLASS)的注解,那么说明该注解只保留在一个 class文件当中,当加载class文件到内存时,虚拟机会将注解去掉,从而在程序中不能访问。

c. 程序运行期间 当在一个注解类前定义了一个@Retetion(RetentionPolicy.RUNTIME)的注解,那么说明该注解在程序运行期 间都会存在内存当中。此时,我们可以通过反射来获得定义在某个类上的所有注解。

注解的定义 

一个简单的注解:

[email protected]{

//定义公共的final静态属性

.....

//定以公共的抽象方法

......}

a.注解可以有哪些成员 注解和接口相似,它只能定义final静态属性和公共抽象方法。

b.注解的方法

1.方法前默认会加上publicabstract

2.在声明方法时可以定义方法的默认返回值。

例如: Stringcolor()default"blue";

String[]color()default{"blue","red",......}

3.方法的返回值可以有哪些类型 8种基本类型,String、Class、枚举、注解及这些类型

的数组。

c.使用注解(参照下面的注解使用)

注解的使用 

注解的使用分为三个过程。

定义注解-->声明注解-->得到注解

a.定义注解(参照上面的注解定义)

b.声明注解

1.在哪些元素上声明注解

如果定义注解时没有指定@Target元注解来限制它的使用范围,那么该注解可以

使用在ElementType枚举指定的任何一个元素前。否则,只能声明在@Target元

注解指定的元素前。

一般形式:

@注解名()

2.对注解的方法的返回值进行赋值 对于注解中定义的每一个没有默认返回值的方法,在

声明注解时必须对它的每一个方法的返回值进行赋值。

一般形式:

@注解名(方法名=方法返回值,...)

如果方法返回的是一个数组时,那么将方法返回值写在{}符号里

@注解名(方法名={返回值1,返回值2,...}...)

3.对于只含有value方法的注解,在声明注解时可以只写返回值。

c.得到注解 对于生命周期为运行期间的注解,都可以通过反射获得该元素上的注解实例。

1、声明在一个类中的注解

可以通过该类Class对象的getAnnotation或getAnnotations方法获得。

2、声明在一个字段中的注解

通过Field对象的getAnnotation或getAnnotations方法获得

3、声明在一个方法中的注解

通过Method对象的getAnnotation或getAnnotations方法获得

为注解增加高级属性

数组类型的属性

int [] arrayAttr() default {1,2,3};

@MyAnnotation(arrayAttr={2,3,4})

如果数组属性中只有一个元素,这时候属性值部分可以省略大括

枚举类型的属性

EnumTest.TrafficLamp lamp() ;

@MyAnnotation(lamp=EnumTest.TrafficLamp.GREEN)

注解类型的属性:

MetaAnnotation annotationAttr() default @MetaAnnotation("xxxx");

@MyAnnotation([email protected](“yyy”) )

可以认为上面这个@MyAnnotation是MyAnnotaion类的一个实例对象,同样的道理,可以认为上面这个 @MetaAnnotation是MetaAnnotation类的一个实例对象,调用代码如下:

MetaAnnotation ma =  myAnnotation.annotationAttr();

System.out.println(ma.value());

注解的详细语法可以通过看java语言规范了解,即看java的language specification。

实例:

下面是使用反射读取RUNTIME保留策略的Annotation信息的例子:

自定义注解:

@Retention(RetentionPolicy.RUNTIME)

public @interface MyAnnotation {

String[] value1() default "abc";

}

使用自定义注解:

public class AnnotationTest2 {

@MyAnnotation(value1={"a","b"})

@Deprecated

public void execute(){

System.out.println("method");

}

}

读取注解中的信息:

public static void main(String[] args) throws SecurityException, NoSuchMethodException,

IllegalArgumentException, IllegalAccessException, InvocationTargetException {

AnnotationTest2 annotationTest2 = new AnnotationTest2();

//获取AnnotationTest2的Class实例

Class<AnnotationTest2> c = AnnotationTest2.class;

//获取需要处理的方法Method实例

Method method = c.getMethod("execute", new Class[]{});

//判断该方法是否包含MyAnnotation注解

if(method.isAnnotationPresent(MyAnnotation.class)){

//获取该方法的MyAnnotation注解实例

MyAnnotation myAnnotation = method.getAnnotation(MyAnnotation.class);

//执行该方法

method.invoke(annotationTest2, new Object[]{});

//获取myAnnotation

String[] value1 = myAnnotation.value1();

System.out.println(value1[0]);

}

//获取方法上的所有注解

Annotation[] annotations = method.getAnnotations();

for(Annotation annotation : annotations){

System.out.println(annotation);

}

}

总结

1. 要用好注解,必须熟悉java 的反射机制,从上面的例子可以看出,注解的解析完全依赖于反射。

2. 不要滥用注解。平常我们编程过程很少接触和使用注解,只有做设计,且不想让设计有过多的配置时。

时间: 2024-10-13 09:50:38

黑马程序员_java注解的相关文章

黑马程序员_Java基础加强(下)

8.注解类 注解相当于一种标记,加了注解就等于打上了某种标记,没加就等于没打特殊标记,开发工具和其他程序可以用反射来了解你的类及各种元素上有无何种标记,看你有什么标记就去干什么事,标记可以加在包.类.字段.方法,方法的参数以及局部变量上. 注解的应用结构图: 为注解增加属性 定义基本类型的属性和应用属性 在注解类中增加String color(); @MyAnnotation(color = "red") 用反射方式获得注解对应的实例对象后,再通过该对象调用属性对应的方法 MyAnno

黑马程序员_Java高新技术

1  JDK5的新特性 1.1 静态导入       在API中那些不需要new对象的类,可以在类文件的开头,import static java.lang.Math.*;这里把Math中的所有的静态方法都导入了,在类中不需要调用Math类就能直接用Math的方法了 package cn.wjd.staticimport; import static java.lang.Math.*; public class StaticImport { public static void main(Str

黑马程序员_JAVA 基础加强学习笔记

一.面向对象 (一)继承  1.继承的好处: (1) 提高了代码的复用性. (2) 让类与类之间产生了关系,提供了另一个特征多态的前提. 注意: 子类中所有的构造函数都会默认访问父类中的空参数的构造函数,因为每一个子类构造内第一行都有默认的语句super();  如果父类中没有空参数的构造函数,那么子类的构造函数内,必须通过super语句指定要访问的父类中的构造函数. 如果子类构造函数中用this来指定调用子类自己的构造函数,那么被调用的构造函数也一样会访问父类中的构造函数. 2.final特点

黑马程序员_Java基础加强(上)

1.静态导入 静态导入是jdk1.5版本以后出现的新特性,一般是指导入静态方法,如:import static java.lang.System.out 是指导入系统输出的静态方法. 例: import static java.lang.System.out //导入java.lang包下的System类的静态方法out public class StaticImport { public static void main(String[] args) { int x=1; x++; out.p

黑马程序员_Java反射机制

一切的操作都将使用Object完成,类,数组的引用都可以使用Object来接收 1,认识Class类 以前要是想知道一个类中的属性,成员变量,方法等等的信息的话,需要通过new这个类的对象才能得到这些信息,但是在Java中,也允许一个实例化对象找到一个类的完整的信息,这个类就是Class类,Class类是继承Object类的. 正常方式:  引入需要的"包.类"名称 >取得实例化对象 反射方式:  实例化对象>得到完整的"包.类"名称 getClass(

黑马程序员_Java IO(下)

1,字符编码 在Java程序的开发中最常见的是ISO8859-1,GBK/GBK2312,unicode,UTF编码. ISO8859-1:属于单字节编码,最多只能表示0-255的字符范围,主要在英文上应用. GBK/GB2312:中文的国际编码,专门用来表示汉字,是双字节编码,如果在此编码中出现中文,则使用ISO8859-1编码,GBK可以表示简体中文和繁体中文,而GB2312只能表示简体中文,GBK兼容GB2312 unicode:Java中使用此编码方式,是最标准的一种编码,使用十六进制进

黑马程序员_Java多线程

- - - - - android培训.java培训.期待与您交流! - - - - - - 进程:正在进行中的程序.其实进程就是一个应用程序运行时的内存分配空间.进程负责的是应用程序的空间的标示. 线程:其实就是进程中一个程序执行控制单元,一条执行路径.线程负责的是应用程序的执行顺序. 一个进程至少有一个线程在运行,当一个进程中出现多个线程时,就称这个应用程序是多线程应用程序. 每个线程在栈区中都有自己的执行空间,自己的方法区.自己的变量. jvm在启动的时,首先有一个主线程,负责程序的执行,

黑马程序员_Java集合框架

- - - - - android培训.java培训.期待与您交流! - - - - - - 集合框架:用于存储数据的容器. 特点: 对象封装数据,对象多了也需要存储.集合用于存储对象. 对象的个数确定可以使用数组.如果不确定可以用集合.因为集合是可变长度的. 集合和数组的区别: 数组是固定长度的:集合可变长度的. 数组可以存储基本数据类型,也可以存储引用数据类型:集合只能存储引用数据类型. 数组存储的元素必须是同一个数据类型:集合存储的对象可以是不同数据类型. 数据结构:就是容器中存储数据的方

黑马程序员_Java面向对象思想

面向对象要把握一个重要的经验:谁拥有数据,谁就对外提供操作这些数据的方法 . 1.人在黑板上画圆 对于这个设计,上面有Person, Blackborad , Circle三个对象 动词 : 画 因为画的动作的数据:坐标(x,y),半径(randius) 是Circle拥有的数据,所以 draw()方法应该属于Circle对象,而不是动作的发出者Person. 注意:[动作发出者往往会委托动作承受者 ] 2.司机紧急刹车 对于这个设计,上面有Driver, Car两个对象 动词 : 刹车 因为刹