黑马程序员---java高新技术之注解

本文深入讲解Java注解的原理和应用,包括基本注解的使用、自定义注解的创建及注解处理器的设计等核心内容。

------- android培训java培训、期待与您交流! ----------

注解:

总结:

注解相当于一种标记,加了注解就等于打上了某种标记,没加,则等于没有某种标记。注解是以@标记开头的。注解是向编译器或开发工具传递某种信息,告诉编译器或开发工具应该怎么的,不应该怎么的,作为一种标记来传递信息。记住,以后,javac编译器,开发工具和其他程序可以用反射来了解你的类及各种元素段上有无何种标记,看你有什么标记,就去干相应的事,标记可以加在包,类,字段,方法,方法的参数以及局部变量上。

了解注解java提供的几个基本注解:

先通过@SuppressWarnings的应用让大家直观地了解注解:

       通过System.runFinalizersOnExit(true);的编译警告引出

       @SuppressWarnings(“deprecation”):取消显示的警告集

     

 publicclassAnnotationTest {

       @SuppressWarnings("deprecation")//这是一个注解。将由编译器在注释的元素中取消显示的警告集。允许使用重复的名称。忽略第二个和后面出现的名称。

       publicstaticvoid main(String[] args){

           System.runFinalizersOnExit(true);

       /*

       使用过时的方法时,在eclipse中,System.runFinalizersOnExit(true)方法会出现删除线,说明这个方法已经过时了。

       如果在命令行中,编译的时候会提示:

           注: Test2.java使用或覆盖了已过时的 API。

           注: 有关详细信息, 请使用 -Xlint:deprecation 重新编译。

       加上@SuppressWarnings("deprecation")这个注解后,就等于告诉编译器,尽管你这个方法已经过时了,

       但是我就是要用,在命令行窗口编译的时候提示就会消失了,这就是注解的作用。

        */

       }

}


      

@Deprecated

       直接在刚才的类中增加一个方法,并加上@Deprecated标注,在另一个类中调用这个方法。

class Test1 {

    @Deprecated

    /*用 @Deprecated 注释的程序元素,表示提示不鼓励程序员使用这样的元素,

     *通常是因为它很危险或存在更好的选择。在使用不被赞成的程序元素或在不被赞成的代码中执行重写时,编译器会发出警告。

     *在eclipse中会出现删除线,在命令行中会出现和上面一样的情况,这就等于告诉调用者这个方法已经过时了,不要再用了。

     * */

    publicstaticvoid sayHello(){

       System.out.println("hi,传智播客");

    }

}

publicclass Test {

    publicstaticvoid main(String[] args){

       Test1.sayHello();//这里调用syaHello方法就出现了删除线,表示已经过时

    }

}

 

@Override

Public boolean equals(Reflect Other)与hashset结合:

publicclassReflectPoint {

   

    privateintx;

    publicinty;

   

    public ReflectPoint(int x, int y) {

       super();

       this.x = x;

       this.y = y;

    }

 

    @Override

    /*  @Override:表示一个方法声明打算重写超类中的另一个方法声明。如果方法利用此注释类型进行注解但没有重写超类方法,则编译器会生成一条错误消息。

     * 这里加了@Override注解后就表明接下来的方法会覆盖父类中的一个方法,如果不覆盖编译就不通过,如果

     * */

    publicbooleanequals(ReflectPoint obj) {//由于父类的方法Public boolean equals(Reflect Other)形参类型是Reflect类类型,因此编译不通过

       if (this == obj)

           returntrue;

       if (obj == null)

           returnfalse;

       if (getClass() != obj.getClass())

           returnfalse;

       final ReflectPoint other = (ReflectPoint) obj;

       if (x != other.x)

           returnfalse;

       if (y != other.y)

           returnfalse;

       returntrue;

    }

}


 

注解的应用结构图

注解就相当于一个你的源程序中要调用的一个特殊的类,要在源程序中应用某个注解,得先准备好了这个注解类,即事先定义好一个注解类。就像你要调用每个类,得先有开发好的这个类。

 

定义一个注解类:

packagecn.itcast.day2;

/*

注解类中再加注解,叫元注解,元数据,元信息,表示这个类是专门为注解服务的。

 

@Retention:指示注释类型的注释要保留多久。如果注释类型声明中不存在Retention 注释,则保留策略默认为RetentionPolicy.CLASS(class文件时期)。

@Target:指示注释类型所适用的程序元素的种类。如果注释类型声明中不存在 Target 元注释,则声明的类型可以用在任一程序元素上。如果存在这样的元注释,则编译器强制实施指定的使用限制。例如,此元注释指示该声明类型是其自身,即元注释类型。它只能用在注释类型声明:@Target(ElementType.ANNOTATION_TYPE)

注解存活周期:

源文件时期:当javac把源文件编译成class文件的时候,有可能去掉这个注解

class文件时期:编译器将把注释记录在类文件中,但在运行时 VM 不需要保留注释.当类加载器把class文件调用到内存来的时候也有可能去掉注解

所以我们必须指定自定义注解的存活时期,否则一旦注解被去掉就找不到了

RUNTIME: 编译器将把注释记录在类文件中,在运行时 VM 将保留注释,因此可以反射性地读取。

 

*/

@Retention(RetentionPolicy.RUNTIME)//元注解,指定注解类的存活周期到运行时期

@Target({ElementType.METHOD,ElementType.TYPE})//元注解,标记该注解类可以放在哪个位置上,ElementType.METHOD:函数上面,ElementType.TYPE:类上面

/*

ElementType的枚举常量有:

ANNOTATION_TYPE:注释类型声明

CONSTRUCTOR:构造方法声明

FIELD:字段声明(包括枚举常量)

LOCAL_VARIABLE:局部变量声明

METHOD:方法声明

PACKAGE:包声明

PARAMETER:参数声明

TYPE:类、接口(包括注释类型)或枚举声明

 

*/

public@interfaceItcastAnnotation {

   

}

应用注解并操作注解:

package cn.itcast.day2;

import java.lang.reflect.*;

import javax.jws.soap.InitParam;

@ItcastAnnotation//应用该注解类

public class AnnotationTest {

           publicstaticvoid main(String[] args) throws Exception{

                     if(AnnotationTest.class.isAnnotationPresent(ItcastAnnotation.class)){//判断AnnotationTest类中是否添加了ItcastAnnotation注解

           ItcastAnnotation annotation = (ItcastAnnotation)AnnotationTest.class.getAnnotation(ItcastAnnotation.class);//通过反射得到这个注解类对象,反射操作注解类时,需要在注解类中指定注解类的存活周期,如果没有指定,是默认的保留到类文件时期,则注解类在没有加载进内存运行的时候就消失了,

       }

    }

}


注意一个概念:类文件不是字节码文件,类文件是编译源文件时产生的.class文件。而字节码文件是指类加载器加载类文件到内存中运行的那些才是字节码文件。

@Override注解的周期:源文件时期,在编译的时候就会告诉编译器,如果没有覆盖则编译不通过,一旦编译成功@Override注解就会消失。

@SuppressWarnings注解的周期:源文件时期,在编译的时候会告诉编译器我要用到已过时的方法,你别给我报信息提示,因此编译完成后也会消失。

@Deprecated注解的周期:运行时期,该注解标记方法为已过时,而方法是给别人用的,当加载进内存扫描的时候才能发现有已过时的方法,才能告诉使用者该方法已经过时了

 

为注解增加属性:

package cn.itcast.day2;

import java.lang.annotation.*;

import cn.itcast.day1.EnumTest;

@Retention(RetentionPolicy.RUNTIME)

@Target({ElementType.METHOD,ElementType.TYPE})

public @interfaceItcastAnnotation {

       Stringcolor() default "blue"; //这里表示为注解增加了一个字符串属性,属性值默认为”blue”

       Stringvalue();//增加了value属性,没有设置默认值。

    int[]arrayAttr()default {3,4,4};//增加数组属性,长度为3.

       EnumTest.TrafficLamplamp() defaultEnumTest.TrafficLamp.RED;//增加枚举属性,默认为EnumTest.TrafficLamp.RED

       MetaAnnotationannotationAttr()default @MetaAnnotation("lhm");//注解类型属性,默认值为@MetaAnnotation("lhm")也是一个注解类型。

}

 

package cn.itcast.day2;

public @interface MetaAnnotation {

       Stringvalue(); //没有缺省值,设置值时必须传如一个值

}

 

 

packagecn.itcast.day2;

import java.lang.reflect.Method;

importjavax.jws.soap.InitParam;

@ItcastAnnotation(annotationAttr=@MetaAnnotation("flx"),color="red",value="abc",arrayAttr=1)//分别设置定义的属性值,如果数组中只有一个元素,这时属性值部分可以省略大括号arrayAttr=1

publicclassAnnotationTest {

    @ItcastAnnotation("xyz")//当只有一个属性需要设置时,即其它属性设置了缺省值,则可以这么传递值,这里设置value的值。

    publicstaticvoid main(String[] args) throws Exception{

          

       if(AnnotationTest.class.isAnnotationPresent(ItcastAnnotation.class)){//判断本类是否有ItcastAnnotation注解类注解

           ItcastAnnotation annotation =(ItcastAnnotation)AnnotationTest.class.getAnnotation(ItcastAnnotation.class);//通过反射得到这个注解类对象

           System.out.println(annotation.color());//打印注解类color()属性

           System.out.println(annotation.value());//打印注解类value()属性

           System.out.println(annotation.arrayAttr().length); //打印注解类arrayAttr数组属性长度

           System.out.println(annotation.lamp().nextLamp().name());//GREEN 红灯下一个灯是绿灯

           System.out.println(annotation.annotationAttr().value());//MetaAnnotation的value值是fix

       }

      

       Method mainMethod = AnnotationTest.class.getMethod("main", String[].class);//用反射的方式得到AnnotationTest类中的主函数

       ItcastAnnotation annotation2 = (ItcastAnnotation)mainMethod.getAnnotation(ItcastAnnotation.class);//得到主函数上加的注解对象

       System.out.println(annotation2.value());//@ItcastAnnotation("xyz"),打印xyz

    }

}


 


评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值