基本注解

Java 从Java 5开始支持注解。

了解了注解的概念以及作用以后,我们来学习一下Java提供的5个基本注解,这5个最基本的注解是:

  1. @Override
  2. @Deprecated
  3. @SuppressWarnings
  4. @SafeVarargs
  5. @FunctionalInterface

注意:使用注解时要在注解前加@符号。使用注解很简单,只需要把注解当成一个修饰符来修饰它支持的程序元素即可。

@Override

@Override注解用来指定子类必须重写父类方法。也就是说如果一个方法被@Override注解所修饰,那么改方法必须是重写了父类的方法,否则编译报错。

 

示例代码

 

 

  1. 声明Fu.java

public class Fu {

     public void eat() {}

}

  1. 声明Zi.java,继承Fu

public class Zi extends Fu {

     @Override

     public void eat() {}//只要不符合方法重写的规则就编译报错}

}

@Override注解主要是用来帮助开发者避免一些低级错误,例如在子类重写父类方法时候不小心将子类的方法名称给写错误。就像这样,本来想写的是execute()结果却写成了executer();这个时候就成了子类独有的方法,而不是子类重写父类的方法。

@Deprecated

@Deprecated注解用于指示程序元素(类,方法等)已过时。

 

示例代码

 

public class Zi extends Fu {

       @Deprecated

       @Override

       public void eat() {}//可以看出来一个程序元素可以被多个注解修饰

}

@SuppressWarnings

@SuppressWarnings注解用于取消编译器提示的警告信息。@SuppressWarnings会一直作用于该程序元素的所有子元素。例如使用@SuppressWarnings修饰某个类取消编译器的某个警告,同时又使用@SuppressWarnings修饰类中的某个方法取消编译器的另一个警告,那么该方法将会同时取消编译器的这两个警告。

 

抑制单一类型警告

编译器的警告信息有多种多样,在抑制单一类型警告这种情况中@SuppressWarnings只负责抑制一种类型的警告信息。

 

示例代码

 

@SuppressWarnings(value = "unchecked")

public static void main(String[] args) {

    @SuppressWarnings(value = "rawtypes")

    // 没有泛型的集合,编译器会给出警告信息,rawtypes用于取消编译给出new Arraylist()警告

    List list = new ArrayList();

    //没有泛型的集合添加元素,可能会引发unchecked异常,所以编译器会给出警告信息,unchecked用于取消添加元素时的警告信息

    list.add(new Object());

}

抑制多种类型警告

为了方便起见,也可以让一个@SuppressWarnings注解抑制多种类型的警告信息。

 

示例代码

 

@SuppressWarnings(value = { "rawtypes", "unchecked" })

// 使用一个@SuppressWarnings注解抑制多种警告信息

public static void main(String[] args) {

    List list = new ArrayList();

    list.add(new Object());

}

 

抑制所有类型警告

顾名思义,就是让一个@SuppressWarnings注解抑制所有的类型的警告信息

 

示例代码

 

@SuppressWarnings(value = "all")

public static void main(String[] args) {

    List list = new ArrayList();

    list.add(new Object());

}

@SuppressWarnings的参数值

@SuppressWarnings注解定义在java.lang.SuppressWarnings中,用来抑制编译时的警告信息。使用它的时候需要添加一个参数,这些参数值都是已经定义好了的。具体看下表

参数名称

说明

Deprecation

使用了过时的类或者方法的警告

Unchecked

执行了未检查的转换的警告,例如使用集合时候未指定泛型

fallthrough

switch语句中发生case穿透编译警告

Path

在类路径,源文件路径等中有不存在路径的编译警告

Serial

可序列化的类中缺少serialVersionUID定义的警告

Finally

任何finally子句不能完成时警告

All

关于以上所有的警告

 

@SafeVarargs

在Java中,将一个不带泛型的对象赋值给一个带泛型的变量,这种情况称之为”堆污染(heap pollution)”。发生”堆污染”以后,代码并不是固定的运行出错,也不是固定的运行正常,而是根据实际情况来定的。

 

“堆污染”示例

示例代码一:

 

    public static void main(String[] args) {

        List listA = new ArrayList<String>();

        listA.add("小钻风");

        List<Integer> listB = new ArrayList<>();

        // "堆污染"代码,编译运行不报错

        listB = listA;

        // 运行报错,类转换异常

        Integer integer = listB.get(0);

        System.out.println(integer);

    }

分析 如果将ListB的泛型定义成String类型,那么运行的时候就不会报错。所以发生“堆污染”以后,代发是否运行报错是根据实际情况而定的。

@SafeVarargs示例

注解@SafeVarargs就是用来取消编译器的堆污染警告信息。

 

示例代码二

Java不支持泛型数组,所以对于参数可变的方法,该方法的形式参数又带泛型,将更容易导致“堆污染”。因为Java在运行的时候会擦除泛型,因此程序在运行的时候会把List<Integer>…当成List[]处理,这就是发生“堆污染”的原因。

 

    @SuppressWarnings(value = {"rawtypes", "unused" })

    @SafeVarargs //取消堆污染警告信息

    public static void addList(List<Integer>... lists) {

        // java不支持泛型数组,这里已经发生堆污染

        List[] listArray = lists;

        List<String> aLists = new ArrayList<>();

        listArray[0] = aLists;

        aLists.add("小钻风");

        //运行报错,将lists泛型修改成String,那么运行就又不报错了(修改以后记得用String接受哦)

        Integer xiaozuanfeng = lists[0].get(0);

    }

 

解析:取消编译器的堆污染警告信息并不意味着运行代码固定正常,它仅仅是取消编译器的警告信息而已。要始终记住,注解,只是一种符号,它帮助开发者在不改变原有逻辑的情况下进行补充,嵌入一些信息等操作。注解的删除,增加并不会影响代码的执行。

 

泛型数组

Java虽然不支持泛型数组,但是却可以声明变量是泛型数组类型,这样就可以将运行时期的错误提前到编译期间,保证代码运行正常。这也正是泛型的好处之一。

 

    @SafeVarargs //取消堆污染编译警告信息

    public static void addList(List<Integer>... lists) {

 

              //java中不支持泛型数组,创建这种对象会报错

              //new ArrayList<Integer>[10];

 

        //跟上次相比,这次的变量类型是泛型数组,那么在编译期间就可以检查元素类型

        List<Integer>[] listArray = lists;

        List<String> aLists = new ArrayList<>();

        //编译报错,避免运行时错误

        //listArray[0] = aLists;

        aLists.add("小钻风");

        Integer xiaozuanfeng = lists[0].get(0);

    }

小结

通过以上三个示例代码,可以总结出来,发生”堆污染”的代码运行时是否异常,要根据实际情况而定。基于这种情况,Java 7在定义方法的时候就发出”堆污染”警告,让开发者更早地注意到程序中可能存在的漏洞。当开发者不希望看到这个警告的时候,有如下三种解决方案

  1. 使用@SafeVarargs注解修饰引发堆污染警告的方法或构造器
  2. 使用@SuppressWarnings(“unchecked”)修饰
  3. 在编译时使用-Xlint:varargs选项

很显然,第三种方式是很少使用,通常选择第一种或者第二种方式。尤其第一种方式,它是Java 7专门为抑制堆污染警告提供的。

@FunctionalInterface

该注解的功能很简单,它用来指示某个接口必须是函数式接口。所以该注解只能修饰接口,不能修饰其它程序元素。

函数式接口就是为Java 8的Lambda表达式准备的,Java 8允许使用Lambda表达式创建函数式接口的实例,因此Java 8专门增加了@FunctionalInterface注解。

 

示例代码

 

@FunctionalInterface

public interface FunctionalInterfaceTest {

    /*

     * 只要接口中的抽象方法数量不是一,则编译报错

     * 所以放开test2()或者注释掉test()都会编译报错

     * 所以该注解就是用来帮助开发者避免一些低级错误

     */

    public abstract void test();

//  public abstract void test2();

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

测试的自我修养

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值