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

5.注解分为三个阶段

java源文件–> class文件 --> 内存中的字节码。

Retention的注解有三种取值:(分别对应注解的三个阶段)

  • RetentionPolicy.SOURCE

  • RetentionPolicy.CLASS

  • 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,大家别急,继续往下看就明白了。

自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数Java工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年Java开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Java开发知识点,真正体系化!

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!

如果你觉得这些内容对你有帮助,可以扫码获取!!(备注Java获取)

img

复习的面试资料

这些面试全部出自大厂面试真题和面试合集当中,小编已经为大家整理完毕(PDF版)

  • 第一部分:Java基础-中级-高级

image

  • 第二部分:开源框架(SSM:Spring+SpringMVC+MyBatis)

image

  • 第三部分:性能调优(JVM+MySQL+Tomcat)

image

  • 第四部分:分布式(限流:ZK+Nginx;缓存:Redis+MongoDB+Memcached;通讯:MQ+kafka)

image

  • 第五部分:微服务(SpringBoot+SpringCloud+Dubbo)

image

  • 第六部分:其他:并发编程+设计模式+数据结构与算法+网络

image

进阶学习笔记pdf

  • Java架构进阶之架构筑基篇(Java基础+并发编程+JVM+MySQL+Tomcat+网络+数据结构与算法

image

  • Java架构进阶之开源框架篇(设计模式+Spring+SpringMVC+MyBatis

image

image

image

  • Java架构进阶之分布式架构篇 (限流(ZK/Nginx)+缓存(Redis/MongoDB/Memcached)+通讯(MQ/kafka)

image

image

image

  • Java架构进阶之微服务架构篇(RPC+SpringBoot+SpringCloud+Dubbo+K8s)

image

image

《互联网大厂面试真题解析、进阶开发核心学习笔记、全套讲解视频、实战项目源码讲义》点击传送门即可获取!
中…(img-WQW0gCnt-1713525137564)]

  • Java架构进阶之开源框架篇(设计模式+Spring+SpringMVC+MyBatis

[外链图片转存中…(img-lmvR0IWG-1713525137566)]

[外链图片转存中…(img-39jCww5Z-1713525137568)]

[外链图片转存中…(img-EYBzGHqu-1713525137569)]

  • Java架构进阶之分布式架构篇 (限流(ZK/Nginx)+缓存(Redis/MongoDB/Memcached)+通讯(MQ/kafka)

[外链图片转存中…(img-FGESA5Ju-1713525137571)]

[外链图片转存中…(img-u4V9jcdQ-1713525137572)]

[外链图片转存中…(img-dUVjzOTZ-1713525137573)]

  • Java架构进阶之微服务架构篇(RPC+SpringBoot+SpringCloud+Dubbo+K8s)

[外链图片转存中…(img-q9FCtRA2-1713525137575)]

[外链图片转存中…(img-YBO5zdyU-1713525137576)]

《互联网大厂面试真题解析、进阶开发核心学习笔记、全套讲解视频、实战项目源码讲义》点击传送门即可获取!

  • 21
    点赞
  • 30
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值