package cn.itcast.day2;
@ItcastAnnotation
public class AnnotationTest {
/**
* @param args
*/
@SuppressWarnings("deprecation")//注解,过时的就可以用了 压缩警告 一个注解是一个类
//@SuppressWarnings("deprecation")用于告诉javac编译器该怎样
//@ItcastAnnotation
public static void main(String[] args) throws Exception{
// TODO Auto-generated method stub
System.runFinalizersOnExit(true);//语言过时了
if(AnnotationTest.class.isAnnotationPresent(ItcastAnnotation.class))//ItcastAnnotation注解是保存在class里面的
{
ItcastAnnotation annotation=(ItcastAnnotation)AnnotationTest.class.getAnnotation(ItcastAnnotation.class);
System.out.println(annotation);
}
}
//如果把方法删去了,以前调用的会报错.新人不用,老的可以继续调用
//@Deprecated,这就说明这个方法已经作废。那么别人在引用的时候就会提示方法已经过时。
@Deprecated
public static void sayHello(){
System.out.println("hi,hiahia");
}
}
(一)概念
package cn.itcast.day2;
public class AnnotationTest {
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
System.runFinalizersOnExit(true);//语言过时了
}
}
AnnotationTest.java:10: 警告:[deprecation] java.lang.System 中的 runFinalizersOnExit(boolean) 已过时
System.runFinalizersOnExit(true);//语言过时了
^
1 警告
package cn.itcast.day2;
public class AnnotationTest {
/**
* @param args
*/
@SuppressWarnings("deprecation")//注解,过时的就可以用了 压缩警告 一个注解是一个类
public static void main(String[] args) {
// TODO Auto-generated method stub
System.runFinalizersOnExit(true);//语言过时了
}
}
2、写过的方法,现在已经不用,但之前调用还可以继续用 标记语言方法过时
@Deprecated,这就说明这个方法已经作废。那么别人在引用的时候就会提示方法已经过时。
例:
//如果把方法删去了,以前调用的会报错.新人不用,老的可以继续调用
@Deprecated
public static void sayHello(){
System.out.println("hi,hiahia");
如果再调用的话:
AnnotationTest.sayHello();
3、覆盖 子类是覆盖父类的方法
@Override
假如我们想覆盖类的equals方法:
public boolean equals(Point pt){
}
但是实际上这个方法并不是重写的Object的equals,如何限定我们就是覆盖的Object的equals而不会出错呢?当我们在方法前面加上@Override注解的时候,编译时就会提示我们其实并没有覆盖!
总结:
注解就是一个标记,加了注解就相当于给程序打了一种标记。
标记可以加载包上,类上,方法上,成员变量,方法的参数,方法的局部变量上面。
但是实际上这个方法并不是重写的Object的equals,如何限定我们就是覆盖的Object的equals而不会出错呢?当我们在方法前面加上@Override注解的时候,编译时就会提示我们其实并没有覆盖!
总结:注解就是一个标记,加了注解就相当于给程序打了一种标记。
标记可以加载包上,类上,方法上,成员变量,方法的参数,方法的局部变量上面。
java.lang包,可看到JDK中提供的最基本的annotation
(二)如何应用
注解就相当于一个你的源程序中要调用的一个类,要在源程序中应用某个注解,得先准备好了这个注解类。就像你要调用某个类,得先有开发好这个类。
注解类:
@interface A{
}
应用了“注解类”的类
@A
Class B{
}
对应用了注解类的类进行反射操作的类。
Class C{
B.class.isAnnotationPresent(A.class);
A a=B.class.getAnnotion(A.class);
}
例子:
在java透视图下,新建选择Annotation
main方法必须放在类里面,但main方法不见得属于这个类的成员
因为ItcastAnnotation注解是保存在class里面的,当调用到内存里时就没有了
所以在注解类ItcastAnnotation.java里面加了一个RUNTIME:一直保留到运行期间
注解类:
ItcastAnnotation.java
package cn.itcast.day2;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
//元注解,元数据,元信息
@Retention(RetentionPolicy.RUNTIME)//RUNTIME一直保留到运行期间
public @interface ItcastAnnotation {
}
应用了“注解类”的类
main方法必须放在类里面,但main方法不见得属于这个类的成员
AnnotationTest.java
package cn.itcast.day2;
import javax.jws.soap.InitParam;
@ItcastAnnotation(annotationAttr=@MetaAnnotation("flx"),color="red",value="abc",arrayAttr={1,2,3})
public class AnnotationTest {
/**
* @param args
*/
@SuppressWarnings("deprecation")//注解,过时的就可以用了 压缩警告 一个注解是一个类
//@SuppressWarnings("deprecation")用于告诉javac编译器该怎样
@ItcastAnnotation("xyz")
public static void main(String[] args) throws Exception{
// TODO Auto-generated method stub
System.runFinalizersOnExit(true);//语言过时了
/*
使用了AnnotatedElement类的isAnnotationPresent()方法判断某个方法是否具有@ItcastAnnotation.class
AnnotationTest.class得到AnnotationTest的字节码
ItcastAnnotation.class:只要是类,要表示它是不是class还是用字节码来表示
如果有
AnnotationTest.class.getAnnotation(ItcastAnnotation.class);得到ItcastAnnotation.class的注解
但是不知道哪一个具体类型的注解(ItcastAnnotation)进行类型转换
*/ if(AnnotationTest.class.isAnnotationPresent(ItcastAnnotation.class))//ItcastAnnotation注解是保存在class里面的
{
ItcastAnnotation annotation=(ItcastAnnotation)AnnotationTest.class.getAnnotation(ItcastAnnotation.class);
System.out.println(annotation.color());
System.out.println(annotation.value());
System.out.println(annotation.arrayAttr().length);
System.out.println(annotation.lamp().nextLamp().name());
System.out.println(annotation.annotationAttr().value());
}
}
//如果把方法删去了,以前调用的会报错.新人不用,老的可以继续调用
//@Deprecated,这就说明这个方法已经作废。那么别人在引用的时候就会提示方法已经过时。
@Deprecated
public static void sayHello(){
System.out.println("hi,hiahia");
}
}
注:
@Override注解的@Retention在哪个阶段
@Override是给javac看的,编译完就没有价值了,也就是说在源代码阶段有用,处理成class就没意义了,保留在source阶段
@SuppressWarnings
SuppressWarnings是给编译器看的,source,运行期间
@Deprecated这个注解的@Retention是
Deprecated是给编译器看的
源程序调用这个类,编译器提示过时了
@SuppressWarnings("deprecation")//注解,过时的就可以用了 压缩警告 一个注解是一个类
//@SuppressWarnings("deprecation")用于告诉javac编译器该怎样
public static void main(String[] args) throws Exception{
System.runFinalizersOnExit(true);//语言过时了
if(AnnotationTest.class.isAnnotationPresent(ItcastAnnotation.class))//ItcastAnnotation注解是保存在class里面的
{
ItcastAnnotation annotation=(ItcastAnnotation)AnnotationTest.class.getAnnotation(ItcastAnnotation.class);
System.out.println(annotation.color());
System.out.println(annotation.value());
System.out.println(annotation.arrayAttr().length);
System.out.println(annotation.lamp().nextLamp().name());
System.out.println(annotation.annotationAttr().value());
}
}
编译器在处理@SuppressWarnings时,在源程序找@SuppressWarnings,如果runFinalizersOnExit过时了,编译器在源程序看不到runFinalizersOnExit过时了,
编译器从System的字节码身上才看得到。
编译器怎么知道runFinalizersOnExit过时了,一定是把System加载到内存来,读System的二进制,检查二进制是否有runFinalizersOnExit方法。
编译器拿到的是System类的二进制编码,所以它保留的就是运行期间
@Retention(RetentionPolicy.RUNTIME)这个注解的意思就是:要让注解一直保留到运行时。
Retention:
1.当在源程序加上一个注解,这个源程序接着要由javac程序编译,javac把源文件编译成class
在编译成class的时候会把源程序里面的一些注解给去掉
2.javac编译成class文件时保留了注解,在用的时候要用类加载器把class调到内存里面,类加载器会对class进行一个处理
处理完后才是二进制的字节码,类加载器把class文件调到内存中也有转换,转换后class文件里面的注解是否留下来,也有说法
所以说一个注解周期有三个阶段
当javac把源文件编译成class的时候,需要做一些处理,而当jvm用类加载器把class里面的二进制数据加载进内存的时候,也要做一些处理,然后生成字节码Class。
因此,一个注解的生命周期有三个阶段:源文件->class文件->字节码。在设计注解的时候就需要指定
设计注解时可以加上@Retention这个说明,说明这个注解的生命周期在哪,元注解三个阶段:RetentionPolicy.SOURCE(元文件阶段),RetentionPolicy.CLASS(默认值),RetentionPolicy.RUNTIME(运行阶段)
注解存在的生命周期,用@Retention来指定,默认是保留在class阶段。
Override的Retention是保留在source阶段,SuppressWarnings也是给编译器看的,保留在source阶段,Deprecated是保留在运行时Runtime。
Retention的取值是一个enum,这个enum的名字叫做:RetentionPolicy,有三个常量和两个方法,CLASS,RUNTIME,SOURCE和static RetentionPolicy valueOf(String name) ,static
@Override、@SuppressWarnings返回的都是source
@Deprecated保留到运行阶段,因为我加在你身上,你这个类以后被别人用,别人知道过时了,别人不是在检查源代码,而是检查二进制代码,扫描有什么方法
他的@Retention填的值是个枚举,名称是RetentionPolicy
@Retention:保存在哪个生命周期
@Target:说明用在那个成分上
注解可以加载到类的那些成份上,枚举的名称是什么
@Target用于标明标记可以加在的成分上(包,类,枚举,注解,接口,字段,方法,构造方法、方法的参数上和局部变量上)
Type
(三)为注解增加属性
一个注解相当于一个胸牌,如:胸前贴了胸牌,就是学生,否则就不是。如果还想区分是哪个班的学生,可以在增加一个属性进行区分。
注解很像接口,他的属性很像方法
default属性的默认值,value属性的特殊运用
package cn.itcast.day2; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; import cn.itcast.day1.EnumTest; @Retention(RetentionPolicy.RUNTIME)//让ItcastAnnotation注解一直保留到RUNTIME运行期间 @Target({ElementType.METHOD,ElementType.TYPE})//枚举 (ElementType.METHOD)在方法上有注释,加上{ElementType.TYPE}就可以在类上用了 //用.TYPE而不是CLASS:因为class有一个父类时type,Type比class更精准,1.5以后出来的 public @interface ItcastAnnotation { /* * 方法color,返回值String,这个方法是抽象的也是public的,不用加指定缺醒值, * blue,可以不用必须写 */ String color() default "blue";//为注解添加属性,添加
default "blue",
@ItcastAnnotation("xyz")才可以用
String value();int[] arrayAttr() default {3,4,5};//数组类型注解EnumTest.TrafficLamp lamp() default EnumTest.TrafficLamp.RED;//枚举类型注解MetaAnnotation annotationAttr() default @MetaAnnotation("lhm");}
@ItcastAnnotation(annotationAttr=@MetaAnnotation("flx"),color="red",value="abc",arrayAttr={1,2,3})用的时候为他设置属性@ItcastAnnotation(color="red") /**
* @param args
*/
@SuppressWarnings("deprecation") @ItcastAnnotation("xyz")//只有value属性要设的时候,不用谢value=,因为注解里有
public class AnnotationTest {
ItcastAnnotation annotation=(ItcastAnnotation)AnnotationTest.class.getAnnotation(ItcastAnnotation.class);
/*
* color用的时候以属性的形式用,设值的时候以属性的形式设值,
* 取值的时候,以以方法调用的形式调用
*/System.out.println(annotation.color());//结果是red }
方法一:在方法上边注释
package cn.itcast.day2;
public class AnnotationTest {
/**
* @param args
*/
@SuppressWarnings("deprecation")//注解,过时的就可以用了 压缩警告 一个注解是一个类
//@SuppressWarnings("deprecation")用于告诉javac编译器该怎样
@ItcastAnnotation
public static void main(String[] args) throws Exception{
// TODO Auto-generated method stub
System.runFinalizersOnExit(true);//语言过时了
if(AnnotationTest.class.isAnnotationPresent(ItcastAnnotation.class))//ItcastAnnotation注解是保存在class里面的
{
ItcastAnnotation annotation=(ItcastAnnotation)AnnotationTest.class.getAnnotation(ItcastAnnotation.class);
System.out.println(annotation);
}
}
//如果把方法删去了,以前调用的会报错.新人不用,老的可以继续调用
//@Deprecated,这就说明这个方法已经作废。那么别人在引用的时候就会提示方法已经过时。
@Deprecated
public static void sayHello(){
System.out.println("hi,hiahia");
}
}
package cn.itcast.day2;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
//元注解,元数据,元信息
@Retention(RetentionPolicy.RUNTIME)//RUNTIME一直保留到运行期间
@Target(ElementType.METHOD)//枚举
public @interface ItcastAnnotation {
}
方法二:在类上注释
package cn.itcast.day2;
@ItcastAnnotation
public class AnnotationTest {
/**
* @param args
*/
@SuppressWarnings("deprecation")//注解,过时的就可以用了 压缩警告 一个注解是一个类
//@SuppressWarnings("deprecation")用于告诉javac编译器该怎样
//@ItcastAnnotation
public static void main(String[] args) throws Exception{
// TODO Auto-generated method stub
System.runFinalizersOnExit(true);//语言过时了
if(AnnotationTest.class.isAnnotationPresent(ItcastAnnotation.class))//ItcastAnnotation注解是保存在class里面的
{
ItcastAnnotation annotation=(ItcastAnnotation)AnnotationTest.class.getAnnotation(ItcastAnnotation.class);
System.out.println(annotation);
}
}
//如果把方法删去了,以前调用的会报错.新人不用,老的可以继续调用
//@Deprecated,这就说明这个方法已经作废。那么别人在引用的时候就会提示方法已经过时。
@Deprecated
public static void sayHello(){
System.out.println("hi,hiahia");
}
}
package cn.itcast.day2;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
//元注解,元数据,元信息
@Retention(RetentionPolicy.RUNTIME)//RUNTIME一直保留到运行期间
@Target({ElementType.METHOD,ElementType.TYPE})//枚举 Target里面用数组 加上{ElementType.TYPE}就可以在类上用了
public @interface ItcastAnnotation {
}
(四)为注解增加高级属性
数组类型的属性
int[] arrayAttr() default{1,2,3};
@MyAnnotation(arrayAttr={2,3,4})
如果数组属性中只有一个元素,这时属性值部分可以省略大括号
枚举类型的属性
EnumTest.TrafficLamp lamp();
@MyAnnotation(lamp=EnumTest.TrafficLamp.GREEN)
注解类型的属性
注解返回的类型能是:原始类型,String,Class,还可以是枚举类型,注解类型
class
例如:
@ItcastAnnotation(a=String.class) //a属性的返回值是class:String.class
注解类:
package cn.itcast.day2;
public @interface MetaAnnotation {
String value();
}
package cn.itcast.day2;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import cn.itcast.day1.EnumTest;
/*
* 在注解上加的注解
* 元注解,元数据,元信息
*/
@Retention(RetentionPolicy.RUNTIME)//RUNTIME一直保留到运行期间
@Target({ElementType.METHOD,ElementType.TYPE})//枚举 加上{ElementType.TYPE}就可以在类上用了
public @interface ItcastAnnotation {
String color() default "blue";//指定缺醒值,blue,可以不用必须写
String value();
int[] arrayAttr() default {3,4,5};//数组类型注解
EnumTest.TrafficLamp lamp() default EnumTest.TrafficLamp.RED;//枚举类型注解
MetaAnnotation annotationAttr() default @MetaAnnotation("lhm");
}
package cn.itcast.day2;
import javax.jws.soap.InitParam;
@ItcastAnnotation(annotationAttr=@MetaAnnotation("flx"),color="red",value="abc",arrayAttr={1,2,3})
public class AnnotationTest {
/**
* @param args
*/
@SuppressWarnings("deprecation")//注解,过时的就可以用了 压缩警告 一个注解是一个类
//@SuppressWarnings("deprecation")用于告诉javac编译器该怎样
@ItcastAnnotation("xyz")
public static void main(String[] args) throws Exception{
// TODO Auto-generated method stub
System.runFinalizersOnExit(true);//语言过时了
if(AnnotationTest.class.isAnnotationPresent(ItcastAnnotation.class))//ItcastAnnotation注解是保存在class里面的
{
ItcastAnnotation annotation=(ItcastAnnotation)AnnotationTest.class.getAnnotation(ItcastAnnotation.class);
System.out.println(annotation.color());
System.out.println(annotation.value());
System.out.println(annotation.arrayAttr().length);//数组类型
System.out.println(annotation.lamp().nextLamp().name());//枚举类型
System.out.println(annotation.annotationAttr().value());//注解annotation的属性annotationAttr返回值还是注解,而这 //个注解上还有属性
}
}
//如果把方法删去了,以前调用的会报错.新人不用,老的可以继续调用
//@Deprecated,这就说明这个方法已经作废。那么别人在引用的时候就会提示方法已经过时。
@Deprecated
public static void sayHello(){
System.out.println("hi,hiahia");
}
}