Java之------注解 ( Annotation )

★ 元数据

        所谓元数据就是数据的数据。也就是说,元数据是描述数据的。就象数据表中的字段一样,每个字段描述了这个字段下的数据的含义。
       元数据可以用于创建文档,跟踪代码中的依赖性,甚至执行基本编译时检查。许多元数据工具,如XDoclet,将这些功能添加到核心Java语言中,暂时成为Java编程功能的一部分。
        一般来说,元数据的好处分为三类:文档编制、编译器检查和代码分析。代码级文档最常被引用。元数据提供了一种有用的方法来指明方法是否取决于其他方法,它们是否完整,特定类是否必须引用其他类,等等。 

★ 什么是注解

       Java中的注解就是Java源代码的元数据,也就是说注解是用来描述Java源代码的。  基本语法就是:@后面跟注解的名称。

★ Java中预定义注解 (Java.lang包当中的三个预定注解)

①Override:标识某一个方法是否正确覆盖了它的父类的方法。
②Deprecated:表示已经不建议使用这个类成员了。  它是一个标记注解。
③SuppressWarnings:用来抑制警告信息。


自定义注解1

自定义注解的语法很简单,跟定义接口类似,只是在名称前面加上@符号。 在MyEclipse中新建时有一个Annotation和Class和Interface放在一起的,这个Annotation文件就是注解。

★ 最简单的自定义注解

public @interface MyAnno {
}
★ 使用这个注解

@MyAnno
public class UserModel{
} 
★ 为注解添加成员

//定义
public @interface MyAnno {
  public String schoolName();
}
//使用
@MyAnno(schoolName="湖南长沙")
public class UserModel{
} 


自定义注解2

★ 设置默认值

//定义
public @interface MyAnno {
  public String schoolName() default "湖南大学";//设置默认值
}
//使用1
@MyAnno//schoolName()会使用默认值"湖南大学"
public class UserModel{
}
//使用2
@MyAnno(schoolName="Java高手训练营")//schoolName会使用这个值
public class UserModel{
}

对注解的注解

☆指定目标 Target

在了解如何使用Target 之前,需要认识另一个类,该类被称为ElementType (通过API详细学习,java.lang.annotation包ElementType接口中有所有的枚举常量值) ,它实际上是一个枚举。这个枚举定义了注释类型可应用的不同程序元素。 

如:

@Target({ ElementType.TYPE, ElementType.METHOD}) 
☆设置保持性 Retention

 RetentionPolicy (通过API详细学习)枚举类中定义了3种注解保持性,分别决定了Java 编译器以何种方式处理注解。  

如:

@Retention(RetentionPolicy.SOURCE) 
☆添加公共文档 Documented

在默认的情况下在使用javadoc自动生成文档时,注解将被忽略掉。如果想在文档中也包含注解,必须使用Documented为文档注解。

@Documented
☆设置继承 Inherited

在默认的情况下,父类的注解并不会被子类继承。如果要继承,就必须加上Inherited注解。 

@Inherited


如何读取注解

        要读取注解的内容,就需要使用反射的技术。   注意:要想使用反射得到注释信息,须用@Retention(RetentionPolicy.RUNTIME)进行注解。

如:

import java.lang.reflect.*;
public class TestMyAnno {
  public static void main(String[] args)throws Exception {
    Class c = Class.forName(“anno.UserModel");
    boolean flag = c.isAnnotationPresent(MyAnno.class);
    System.out.println(flag);
    if(flag){
      MyAnno ma = (MyAnno)c.getAnnotation(MyAnno.class);
      System.out.println("学校名称:=="+ma.schoolName());
      //获取到了这些数据过后,下面就可以开始你的处理了
    }
  }
}

下面是具体的代码实现:

先通过一个小例子热热身:

package cn.hncu.anno;

import java.util.ArrayList;

import org.junit.Test;

//@MyAnno
public class MyThread extends Thread {
	private int num=100;
	
	@Override
	public void run() {
		System.out.println("run......");
	}
	
	@SuppressWarnings("rawtypes")
	@Deprecated
	public void aaa(){
		ArrayList list=new ArrayList();
		System.out.println(list);
	}
	
	@Test
	public void test(){
		MyThread t1=new MyThread();
		t1.start();
		aaa();
	}
}

运行结果:

Java之------注解 ( Annotation )_第1张图片

下面正式开始:

注解一:

package cn.hncu.anno;

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

@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE,ElementType.METHOD})
public @interface MyAnno {
}
注解二:
package cn.hncu.anno;

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

@Retention(RetentionPolicy.RUNTIME)
public @interface MyAnno2 {
	public String schoolName() default "湖南大学";
}

新建一个类用于加注解便于测试

package cn.hncu.anno;

@MyAnno
public class UserModel {
	private String uuid;
	private String name;
//	@MyAnno
	private int age;
	
	public String getUuid() {
		return uuid;
	}
	
	@MyAnno
	public void setUuid(String uuid) {
		this.uuid = uuid;
	}
	
	@MyAnno2
	public String getName() {
		return name;
	}
	
	@MyAnno2(schoolName="Java培训班")
	public void setName(String name) {
		this.name = name;
	}
	
	@MyAnno
	public int getAge() {
		return age;
	}
	
	public void setAge(int age) {
		this.age = age;
	}
}
建立一个测试类:

package cn.hncu.anno;

import java.lang.reflect.Method;

import org.junit.Test;

public class Demo {
	
	/**
	 * 分别读取类上的@MyAnno注解 和  方法上的@MyAnno注解
	 */
	@Test
	public void readAnno(){
		//※※注意:MyAnno注解定义时,必须指定它的保持性为 RUNTIME,否则下面是读取不出注解的
		
		//以下方式是读取“声明在类上的”MyAnno注解
		Class cls=UserModel.class;
//		boolean boo=cls.isAnnotationPresent(MyAnno.class);//这种方式可行
//		boolean boo=cls.isAnnotationPresent(cn.hncu.anno.MyAnno.class);//这种方式也可行
		boolean boo=(cls.getAnnotation(MyAnno.class)!=null);
		System.out.println(boo);
		
		//以下方式是读取“声明在方法上的”MyAnno注解
		Method methods[]=cls.getDeclaredMethods();
		for (Method m:methods){
			if (m.isAnnotationPresent(MyAnno.class)){
				System.out.println(m.getName()+"方法上有@MyAnno注解");
			}
		}
	}
	
	/**
	 * 读取@MyAnno2注解及它的schoolName参数---在注解中指定了参数值的
	 * @throws Exception 
	 *  
	 */
	@Test
	public void readAnno2() throws Exception{
		Class cls=UserModel.class;
		Class paramTypes[]=new Class[1];
		paramTypes[0]=String.class;
		Method m=cls.getDeclaredMethod("setName", paramTypes);
		if (m.isAnnotationPresent(MyAnno2.class)){
			MyAnno2 ma2=m.getAnnotation(MyAnno2.class);
			String sName=ma2.schoolName();
			System.out.println(sName);
		}
	}
	
	/**
	 * 读取@MyAnno2注解及它的schoolName参数---在注解中没有指定参数值,即读取默认的
	 */
	@Test
	public void readAnno3() throws Exception{
		Class cls=UserModel.class;
		Method m=cls.getDeclaredMethod("getName");
		if (m.isAnnotationPresent(MyAnno2.class)){
			MyAnno2 ma2=m.getAnnotation(MyAnno2.class);
			String sName=ma2.schoolName();
			System.out.println(sName);
		}
	}
}
readAnno()运行结果:

Java之------注解 ( Annotation )_第2张图片
readAnno2()运行结果:

Java之------注解 ( Annotation )_第3张图片

readAnno3()运行结果:

Java之------注解 ( Annotation )_第4张图片

你可能感兴趣的:(Java学习笔记)