Java注释(注解)简介

1、介绍

从JDK5.0开始,Java增加了对元数据(MetaData)的支持,也就是Annotation。其实就是代码里的特殊标记,这些标记可以在编译、类加载、运行时被读取,并执行相应的处理。

通过使用Annotation,程序开发人员可以在不改变原有逻辑的情况下,在源文件嵌入一些补充的信息。代码分析工具、开发工具和部署工具可以通过这些补充信息进行验证

或者进行部署。

Annotation不影响程序代码的执行,无论增加、删除Annotation,代码都始终如一的执行。如果希望让程序中的Annotation能在运行时起一定的作用,只有通过某种配套的

工具对Annotation中的信息进行访问和处理,访问和处理Annotation的工具统称为APT(Annotation Processing Tool)。

2、原理

http://rejoy.iteye.com/blog/1627355

http://blog.csdn.net/blueheart20/article/details/18810693

可以参考JDK源码看其实现原理

3、使用

基本的Annotation

@Override:仅用来指定覆盖方法的,它强制一个子类必须要覆盖父类的方法。

@Deprecated:表示某个程序元素(类、方法等)已过时,当其他程序使用已过时的类、方法时,编译器将会给出警告。比如标记父类中的某个方法过时。

@SuppressWarnings("unchecked"):表示被Annotation标示的程序元素(以及在该程序元素中的所有子元素)取消显示指定的编译器警告。

自定义Annotation

使用关键字@interface

package com.java.anotion;

public @interface MyAnnotation {

//定义了两个变量的Annotation,default是默认值。

String name() default "cheney";

int age() default 18;

}

Annotation分为两类:

1、标记Annotation,没有成员定义,用自身的是否存在来为我们提供信息。

2、元数据Annotation,包含成员变量的Annotation,他们可以接受更多的元数据,所以被成为元数据Annotation。

提取Annotation的信息

java.lang.reflect新增的接口AnnotatedElement接口,该接口被主要的反射类实现,如Class,Constructor,Field,Method,Package等。通过反射类可以获取实现类的注释等信息。

两个示例:

示例一

package com.java.anotion;

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

/**
 * 空注释
 */
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface Testable {
}
package com.java.anotion;

import java.lang.reflect.Method;

/**
 *@Testable注释处理工具类 
 */
public class TestProcessor {

	/**
	 * 反射clazz调用的时候要加上报名称路径,不然会包找不到类异常
	 * @param clazz
	 * @throws SecurityException
	 * @throws ClassNotFoundException
	 */
	public static void process(String clazz) throws SecurityException, ClassNotFoundException{
		int passed = 0;
		int failed = 0;
		for(Method m : Class.forName(clazz).getMethods()){
			if(m.isAnnotationPresent(Testable.class)){
				try {
					m.invoke(null);
					passed++;
				} catch (Exception e) {
					System.out.println("方法" + m + "运行失败,异常:" + e.getCause());
					failed++;
				}
			}
		}
		System.out.println("共运行了" + (passed + failed) + "方法,其中成功的" 
				+ passed + "个,失败的" + failed + "个");
	}
}
package com.java.anotion;

/**
 * 注释@Testable的目标类
 */
public class TestableAnnotationTest {
	@Testable
	public static void method1(){

	}
	public static void method2(){

	}

	@Testable
	public static void method3(){
		throw new RuntimeException("method3 RuntimeException");
	}
	public static void method4(){

	}

	@Testable
	public static void method5(){

	}
	public static void method6(){

	}

	@Testable
	public static void method7(){
		throw new RuntimeException("method7 RuntimeException");
	}
	@Testable
	public static void method8(){

	}
}
package com.java.anotion;

import java.util.ArrayList;
import java.util.List;

/**
 * @author youyang
 *
 *
 */

public class Test extends Fruit{

	@MyAnnotation(name="ch",age=6)
	public void foo(){
		System.out.println("еfoo");
	}

	@SuppressWarnings("unchecked")
	public static void main(String[] args) throws Exception {
//		new Test().foo();
//		List<String> list = new ArrayList();
		TestProcessor.process("com.java.anotion.TestableAnnotationTest");
	}
}

示例二

package com.java.anotion;

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

/**
 * 带成员变量的注释
 */
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface ActionListenerFor {
	String listener();
}
package com.java.anotion;

import java.awt.event.ActionListener;
import java.lang.reflect.Field;

import javax.swing.AbstractButton;

public class ActionListenerInstaller {
	public static void processAnnotations(Object obj){
		Class cl = obj.getClass();
		for(Field f : cl.getDeclaredFields()){
			//讲指定Field设置为可自由访问的,避免private的不可访问
			f.setAccessible(true);
			//获取指定Filed的ActionListenerFor类型的注释
			ActionListenerFor a = f.getAnnotation(ActionListenerFor.class);
			if(a != null){
				try {
					Class listenerClass = Class.forName(a.listener());
					ActionListener al = (ActionListener) listenerClass.newInstance();
					AbstractButton ab = (AbstractButton) f.get(obj);
					ab.addActionListener(al);
				} catch (ClassNotFoundException e) {
					e.printStackTrace();
				} catch (InstantiationException e) {
					e.printStackTrace();
				} catch (IllegalAccessException e) {
					e.printStackTrace();
				}
			}
		}
	}
}
package com.java.anotion;

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JPanel;

public class AnnotationTest {
	private JFrame jFrame = new JFrame("使用注释绑定事件监听器");
	//引用内部类的时候com.java.anotion.AnnotationTest$OkListenter反射不成功,报错
	@ActionListenerFor(listener="com.java.anotion.OkListenter")
	private JButton ok = new JButton("确定");
	@ActionListenerFor(listener="com.java.anotion.CancelListenter")
	private JButton cancel = new JButton("取消");

	public void init(){
		JPanel jp = new JPanel();
		jp.add(ok);
		jp.add(cancel);
		jFrame.add(jp);
		ActionListenerInstaller.processAnnotations(this);
		jFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		jFrame.setLocation(300, 200);
		jFrame.setSize(500, 300);
		jFrame.setVisible(true);

	}

	public static void main(String[] args) {
		new AnnotationTest().init();
	}
	/*
	class OkListenter implements ActionListener{
		public void actionPerformed(ActionEvent e) {
			JOptionPane.showMessageDialog(null, "点击了确认按钮");
		}
	}
	class CancelListenter implements ActionListener{
		public void actionPerformed(ActionEvent e) {
			JOptionPane.showMessageDialog(null, "点击了取消按钮");
		}
	}
	*/
}
package com.java.anotion;

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.JOptionPane;

public class CancelListenter implements ActionListener{
	public void actionPerformed(ActionEvent e) {
		JOptionPane.showMessageDialog(null, "点击了取消按钮");
	}
}
package com.java.anotion;

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.JOptionPane;

public class OkListenter implements ActionListener{
	public void actionPerformed(ActionEvent e) {
		JOptionPane.showMessageDialog(null, "点击了确认按钮");
	}
}

JDK的元Annotation

在java.lang.annotation包下提供了四个元Annotation。

@Retention:用于指定该Annotation可以保留多长时间。包含一个RetentionPolicy类型的value成员变量。

value有三个值:

1、RetentionPolicy.CLASS 编译器将把注释记录在class文件中。当运行Java程序时,JVM不再保留注释。这是默认值。

2、RetentionPolicy.RUNTIME 编译器把注释记录在class文件中。当运行Java程序时,JVM也会保留注释,程序可以通过反射获取该注释。

3、RetentionPolicy.SOURCE 编译器直接丢弃这种策略的注释。

注:如果Annotation类型只有一个value成员变量,可以直接写value值,不用name=value的形式。

@Target:用于指定该Annotation修饰哪些程序元素。也包含一个ElementType类型的value成员变量。

value值有8个:

ElementType.ANNOTATION_TYPE只能修饰Annotation

ElementType.CONSTRUCTOR修饰构造器

ElementType.FIELD修饰成员变量

ElementType.LOCAL_VARIABLE修饰局部变量

ElementType.METHOD修饰方法定义

ElementType.PACKAGE修饰包定义

ElementType.PARAMETER修饰参数

ElementType.TYPE修饰类、接口或枚举定义

@Documented: 用于呗javadoc工具提取成文档,如果注释了提前的文档说明会有注释,否则没有。

@Inherited:指定被它修饰的Annotation将具有继承性。基类如有@Inherited,继承此基类的类也有此annotation。

4、提高

使用APT处理Annotation

APT(annotation processing tool)是一种处理注释工具。它对源文件进行检测找出其中的Annotation后,使用Annotation进行额外的处理。

Annotation处理器在处理Annotation时可以根据源文件中的Annotation生成额外的源文件和其他的文件(文件具体内容由Annotation处理器的编写者决定),APT还会编译

生成的源代码文件和原来的源文件,将它们一起生成class文件。

使用APT主要目的是简化开发者的工作量,因为APT可以在编译程序源代码的同时,生成一些附属文件(比如源文件、类文件、程序发布描述文件等),这些附属文件的内容

也都是与源代码相关的。换句话说,使用APT可以代替传统的对代码信息和附属文件的维护工作。

为了是系统的APT工具读取源文件中的Annotation,必须自定义一个Annotation处理器,编写处理器需要JDK lib目录中的tools.jar里的如下四个包:

com.sun.mirror.apt:和APT交互的接口

com.sun.mirror.declaration:包含各种封装类成员、类方法、类声明的接口

com.sun.mirror.type:包含各种封装源代码中程序元素的接口。

com.sun.mirror.util:提供了用于处理类型和声明的一些工具。

对于APT的使用,比如hibernate自动生成的bean属性文件xxx.xxx.xml,实现原理就是APT。编写自己的Annotation,

在bean类中引用自定义Annotation,系统会调用APT生成响应的配置文件。

时间: 2025-01-01 08:04:23

Java注释(注解)简介的相关文章

深入理解Java:注解(Annotation)--注解处理器

深入理解Java:注解(Annotation)--注解处理器 如果没有用来读取注解的方法和工作,那么注解也就不会比注释更有用处了.使用注解的过程中,很重要的一部分就是创建于使用注解处理器.Java SE5扩展了反射机制的API,以帮助程序员快速的构造自定义注解处理器. 注解处理器类库(java.lang.reflect.AnnotatedElement): Java使用Annotation接口来代表程序元素前面的注解,该接口是所有Annotation类型的父接口.除此之外,Java在java.l

第17篇-JAVA Annotation 注解

第17篇-JAVA Annotation 注解 每篇一句 :真的努力后你会发现自己要比想象的优秀很多 初学心得: 怀着一颗奋斗不息的心,一切困苦艰辛自当迎刃而解 (笔者:JEEP/711)[JAVA笔记 | 时间:2017-05-17| JAVA Annotation注解 ] 1.什么是注解(Annotation) Annotation 其实就是代码里的特殊标记, 它用于替代配置文件,也就是说,传统方式通过配置文件告诉类如何运行,有了注解技术后,开发人员可以通过注解告诉类如何运行.在Java技术

Java Annotation 注解

java_notation.html div.oembedall-githubrepos { border: 1px solid #DDD; list-style-type: none; margin: 0 0 10px; padding: 8px 10px 0; font: 13.34px/1.4 helvetica, arial, freesans, clean, sans-serif; width: 452px; background-color: #fff } div.oembedall

java自定义注解类

一.前言 今天阅读帆哥代码的时候,看到了之前没有见过的新东西, 比如java自定义注解类,如何获取注解,如何反射内部类,this$0是什么意思? 于是乎,学习并整理了一下. 二.代码示例 import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Tar

[2]注解(Annotation)-- 深入理解Java:注解(Annotation)自定义注解入门

转载 http://www.cnblogs.com/peida/archive/2013/04/24/3036689.html 深入理解Java:注解(Annotation)自定义注解入门 要深入学习注解,我们就必须能定义自己的注解,并使用注解,在定义自己的注解之前,我们就必须要了解Java为我们提供的元注解和相关定义注解的语法. 元注解: 元注解的作用就是负责注解其他注解.Java5.0定义了4个标准的meta-annotation类型,它们被用来提供对其它 annotation类型作说明.J

【面试加分项】java自定义注解之申明注解

之前的博客http://blog.csdn.net/u010590685/article/details/47029447介绍了java的注解的基本知识今天我们学习如何使用自定义注解. 首先我们要声明一个注解,声明代码如下: import java.lang.annotation.Documented; import java.lang.annotation.ElementType; import java.lang.annotation.Inherited; import java.lang.

java 注释annotation学习---两篇不错的blog

深入理解Java:注解(Annotation)自定义注解入门 ---- http://www.cnblogs.com/peida/archive/2013/04/24/3036689.html 深入理解Java:注解(Annotation)--注解处理器 -----http://www.cnblogs.com/peida/archive/2013/04/26/3038503.html 其中第一个文章里面提到的: 有四个元注解: 为JDK的解释: Documented : 指示某一类型的注释将通过

深入理解Java:注解(Annotation)基本概念

转自 竹子-博客:http://www.cnblogs.com/peida/archive/2013/04/23/3036035.html 什么是注解(Annotation): Annotation(注解)就是Java提供了一种元程序中的元素关联任何信息和着任何元数据(metadata)的途径和方法.Annotion(注解)是一个接口,程序可以通过反射来获取指定程序元素的Annotion对象,然后通过Annotion对象来获取注解里面的元数据. Annotation(注解)是JDK5.0及以后版

[3] 注解(Annotation)-- 深入理解Java:注解(Annotation)--注解处理器

转载 http://www.cnblogs.com/peida/archive/2013/04/26/3038503.html 深入理解Java:注解(Annotation)--注解处理器 如果没有用来读取注解的方法和工作,那么注解也就不会比注释更有用处了.使用注解的过程中,很重要的一部分就是创建于使用注解处理器.Java SE5扩展了反射机制的API,以帮助程序员快速的构造自定义注解处理器. 注解处理器类库(java.lang.reflect.AnnotatedElement): Java使用

[1] 注解(Annotation)-- 深入理解Java:注解(Annotation)基本概念

转载 http://www.cnblogs.com/peida/archive/2013/04/23/3036035.html 深入理解Java:注解(Annotation)基本概念 什么是注解(Annotation): Annotation(注解)就是Java提供了一种元程序中的元素关联任何信息和着任何元数据(metadata)的途径和方法.Annotion(注解)是一个接口,程序可以通过反射来获取指定程序元素的Annotion对象,然后通过Annotion对象来获取注解里面的元数据. Ann