注解(@):JDK1.5新特新。注解就相当于一种标记,在程序中加了注解就等于程序加了某种标记。
作用:告诉javac编译器或者java开发工具......向其传递某种信息,作为一个标记。
一个注解就是一个类。
标记可以加在包、类、字段、方法,方法参数以及局部变量上。可以同时存在多个注解。
每一个注解结尾都没有“;”或者其他特别符合。
eg:
@SuppressWarnings ("deprecation")//编译器警告过时(source阶段)
@Deprecated //过时(Runtime阶段)
@Override //重写(source阶段)
@Retention(RetentionPolicy.RUNTIME)//保留注解到程序运行时。(Runtime阶段)
@Target({ElementType.METHOD,ElementType.TYPE})//标记既能定义在方法上,又能定义在类、接口、枚举上等。
笔记:
①添加注解需要有注解类。RetentionPolicy是一个枚举类(有三个成员)。
②Target中可以存放数组。他的默认值为任何元素。
ElementType.METHOD:表示只能标记在方法上。
ElementType.TYPE:表示只能标记定义在类上、接口上枚举上等。
③ElementType也是枚举类。成员包括:ANNOTATION_TYPE(注解)、CONSTRUCTOR(构造方法)、FIEID(成员变量)、LOCAL_VARIABLE(变量)、
METHOD(方法)、PACKAGE(包)、PARAMETER(参数)、TYPE。
注解应用结构图:
简单相关知识了解:
元注解:注解的注解(理解:给一个注解类再加上注解)
元数据:数据的数据
元信息:信息的信息
注解分为三个阶段:java源文件→class文件→内存中的字节码。
Retention的注解有三种取值:(分别对应注解的三个阶段)
RetentionPolicy.SOURCE
RetentionPolicy.CLASS
RetentionPolicy.RUNTIME
笔记:注解的默认阶段是Class。
注解的属性类型:
原始类型(就是八个基本数据类型)、String类型、Class类型、数组类型、枚举类型、注解类型。
为注解增加属性:
value:是一个特殊的属性,若在设置值时只有一个value属性需要设置或者其他属性都采用默认值时,那么value=可以省略,直接写所设置的值即可。
eg:@SuppressWarnings("deprecation")
为属性指定缺省值(默认值):
eg:String value() default "blue";//定义在注解类中
数组类型的属性:
eg:int[] arrayArr() default {3,4,5,5};//定义在注解类中
SunAnnotation(arrayArr={3,9,8})//设置数组值
笔记:如果数组属性中只有一个元素时,属性值部分可以省略大括号。
eg:SunAnnotation(arrayArr=9)
枚举类型的属性:
eg:EnumDemo.TrafficLamp lamp()
default EnumDemo.trafficLamp.RED;
//枚举类型的属性,定义在注解类中,这里使用了自定义的枚举类EnumDemo.java
注解类型的属性:
eg:MetaAnnotation annotationAttr()
default @MetaAnnotation("lhm");
//定义在一个注解类中,并指定缺省值,此属性关联到注解类:MetaAnnotation.java
@SunAnnotation(annotationAttr=@MetaAnnotation("flx")) //设置注解属性值
代码参考:
AnnotationDemo.java:
/*
* 关联的类:
* 自定义注解类SunAnnotation.java
* 自定的枚举类EnumDemo.java
* 自定义类ReflectDemo.class、ReflectDemo2.class
* */
@SunAnnotation(annotationClass=ReflectDemo2.class,annotationAttr=@MetaAnnotation("flx"),color="red",value="abc",arrayArr={1,3,9}) //注解:为注解添加属性值
//若在设置值时只有一个value属性需要设置 ,那么value可以省略,直接写所设置的值即可。
public class AnnotationDemo {
@SunAnnotation("xyz")
@SuppressWarnings("deprecation") //注解:告诉编译器或者开发工具……
//若在设置值时只有一个value属性需要设置 ,那么value可以省略,直接写所设置的值即可。
//上面"deprecation"即是省略的value后的值。
public static void main(String[] args)throws Exception {
System.runFinalizersOnExit(true);//中间带横线的部分,说明该方法已经过时了。
//检查某注解是否存在,使用反射;并返回该注解
if(AnnotationDemo.class.isAnnotationPresent(SunAnnotation.class))
{
//获取注解
SunAnnotation annotation=(SunAnnotation)AnnotationDemo.class.getAnnotation(SunAnnotation.class);
//获取属性值
System.out.println("属性color值:"+annotation.color());//调用color属性方法
System.out.println(annotation.value());
System.out.println(annotation.arrayArr().length);//这里输出的是数组长度,不能直接输出数组的每一个值,调用得到的是数组哈希地址值
System.out.println(annotation.lamp().nextLamp().name());//调用注解默认灯的nextLamp方法
annotation.annotationAttr().value();
//获取类类型注解中的 类名称
System.out.println(annotation.annotationClass());
}
}
@Deprecated //表示下面的方法过时了
public static void sayHello()
{
System.out.println("hi");
}
}
SunAnnotation.java
/*
* 元注解:注解的注解
* 元数据:数据的数据
* 元信息:信息的信息
* */
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.METHOD:表示只能标记在方法上。ElementType.TYPE:表示只能标记定义在类上、接口上、枚举上等。
@Target({ElementType.METHOD,ElementType.TYPE})
public @interface SunAnnotation {
String color() default "blue"; //表示有一个color属性,以方法的形式。设置默认属性值为蓝色
String value();
//是一个特殊的属性,若在设置值时只有一个value属性需要设置 ,那么value可以省略,直接写所设置的值即可。
//数组属性
int[] arrayArr() default {3,4,5,5};
//枚举类型属性,这里使用了自定的枚举类EnumDemo.java
EnumDemo.TrafficLamp lamp() default EnumDemo.TrafficLamp.RED;
//注解类型属性,此时关联到注解类:MetaAnnotation.java,并指定缺省值
MetaAnnotation annotationAttr() default @MetaAnnotation("lhm");
//Class类属性:设置默认值 ReflectDemo.java 类
Class annotationClass() default ReflectDemo.class;
}
EnumDemo.java
//枚举的基本实例
public class EnumDemo {
public static void main(String[] args) {
// TODO Auto-generated method stub
WeekDay weekDay=WeekDay.FRI;
System.out.println(weekDay);
System.out.println(weekDay.name());
System.out.println(weekDay.ordinal());
System.out.println(weekDay.getClass());
//将字符串变成枚举对应的元素
System.out.println(weekDay.valueOf("SUN").toString());//这里默认调用toString方法,可以不加的
//将枚举所有元素转换成数组进行操作
System.out.println(weekDay.values().length);
}
//内部类:枚举—— 星期几示例
public enum WeekDay{
//枚举的元素列表必须在首位,其他方法等位于其后。
//这些元素都是静态的,默认调用的是无参构造。若想调用带参构造就在对应元素后加相应参数
SUN(2),MON,TUE,WED,THI,FRI,STA;
//每个元素原型:public static final WeekDay SUN =new WeekDay(){};
//枚举类的构造方法必须是私有的
private WeekDay(){
System.out.println("first");
}
private WeekDay(int day){
System.out.println("Sencond");
}
}
//内部类:枚举—— 交通灯示例 带有抽象方法
public enum TrafficLamp{
//定义枚举元素列表RED、GREEN、YELLOW
//RED、GREEN、YELLOW是TrafficLamp的子类的实例对象
//new子类的实例对象,实现父类的抽象方法
//RED后带括号参数,表示指定调用有参构造函数
RED(30){
//实现父类TrafficLamp的nextLamp方法
public TrafficLamp nextLamp()
{
return GREEN;
}
},
GREEN(45){
public TrafficLamp nextLamp()
{
return YELLOW;
}
},
YELLOW(5){
public TrafficLamp nextLamp()
{
return RED;
}
};
//类中有私有的成员变量:每个灯都有自己的时间
private int time;
//私有带参构造:
private TrafficLamp(int time){
this.time=time;
}
//定义一个抽象方法,返回值类型是本类
public abstract TrafficLamp nextLamp();
}
}