33_张孝祥_Java基础加强_了解和入门注解的应用
l 了解注解及java提供的几个基本注解。
Ÿ 先通过@SuppressWarnings的应用让大家认识和了解一下注解:
Ø 通过System.runFinalizersOnExit(true);的编译警告引出@SuppressWarnings("deprecation")
Ÿ @Deprecated
Ø 直接在刚才的类中增加一个方法,并加上@Deprecated标注,在另外一个类中调用这个方法。
Ÿ @Override
Ø public boolean equals(Reflect other)方法与HashSet结合讲解。
Ÿ 总结:
Ø 注解相当于一种标记,在程序中加了注解就等于为程序打上了某种标记,没加,则等于没有某种标记,以后,javac编译器,开发工具和其他程序可以用反射来了解你的类及各种元素上有无何种标记,看你有什么标记,就去干相应的事。标记可以加在包,类,字段,方法,方法的参数以及局部变量上。
Ø 看java.lang包,可看到JDK中提供的最基本的annotation。
34_张孝祥_Java基础加强_注解的定义与反射调用
l 注解的应用结构图
l 一个注解的生命周期有三个阶段:java源文件àclass文件-->在内存中的字节码。
l 自定义注解及其运用
Ø 定义一个最简单的注解:public @interfaceMyAnnotation {}
Ø 把它加在某个类上:@MyAnnotation public classAnnotationTest{}
Ø 用反射进行测试AnnotationTest的定义上是否有@MyAnnotation
Ø 根据发射测试的问题,引出@Retention元注解的讲解,其三种取值:RetetionPolicy.SOURCE、RetetionPolicy.CLASS、RetetionPolicy.RUNTIME;分别对应:java源文件-->class文件-->内存中的字节码。
Ÿ 思考:@Override、@SuppressWarnings和@Deprecated这三个注解的属性值分别是什么?
Ø 演示和讲解@Target元注解
Ÿ Target的默认值为任何元素,设置Target等于ElementType.METHOD,原来加在类上的注解就报错了,改为用数组方式设置{ElementType.METHOD,ElementType.TYPE}就可以了。
Ø 元注解以及其枚举属性值不用记,只要会看jdk提供那几个基本注解的API帮助文档的定义或其源代码,按图索骥即可查到,或者直接看java.lang.annotation包下面的类。
l 为注解增加基本属性
Ø 什么是注解的属性?
一个注解相当于一个胸牌,如果你胸前贴了胸牌,就是传智播客的学生,否则,就不是。如果还想区分出是传智播客哪个班的学生,这时候可以为胸牌在增加一个属性来进行区分。加了属性的标记效果为:@MyAnnotation(color="red")
Ø 定义基本类型的属性和应用属性:
<1>在注解类中增加String color();
<2>@MyAnnotation(color="red");
Ø 用反射方式获得注解对应的实例对象后,再通过该对象调用属性对应的方法
u MyAnnotation a =(MyAnnotation)AnnotationTest.class.getAnnotation(MyAnnotation.class);
u System.out.println(a.color());
u 可以认为上面这个@MyAnnotation是MyAnnotaion类的一个实例对象
Ø 为属性指定缺省值:
u String color() default "yellow";
Ø value属性:
u String value() default "zxx";
u 如果注解中有一个名称为value的属性,且你只想设置value属性(即其他属性都采用默认值或者你只有一个value属性),那么可以省略value=部分,例如:@MyAnnotation("lhm")。
l 为注解增加高级属性
Ø 数组类型的属性
u int [] arrayAttr() default {1,2,3};
u @MyAnnotation(arrayAttr={2,3,4})
u 如果数组属性中只有一个元素,这时候属性值部分可以省略大括
Ø 枚举类型的属性
u EnumTest.TrafficLamp lamp() ;
u @MyAnnotation(lamp=EnumTest.TrafficLamp.GREEN)
Ø 注解类型的属性:
u MetaAnnotation annotationAttr() default@MetaAnnotation("xxxx");
u @MyAnnotation(annotationAttr=@MetaAnnotation(“yyy”) )
u 可以认为上面这个@MyAnnotation是MyAnnotaion类的一个实例对象,同样的道理,可以认为上面这个@MetaAnnotation是MetaAnnotation类的一个实例对象,调用代码如下:
MetaAnnotationma = myAnnotation.annotationAttr();
System.out.println(ma.value());
Ø 注解的详细语法可以通过看java语言规范了解,即看java的language specification。
视频代码演示:
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)/*原注解,此注解是说保留到运行期间*/
@Target({ElementType.METHOD,ElementType.TYPE})
public @interface ItcastAnnotation {
String color() default"blue";
String value();
int[] arrayAttr()default {3,4,4};
EnumTest.TrafficLamp lamp() default EnumTest.TrafficLamp.RED;//注意:TrafficLamp是定义在EnumTest类的内部的。
MetaAnnotation annotationAttr()default@MetaAnnotation("lhm");
}
public @interface MetaAnnotation {
String value();
}
import java.lang.reflect.Method;
import javax.jws.soap.InitParam;
@ItcastAnnotation(annotationAttr=@MetaAnnotation("flx"),color="red",value="abc",arrayAttr=1)
public class AnnotationTest {
@SuppressWarnings("deprecation")
@ItcastAnnotation("xyz")
public static void main(String[] args)throws Exception{
// TODO Auto-generatedmethod stub
System.runFinalizersOnExit(true);
if(AnnotationTest.class.isAnnotationPresent(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());
}
Method mainMethod = AnnotationTest.class.getMethod("main", String[].class);
ItcastAnnotation annotation2 = (ItcastAnnotation)mainMethod.getAnnotation(ItcastAnnotation.class);
System.out.println(annotation2.value());
}
@Deprecated
public static void sayHello(){
System.out.println("hi,传智播客");
}
}
l 为了加强本知识点,模仿视频,配合java api再次进行练习。
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@Retention(RetentionPolicy.RUNTIME)//注意:不加此注解,生命周期达不到运行期间。
public @interface MyAnnotation {
String name() default"李某某";
WeekDay weekday() default WeekDay.MON;
int[] ArrayAttr();
MyAnnotation.MetaAnnotation annotationAttr()default@MetaAnnotation("hah");
public enum WeekDay{
SUN(){
@Override
public WeekDay nextDay() {
returnMON;
}
}
,MON(){
@Override
public WeekDay nextDay() {
returnTUE;
}
}
,TUE() {
@Override
public WeekDay nextDay() {
returnWED;
}
}
,WED() {
@Override
public WeekDay nextDay() {
returnTHU;
}
}
,THU() {
@Override
public WeekDay nextDay() {
returnFRI;
}
}
,FRI() {
@Override
public WeekDay nextDay() {
returnSAT;
}
}
,SAT() {
@Override
public WeekDay nextDay() {
returnSUN;
}
};//注解内部也能定义枚举类型
public abstract WeekDay nextDay();
}
/*当一个注解中只定义了一个属性,赋初值的时候可以直接省略属性名
* 例如,@MetaAnnotation("hello"),这种赋值是正确的。
* */
public @interface MetaAnnotation{//在注解内部定义注解
String value();
}
}
import java.lang.reflect.Array;
import day26annotation.MyAnnotation.MetaAnnotation;
@MyAnnotation(name="李斯",ArrayAttr={1,2,3},annotationAttr=@MetaAnnotation("xy"))
public class MyAnnotationTest {
public static void main(String[] args) {
if(MyAnnotationTest.class.isAnnotationPresent(MyAnnotation.class)){//判断此类上是否存在指定注解。
MyAnnotation annotation = MyAnnotationTest.class.getAnnotation(MyAnnotation.class);//获取注解实例
System.out.println(annotation.name());//打印属性的值,注意此处不是调用一个函数。
System.out.println(annotation.weekday().SUN.nextDay());//MON
System.out.println(Array.get(annotation.ArrayAttr(), 2));//打印数组指定索引元素的值,返回值类型是Object类型。
System.out.println(annotation.annotationAttr().value());//打印内部注解的属性值
}
}
}
/*
打印结果:
MON
3
xy
*/