Java注解与自定义注解详解

注解

1. 注解的介绍

注解是Java 1.5 引入的,目前已被广泛应用于各种Java
框架,如Hibernate,Jersey,Spring。注解相当于是一
种嵌入在程序中的 元数据 ,可以使用注解解析工具或编
译器对其进行解析,也可以指定注解在编译期或运行期
有效。在注解诞生之前,程序的元数据存在的形式仅限
于java注释或javadoc,但注解可以提供更多功能,它不
仅包含元数据,还能作用于运行期,注解解析器能够使
用注解决定处理流程。
Annotation(注解)就是Java提供了一种元程序中的元素关
联任何信息和任何元数据 (metadata)的途径和方法。
Annotation是一个接口,程序可以通过反射来获取指定
程序元素的Annotation对象,然后通过Annotation对象来
获取注解里面的元数据。注解API非常强大,被广泛应用
于各种Java框架。
元数据:描述数据的数据

2. 注解的分类

根据注解参数的个数分类
1)、标记注解:一个没有成员定义的Annotation类型被
称为标记注解。
2)、单值注解:只有一个值
3)、完整注解:拥有多个值
根据注解使用方法和用途分类
1)、JDK内置系统注解
2)、元注解
3)、自定义注解

3. 内置注解

JavaSE中内置三个标准注解,定义在java.lang中:

3.1. @Override

限定重写父类方法,若想要重写父类的一个方法时,需
要使用该注解告知编译器我们正在重写一个方法。如此
一来,当父类的方法被删除或修改了,编译器会提示错
误信息;或者该方法不是重写也会提示错误。

public interface Car {
	void run();
}
class QQ implements Car{
	@Override
	public void run() {}
}
class Bmw implements Car{
	@Override
	void run() {}
}

3.2. @Deprecated

标记已过时,当我们想要让编译器知道一个方法已经被
弃用(deprecate)时,应该使用这个注解。Java推荐在
javadoc中提供信息,告知用户为什么这个方法被弃用
了,以及替代方法是什么

/**
* Deprecated -->该方法过时(有更好的解决方案)
*/
public class TestDeprecated {
	@Deprecated
	public int test(){
		System.out.println("TestDeprecated.test()");
		return 0;
	}
	public void test(int a){
		System.out.println("TestDeprecated.test(int)");
	}
}

3.3. @SuppressWarnings

抑制编译器警告,该注解仅仅告知编译器,忽略它们产
生了特殊警告。如:在java泛型中使用原始类型。其保
持性策略(retention policy)是SOURCE,在编译器中将被
丢弃。

/**
* SuppressWarnings 压制警告
* @author Administrator
*/

public class TestSuppressWarnings {
	public static void main(String[] args) {
		@SuppressWarnings("unused")
		List<String> list =new
		ArrayList<String>();
	}
	@SuppressWarnings("rawtypes") //没有定义范型
		public static List test(){
			return new ArrayList();
		}
	}
  1. all to suppress all warnings (抑制所有警告)
  2. boxing to suppress warnings relative to
    boxing/unboxing operations(抑制装箱、拆箱操作
    时候的警告)
  3. cast to suppress warnings relative to cast operations
    (抑制映射相关的警告)
  4. dep-ann to suppress warnings relative to
    deprecated annotation(抑制启用注释的警告)
  5. deprecation to suppress warnings relative to
    deprecation(抑制过期方法警告)
  6. fallthrough to suppress warnings relative to missing
    breaks in switch statements(抑制确在switch中缺
    失breaks的警告)
  7. finally to suppress warnings relative to finally block
    that don’t return (抑制finally模块没有返回的警
    告)
public class TestSuppressWarnings {
	public static void main(String[] args) {
		@SuppressWarnings("unused")
		List<String> list =new
		ArrayList<String>();
	}
	@SuppressWarnings("rawtypes") //没有定义范型
	public static List test(){
		return new ArrayList();
	}
}
  1. hiding to suppress warnings relative to locals that
    hide variable()
  2. incomplete-switch to suppress warnings relative to
    missing entries in a switch statement (enum case)
    (忽略没有完整的switch语句)
  3. nls to suppress warnings relative to non-nls string
    literals(忽略非nls格式的字符)
  4. null to suppress warnings relative to null analysis(忽
    略对null的操作)
  5. rawtypes to suppress warnings relative to unspecific types when using generics on class
    params(使用generics时忽略没有指定相应的类型)
  6. restriction to suppress warnings relative to usage of
    discouraged or forbidden references
  7. serial to suppress warnings relative to missing
    serialVersionUID field for a serializable class(忽略在
    serializable类中没有声明serialVersionUID变量)
  8. static-access to suppress warnings relative to
    incorrect static access(抑制不正确的静态访问方
    式警告)
  9. synthetic-access to suppress warnings relative to
    unoptimized access from inner classes(抑制子类
    没有按最优方法访问内部类的警告)
  10. unchecked to suppress warnings relative to
    unchecked operations(抑制没有进行类型检查操
    作的警告)
  11. unqualified-field-access to suppress warnings
    relative to field access unqualified (抑制没有权限
    访问的域的警告)
  12. unused to suppress warnings relative to unused
    code (抑制没被使用过的代码的警告)

4. 自定义注解

自己定义的注解,让别人去使用,完整的注解分两块,
一块是注解的定义,与之配套的会有相应的解析器。对
我们而言,就是使用注解,能看懂别人的注解即可。学
习自定义注解就是以后看到一个注解能够使用。

4.1. 简单入门

@interface:用来声明一个注解。注解类里的每一个方法
实际上是声明了一个配置参数。方法的名称就是参数的
名称,返回值类型就是参数的类型。可以通过default来
声明参数的默认值。

@interface Simple{
//这里定义了一个空的注解,它能干什么呢?我也不知
//道,但他能用。后面有补充
}

4.2. 元注解

元注解的作用就是负责注解其他注解。Java5.0定义了4
个标准的 meta-annotation 类型,它们被用来提供对其
它 annotation类型作说明。Java5.0定义的元注解有四
个,这些类型和它们所支持的类在java.lang.annotation
包中可以找到。

4.2.1. @Target

用于描述注解的使用范围(即:被描述的注解可以用在
什么地方)。表示支持注解的程序元素的种类,一些可
能的值有TYPE, METHOD, CONSTRUCTOR, FIELD等等。如果Target元注解不存在,那么该注解就可以使用在任何程序元素之上。取值(ElementType)有:

  1. CONSTRUCTOR:用于描述构造器
  2. FIELD:用于描述域
  3. LOCAL_VARIABLE:用于描述局部变量
  4. METHOD:用于描述方法
  5. PACKAGE:用于描述包
  6. PARAMETER:用于描述参数
  7. TYPE:用于描述类、接口(包括注解类型) 或enum声明

此时在空注解中加入@Target元注解如:

//此注解只能用在方法上
@Target(ElementType.METHOD)
@interface TestMethod {}
4.2.2. @Retention

表示需要在什么级别保存该注释信息,用于描述注解的
生命周期(即:被描述的注解在什么范围内有效)表示
注解类型保留时间的长短。取值(RetentionPoicy)有:

  1. SOURCE:在源文件中有效(即源文件保留)
  2. CLASS:在class文件中有效(即class保留)
  3. RUNTIME:在运行时有效(即运行时保留)

此时在上述注解中加入@Retention元注解如

// 此注解可以用于注解类、接口(包括注解类型) 或enum声
明
@Target(ElementType.TYPE)
//该注解运行时有效。注解处理器可以通过反射,获取到该注
解的属性值,从而去做一些运行时的逻辑处理
@Retention(RetentionPolicy.RUNTIME)
@interface TestRn{
}
4.2.3. @Documented

表示使用该注解的元素应被javadoc或类似工具文档化,
它应用于类型声明,类型声明的注解会影响客户端对注
解元素的使用。如果一个类型声明添加了Documented注
解,那么它的注解会成为被注解元素的公共API的一部
分,@Documented是一个标记注解。

//可以被例如javadoc此类的工具文档化
@Documented
@interface TestDoc{
}
4.2.4. @Inherited

表示一个注解类型会被自动继承,如果用户在类声明的
时候查询注解类型,同时类声明中也没有这个类型的注
解,那么注解类型会自动查询该类的父类,这个过程将
会不停地重复,直到该类型的注解被找到为止,或是到
达类结构的顶层(Object)。

//被子类继承的注解
@Inherited
@interface TestInheri{}

4.3. 自定义注解

使用@interface自定义注解时,自动继承了
java.lang.annotation.Annotation接口,由编译程序自动
完成其他细节。在定义注解时,不能继承其他的注解或
接口。

4.3.1. 定义注解格式

@interface用来声明一个注解,其中的每一个方法实际上
是声明了一个配置参数。方法的名称就是参数的名称,
返回值类型就是参数的类型(返回值类型只能是基本类
型、Class、String、enum)。可以通过default来声明参
数的默认值。

public @interface 注解名{定义体}
4.3.2. 注解参数(即方法)

注解里面的每一个方法实际上就是声明了一个配置参
数,其规则如下
修饰符
只能用public或默认(default)这两个访问权修饰 ,默认为
default
方法的类型
注解体中的方法的返回值,作为注解参数,只支持以下
数据类型

int,float,boolean,byte,double,char,long,shor
t);
String类型;
Class类型;
enum类型;
Annotation类型;
以上所有类型的数组

命名(方法的名字)
对取名没有要求,如果只有一个参数成员,最好把参数名
称设为"value",后加小括号。
参数
注解中的方法不能存在参数
默认值
可以包含默认值,使用default来声明默认值

4.3.3. 例子
/*
* 码农定义注解
*/
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@interface Programmer{
String value() default "马云";
}
/**
* 码农类型注解
* @author peida
*/
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@interface ProgrammerType {
	/**
	* 类型枚举 程序猿 射鸡师
	*/
public enum CoderType{MONKEYS,LION,CHOOK};
	/**
	* 颜色属性
	*/
	CoderType type() default
	CoderType.MONKEYS;
}
/**
* 码农制造厂
* @author Administrator
*/
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@interface ProgrammerProductor {
	/**
	* 厂家编号
	* @return
	*/
	public int id() default -1;
	/**
	* 厂家名称
	* @return
	*/
	public String name() default "shsxt";
	/**
	* 厂家地址
	* @return
	*/
	public String address() default "上海";
	}
/**
* 注解使用
*/
class Coder{
	@Programmer("老裴")
	private String coderName;
	@ProgrammerType(type=CoderType.MONKEYS)
	private String coderType;
	@ProgrammerProductor(id=1,name="程序猿
	乐园",address="浦东新区")
	private String coderProductor;
	public String getCoderName() {
	return coderName;
}
public void setCoderName(String
coderName) {
	this.coderName = coderName;
}
public String getCoderType() {
	return coderType;
}
public void setCoderType(String
coderType) {
	this.coderType = coderType;
}
public String getCoderProductor() {
	return coderProductor;
}
public void setCoderProductor(String
coderProductor) {
	this.coderProductor = coderProductor;
}
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值