为了账号安全,请及时绑定邮箱和手机立即绑定

【女神推荐】入门新手秘籍之java注解(一)

标签:

图片描述

java注解(Annotation)

标签(空格分隔):java 注解


什么是java注解?
  • Annotation(注解)就是Java提供了一种元程序中的元素关联任何信息和着任何元数据(metadata)的途径和方法。Annotion(注解)是一个接口,程序可以通过反射来获取指定程序元素的Annotion对象,然后通过Annotion对象来获取注解里面的元数据。
什么是元数据?

元数据从metadata一词译来,就是“关于数据的数据”的意思。
元数据的功能作用有很多,比如:你可能用过Javadoc的注释自动生成文档。这就是元数据功能的一种。总的来说,元数据可以用来创建文档,跟踪代码的依赖性,执行编译时格式检查,代替已有的配置文件。如果要对于元数据的作用进行分类,目前还没有明确的定义,不过我们可以根据它所起的作用,大致可分为三类:

  • 1.编写文档:通过代码里标识的元数据生成文档
  • 2.代码分析:通过代码里标识的元数据对代码进行分析
  • 3.编译检查:通过代码里标识的元数据让编译器能实现基本的编译检查
      在Java中元数据以标签的形式存在于Java代码中,元数据标签的存在并不影响程序代码的编译和执行,它只是被用来生成其它的文件或针在运行时知道被运行代码的描述信息。

    综上所述:

  • 1.元数据以标签的形式存在于Java代码中。
  • 2.元数据描述的信息是类型安全的,即元数据内部的字段都是有明确类型的。
  • 3.元数据需要编译器之外的工具额外的处理用来生成其它的程序部件。
  • 4.元数据可以只存在于Java源代码级别,也可以存在于编译之后的Class文件内部。
注解原理
  • Annotation其实是一种接口。通过Java的反射机制相关的API来访问annotation信息。相关类(框架或工具中的类)根据这些信息来决定如何使用该程序元素或改变它们的行为。
  • annotation是不会影响程序代码的执行,无论annotation怎么变化,代码都始终如一地执行。
  • Java语言解释器在工作时会忽略这些annotation,因此在JVM 中这些annotation是“不起作用”的,只能通过配套的工具才能对这些annontaion类型的信息进行访问和处理。
  • java.lang.annotation中包含所有定义自定义注解所需用到的原注解和接口。如接口 java.lang.annotation.Annotation 是所有注解继承的接口,并且是自动继承,不需要定义时指定,类似于所有类都自动继承Object。该包同时定义了四个元注解,Documented,Inherited,Target(作用范围,方法,属性,构造方法等),Retention(生命范围,源代码,class,runtime)。 Annotationinterface的异同:
  • 1.Annotation类型使用关键字@interface而不是interface。这个关键字声明隐含了一个信息:它是继承了java.lang.annotation.Annotation接口,并非声明了一个interface;
  • 2.Annotation类型、方法定义是独特的、受限制的。
      Annotation类型的方法必须声明为无参数、无异常抛出的。这些方法定义了annotation的成员:方法名成为了成员名,而方法返回值成为了成员的类型。而方法返回值类型必须为primitive类型、Class类型、枚举类型、annotation类型或者由前面类型之一作为元素的一维数组。方法的后面可以使用 default和一个默认数值来声明成员的默认值,null不能作为成员默认值,这与我们在非annotation类型中定义方法有很大不同。
      Annotation类型和它的方法不能使用annotation类型的参数、成员不能是generic。只有返回值类型是Class的方法可以在annotation类型中使用generic,因为此方法能够用类转换将各种类型转换为Class
  • 3.Annotation类型又与接口有着近似之处。
      它们可以定义常量、静态成员类型(比如枚举类型定义)。Annotation类型也可以如接口一般被实现或者继承。
应用场合
  • 生成文档。这是最常见的,也是java最早提供的注解。常用的有@see@param@return 等;
  • 跟踪代码依赖性,实现替代配置文件功能。比较常见的spring2.5开始的基于注解配置。作用就是减少配置。现在的框架基本都使用了这种配置来减少配置文件的数量;
  • 在编译时进行格式检查。如@override放在方法前,如果你这个方法并不是覆盖了超类方法,则编译时就能检查出。
注解分类

根据注解参数的个数,我们可以将注解分为三类:

  • 1.标记注解:一个没有成员定义的Annotation类型被称为标记注解。这种Annotation类型仅使用自身的存在与否来为我们提供信息。比如系统注解@Override;
  • 2.单值注解
  • 3.完整注解  

根据注解使用方法和用途,我们可以将Annotation分为三类:

  • 1.JDK内置系统注解
  • 2.元注解
  • 3.自定义注解(第三方提供和自己定义)

JDK内置注解

JavaSE中内置三个标准注解,定义在java.lang中:

  • @Override:用于修饰此方法覆盖了父类的方法;
  • @Deprecated:用于修饰已经过时的方法;
  • @SuppressWarnnings:用于通知java编译器禁止特定的编译警告。

@Override是一个标记注解类型,它被用作标注方法,不能用于其他程序。

它说明了被标注的方法重载了父类的方法,起到了断言的作用。如果我们使用了这种Annotation在一个没有覆盖父类方法的方法时,java编译器将以一个编译错误来警示。这个annotaton常常在我们试图覆盖父类方法而确又写错了方法名时发挥威力。使用方法极其简单:在使用此annotation时只要在被修饰的方法前面加上@Override即可。下面的代码是一个使用@Override修饰一个企图重载父类的displayName()方法,而又存在拼写错误的实例:

public class Fruit {

    public void displayName(){
        System.out.println("水果的名字是:*****");
    }
}

//编译没有问题
class Orange extends Fruit {
    @Override
    public void displayName(){
        System.out.println("水果的名字是:桔子");
    }
}

//编译出错
class Apple extends Fruit {
    @Override
    public void displayname(){
        System.out.println("水果的名字是:苹果");
    }
}

@Deprecated,标记已过时:

  同样Deprecated也是一个标记注解。当一个类型或者类型成员使用@Deprecated修饰的话,编译器将不鼓励使用这个被标注的程序元素。而且这种修饰具有一定的 “延续性”:如果我们在代码中通过继承或者覆盖的方式使用了这个过时的类型或者成员,虽然继承或者覆盖后的类型或者成员并不是被声明为 @Deprecated,但编译器仍然要报警。
  值得注意,@Deprecated这个annotation类型和javadoc中的 @deprecated这个tag是有区别的:前者是java编译器识别的,而后者是被javadoc工具所识别用来生成文档(包含程序成员为什么已经过 时、它应当如何被禁止或者替代的描述)。
  在java5.0java编译器仍然象其从前版本那样寻找@deprecated这个javadoc tag,并使用它们产生警告信息。但是这种状况将在后续版本中改变,我们应在现在就开始使用@Deprecated来修饰过时的方法而不是 @deprecated javadoc tag
  下面一段程序中使用了@Deprecated注解标示方法过期,同时在方法注释中用@deprecated tag 标示该方法已经过时,代码如下:

class AppleService {
    public void displayName(){
        System.out.println("水果的名字是:苹果");
    }

    /**
     * @deprecated 该方法已经过期,不推荐使用
     */
    @Deprecated
    public void showTaste(){
        System.out.println("水果的苹果的口感是:脆甜");
    }

    public void showTaste(int typeId){
        if(typeId==1){
            System.out.println("水果的苹果的口感是:酸涩");
        }
        else if(typeId==2){
            System.out.println("水果的苹果的口感是:绵甜");
        }
        else{
            System.out.println("水果的苹果的口感是:脆甜");
        }
    }
}

public class FruitRun {

    /**
     * @param args
     */
    public static void main(String[] args) {
        Apple apple=new Apple();
        apple.displayName();    
       /*在FruitRun类中使用的时候,编译器会给出该方法已过期,不推荐使用的提示 */
        AppleService appleService=new AppleService();
        appleService.showTaste();
        appleService.showTaste(0);
        appleService.showTaste(2);
    }

}

SuppressWarnnings,抑制编译器警告:

  @SuppressWarnings被用于有选择的关闭编译器对类、方法、成员变量、变量初始化的警告。在java5.0sun提供的javac编译器为我们提供了-Xlint选项来使编译器对合法的程序代码提出警告,此种警告从某种程度上代表了程序错误。例如当我们使用一个genericcollection类而又没有提供它的类型时,编译器将提示出"unchecked warning"的警告。通常当这种情况发生时,我们就需要查找引起警告的代码。如果它真的表示错误,我们就需要纠正它。例如如果警告信息表明我们代码中的switch语句没有覆盖所有可能的case,那么我们就应增加一个默认的case来避免这种警告。
  有时我们无法避免这种警告,例如,我们使用必须和非generic的旧代码交互的generic collection类时,我们不能避免这个unchecked warning。此时@SuppressWarning就要派上用场了,在调用的方法前增加@SuppressWarnings修饰,告诉编译器停止对此方法的警告。
  SuppressWarning不是一个标记注解。它有一个类型为String[]的成员,这个成员的值为被禁止的警告名。对于javac编译器来讲,被-Xlint选项有效的警告 名也同样对@SuppressWarings有效,同时编译器忽略掉无法识别的警告名。
  annotation语法允许在annotation名后跟括号,括号中是使用逗号分割的name=value对用于为annotation的成员赋值。实例如下:

public class FruitService {

    @SuppressWarnings(value={ "rawtypes", "unchecked" })
    public static  List<Fruit> getFruitList(){
        List<Fruit> fruitList=new ArrayList();
        return fruitList;
    }

    @SuppressWarnings({ "rawtypes", "unchecked" })
    public static  List<Fruit> getFruit(){
        List<Fruit> fruitList=new ArrayList();
        return fruitList;
    }

    @SuppressWarnings("unused")
    public static void main(String[] args){
        List<String> strList=new ArrayList<String>();
    }
}

在这个例子中SuppressWarnings annotation类型只定义了一个单一的成员,所以只有一个简单的value={...}作为name=value对。又由于成员值是一个数组,故使用大括号来声明数组值。注意:我们可以在下面的情况中缩写annotation

  • annotation只有单一成员,并成员命名为"value="。这时可以省去"value="。比如将上面方法getFruit()SuppressWarnings annotation就是缩写的。

SuppressWarnings注解的常见参数值的简单说明:

  • 1.deprecation:使用了不赞成使用的类或方法时的警告;
  • 2.unchecked:执行了未检查的转换时的警告,例如当使用集合时没有用泛型 (Generics) 来指定集合保存的类型;
  • 3.fallthrough:当 Switch程序块直接通往下一种情况而没有 Break 时的警告;
  • 4.path:在类路径、源文件路径等中有不存在的路径时的警告;
  • 5.serial:当在可序列化的类上缺少 serialVersionUID 定义时的警告;
  • 6.finally:任何 finally子句不能正常完成时的警告;
  • 7.all:关于以上所有情况的警告。
点击查看更多内容
17人点赞

若觉得本文不错,就分享一下吧!

评论

作者其他优质文章

正在加载中
感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦
今天注册有机会得

100积分直接送

付费专栏免费学

大额优惠券免费领

立即参与 放弃机会
意见反馈 帮助中心 APP下载
官方微信

举报

0/150
提交
取消