【Java8新特性】重复注解与类型注解,你真的学会了吗?

  • RetentionPolicy.RUNTIME

注意:注解的默认阶段是Class。

6.注解的属性类型

原始类型(就是八个基本数据类型)、String类型、Class类型、数组类型、枚举类型、注解类型。

7.为注解增加属性

value:是一个特殊的属性,若在设置值时只有一个value属性需要设置或者其他属性都采用默认值时 ,那么value=可以省略,直接写所设置的值即可。

例如:@SuppressWarnings(“deprecation”)

为属性指定缺省值(默认值):

例如:String value() default “blue”; //定义在注解类中

数组类型的属性:

例如:int[] arrayArr() default {3,4,5,5};//定义在注解类中

SunAnnotation(arrayArr={3,9,8}) //设置数组值

注意:如果数组属性中只有一个元素时,属性值部分可以省略大括号。

例如:SunAnnotation(arrayArr=9)

枚举类型的属性:

例如:EnumDemo.TrafficLamp lamp()

枚举类型属性, 定义在注解类中,这里使用了自定义的枚举类EnumDemo.java并没有给出相关代码,这里只是举个例子

default EnumDemo.TrafficLamp.RED;

注解类型的属性:

例如:MetaAnnotation annotationAttr()

//定义在一个注解类中,并指定缺省值,

//此属性关联到注解类:MetaAnnotation.java,

default @MetaAnnotation(“lhm”);

//设置注解属性值

@SunAnnotation(annotationAttr=@MetaAnnotation(“flx”))

Java8中的注解


对于注解(也被称做元数据),Java 8 主要有两点改进:类型注解和重复注解。

1.类型注解

1)Java 8 的类型注解扩展了注解使用的范围。

在java 8之前,注解只能是在声明的地方所使用,java8开始,注解可以应用在任何地方。

例如:

创建类实例

new @Interned MyObject();

类型映射

myString = (@NonNull String) str;

implements 语句中

class UnmodifiableList implements@Readonly List<@Readonly T> { … }

throw exception声明

void monitorTemperature() throws@Critical TemperatureException { … }

注意:

在Java 8里面,当类型转化甚至分配新对象的时候,都可以在声明变量或者参数的时候使用注解。

Java注解可以支持任意类型。

类型注解只是语法而不是语义,并不会影响java的编译时间,加载时间,以及运行时间,也就是说,编译成class文件的时候并不包含类型注解。

2)新增ElementType.TYPE_USE 和ElementType.TYPE_PARAMETER(在Target上)

新增的两个注释的程序元素类型 ElementType.TYPE_USE 和 ElementType.TYPE_PARAMETER用来描述注解的新场合。

  • ElementType.TYPE_PARAMETER 表示该注解能写在类型变量的声明语句中。

  • ElementType.TYPE_USE 表示该注解能写在使用类型的任何语句中(例如:声明语句、泛型和强制转换语句中的类型)。

例如,下面的示例。

@Target({ElementType.TYPE_PARAMETER, ElementType.TYPE_USE})

@interface MyAnnotation {}

3)类型注解的作用

类型注解被用来支持在Java的程序中做强类型检查。配合第三方插件工具Checker Framework(注:此插件so easy,这里不介绍了),可以在编译的时候检测出runtime error(例如:UnsupportedOperationException; NumberFormatException;NullPointerException异常等都是runtime error),以提高代码质量。这就是类型注解的作用。

注意:使用Checker Framework可以找到类型注解出现的地方并检查。

例如下面的代码。

import checkers.nullness.quals.*;

public class TestDemo{

void sample() {

@NonNull Object my = new Object();

}

}

使用javac编译上面的类:(当然若下载了Checker Framework插件就不需要这么麻烦了)

javac -processor checkers.nullness.NullnessChecker TestDemo.java

上面编译是通过的,但若修改代码:

@NonNull Object my = null;

但若不想使用类型注解检测出来错误,则不需要processor,正常javac TestDemo.java是可以通过编译的,但是运行时会报 NullPointerException 异常。

为了能在编译期间就自动检查出这类异常,可以通过类型注解结合 Checker Framework 提前排查出来错误异常。

注意java 5,6,7版本是不支持注解@NonNull,但checker framework 有个向下兼容的解决方案,就是将类型注解@NonNull 用/**/注释起来。

import checkers.nullness.quals.*;

public class TestDemo{

void sample() {

/@NonNull/ Object my = null;

}

}

这样javac编译器就会忽略掉注释块,但用checker framework里面的javac编译器同样能够检测出@NonNull错误。

通过 类型注解 + checker framework 可以在编译时就找到runtime error。

2.重复注解

允许在同一声明类型(类,属性,或方法)上多次使用同一个注解。

Java8以前的版本使用注解有一个限制是相同的注解在同一位置只能使用一次,不能使用多次。

Java 8 引入了重复注解机制,这样相同的注解可以在同一地方使用多次。重复注解机制本身必须用 @Repeatable 注解。

实际上,重复注解不是一个语言上的改变,只是编译器层面的改动,技术层面仍然是一样的。

例如,我们可以使用如下示例来具体对比Java8之前的版本和Java8中的注解。

**1)**自定义一个包装类Hints注解用来放置一组具体的Hint注解

@interface MyHints {

Hint[] value();

}

@Repeatable(MyHints.class)

@interface Hint {

String value();

}

使用包装类当容器来存多个注解(旧版本方法)

@MyHints({@Hint(“hint1”), @Hint(“hint2”)})

class Person {}

使用多重注解(新方法)

@Hint(“hint1”)

@Hint(“hint2”)

class Person {}

**2)**完整类测试如下所示。

public class RepeatingAnnotations {

@Target(ElementType.TYPE)

@Retention(RetentionPolicy.RUNTIME)

public @interface Filters {

Filter[] value();

}

@Target(ElementType.TYPE)

@Retention(RetentionPolicy.RUNTIME)

@Repeatable(Filters.class)

public @interface Filter {

String value();

}

@Filter(“filter1”)

@Filter(“filter2”)

public interface Filterable {

}

public static void main(String[] args) {

for (Filter filter : Filterable.class.getAnnotationsByType(Filter.class)) {

System.out.println(filter.value());

}

}

}

输出结果:

filter1

filter2

分析:

注释Filter被@Repeatable( Filters.class )注释。Filters 只是一个容器,它持有Filter, 编译器尽力向程序员隐藏它的存在。通过这样的方式,Filterable接口可以被Filter注释两次。

另外,反射的API提供一个新方法getAnnotationsByType() 来返回重复注释的类型(注意Filterable.class.getAnnotation( Filters.class )将会返回编译器注入的Filters实例。

**3)**java 8之前也有重复使用注解的解决方案,但可读性不好。

public @interface MyAnnotation {

String role();

}

public @interface Annotations {

MyAnnotation[] value();

}

public class RepeatAnnotationUseOldVersion {

@Annotations({@MyAnnotation(role=“Admin”),@MyAnnotation(role=“Manager”)})

public void doSomeThing(){

}

}

Java8的实现方式(由另一个注解来存储重复注解,在使用时候,用存储注解Authorities来扩展重复注解),可读性更强。

@Repeatable(Annotations.class)

public @interface MyAnnotation {

String role();

}

public @interface Annotations {

MyAnnotation[] value();

}

public class RepeatAnnotationUseOldVersion {

@MyAnnotation(role=“Admin”)

@MyAnnotation(role=“Manager”)

public void doSomeThing(){

}

}

什么?没看懂?那就再来一波!!!

Java8对注解的增强


Java 8对注解处理提供了两点改进:可重复的注解及可用于类型的注解。总体来说,比较简单,下面,我们就以实例的形式来说明Java8中的重复注解和类型注解。

首先,我们来定义一个注解类BingheAnnotation,如下所示。

package io.mykit.binghe.java8.annotition;

import java.lang.annotation.*;

/**

  • @author binghe

  • @version 1.0.0

  • @description 定义注解

*/

@Repeatable(BingheAnnotations.class)

@Target({ElementType.TYPE, ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER, ElementType.CONSTRUCTOR, ElementType.LOCAL_VARIABLE,ElementType.TYPE_PARAMETER})

@Retention(RetentionPolicy.RUNTIME)

public @interface BingheAnnotation {

String value();

}

注意:在BingheAnnotation注解类上比普通的注解多了一个@Repeatable(BingheAnnotations.class)注解,有小伙伴会问:这个是啥啊?这个就是Java8中定义可重复注解的关键,至于BingheAnnotations.class,大家别急,继续往下看就明白了。

接下来,咱们定义一个BingheAnnotations注解类,如下所示。

package io.mykit.binghe.java8.annotation;

import java.lang.annotation.*;

/**

  • @author binghe

  • @version 1.0.0

  • @description 定义注解

*/

@Target({ElementType.TYPE, ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER, ElementType.CONSTRUCTOR, ElementType.LOCAL_VARIABLE,ElementType.TYPE_PARAMETER})

@Retention(RetentionPolicy.RUNTIME)

public @interface BingheAnnotations {

BingheAnnotation[] value();

}

最后

无论是哪家公司,都很重视基础,大厂更加重视技术的深度和广度,面试是一个双向选择的过程,不要抱着畏惧的心态去面试,不利于自己的发挥。同时看中的应该不止薪资,还要看你是不是真的喜欢这家公司,是不是能真的得到锻炼。

针对以上面试技术点,我在这里也做一些分享,希望能更好的帮助到大家。

otation.*;

/**

  • @author binghe

  • @version 1.0.0

  • @description 定义注解

*/

@Target({ElementType.TYPE, ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER, ElementType.CONSTRUCTOR, ElementType.LOCAL_VARIABLE,ElementType.TYPE_PARAMETER})

@Retention(RetentionPolicy.RUNTIME)

public @interface BingheAnnotations {

BingheAnnotation[] value();

}

最后

无论是哪家公司,都很重视基础,大厂更加重视技术的深度和广度,面试是一个双向选择的过程,不要抱着畏惧的心态去面试,不利于自己的发挥。同时看中的应该不止薪资,还要看你是不是真的喜欢这家公司,是不是能真的得到锻炼。

针对以上面试技术点,我在这里也做一些分享,希望能更好的帮助到大家。

[外链图片转存中…(img-oqZ2TLv5-1721161232927)]

[外链图片转存中…(img-Y3fdysDj-1721161232928)]

[外链图片转存中…(img-YwuXlzq7-1721161232929)]

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值