Java 8 新特性:扩展注解(类型注解和重复注解)

转载自  Java 8 新特性:扩展注解(类型注解和重复注解)

(注:先回顾下JDK1.5版本出现的注解 ,然后再解释JDK 8的注解 更新内容。)

一.注解(JDK1.5)

1.注解(@):
注解就相当于一种标记,在程序中加了注解就等于为程序加了某种标记。(JDK1.5新特性)。

2.作用:
告诉javac编译器或者java开发工具……向其传递某种信息,作为一个标记。

3.了解注解:
一个注解就是一个类。
标记可以加在包、类、字段、方法,方法参数以及局部变量上。可以同时存在多个注解。
每一个注解结尾都没有“;”或者其他特别符号。

eg:

@SuppressWarnings("deprecation")    //编译器警告过时(source阶段)  
@Deprecated                         //过时(Runtime阶段)  
@Override                               //重写(source阶段)  
@Retention(RetentionPolicy.RUNTIME)   
//保留注解到程序运行时。(Runtime阶段)  
@Target({ElementType.METHOD,ElementType.TYPE})  
//标记既能定义在方法上,又能定义在类、接口、枚举上等。

Note:
1)添加注解需要有注解类。RetentionPolicy是一个枚举类(有三个成员)。
2)Target中可以存放数组。它的默认值为任何元素。
ElementType.METHOD:表示只能标记在方法上。
ElementType.TYPE:表示只能标记定义在类上、接口上、枚举上等。
3)ElementType也是枚举类。成员包括:ANNOTATION_TYPE(注解)、CONSTRUCTOR(构造方法)、FIEID(成员变量)、LOCAL_VARIABLE(变量)、METHOD(方法)、PACKAGE(包)、PARAMETER(参数)、TYPE。


4.注解应用结构图:



5.简单相关知识了解:

元注解:注解的注解(理解:给一个注解类再加注解)
元数据:数据的数据
元信息:信息的信息

6.注解分为三个阶段:

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

Retention的注解有三种取值:(分别对应注解的三个阶段)
RetentionPolicy.SOURCE
RetentionPolicy.CLASS
RetentionPolicy.RUNTIME
Note:注解的默认阶段是Class。

7.注解的属性类型:
原始类型(就是八个基本数据类型)、String类型、Class类型、数组类型、枚举类型、注解类型。

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

eg:@SuppressWarnings("deprecation")


为属性指定缺省值(默认值):
eg:String value() default "blue"; //定义在注解类中
 
数组类型的属性:
eg:int[] arrayArr() default {3,4,5,5};//定义在注解类中
SunAnnotation(arrayArr={3,9,8}) //设置数组值
Note:如果数组属性中只有一个元素时,属性值部分可以省略大括号。
eg:SunAnnotation(arrayArr=9)
 
枚举类型的属性:
eg:EnumDemo.TrafficLamp lamp()
default EnumDemo.TrafficLamp.RED;
//枚举类型属性, 定义在注解类中,这里使用了自定义的枚举类EnumDemo.java并没有给出相关代码,这里只是举个例子

注解类型的属性:
eg:MetaAnnotation annotationAttr()

default @MetaAnnotation("lhm");
//定义在一个注解类中,并指定缺省值,
//此属性关联到注解类:MetaAnnotation.java, 

@SunAnnotation(annotationAttr=@MetaAnnotation("flx"))
//设置注解属性值

9.注解应用示例:

(注:下面只是示例,涉及枚举的类,并没有给出相关代码。)
import java.lang.annotation.ElementType;  
import java.lang.annotation.Retention;  
import java.lang.annotation.RetentionPolicy;  
import java.lang.annotation.Target;  @Retention(RetentionPolicy.RUNTIME)         //元注解:注解的注解。此注解表示使注解保留到运行时。  //Target中可以存放数组。ElementType.METHOD:表示只能标记在方法上。ElementType.TYPE:表示只能标记定义在类上、接口上、枚举上等。  
@Target({ElementType.METHOD,ElementType.TYPE})    public @interface SunAnnotation {  String color() default "blue"; //表示有一个color属性,以方法的形式。设置默认属性值为蓝色  String value();       //是一个特殊的属性,若在设置值时只有一个value属性需要设置 ,那么value可以省略,直接写所设置的值即可。  //数组属性  int[] arrayArr() default {3,4,5,5};  //枚举类型属性,这里使用了自定的枚举类EnumDemo.java  EnumDemo.TrafficLamp lamp() default EnumDemo.TrafficLamp.RED;  //注解类型属性,此时关联到注解类:MetaAnnotation.java,并指定缺省值  MetaAnnotation annotationAttr() default @MetaAnnotation("lhm");  //Class类属性:设置默认值 ReflectDemo.java   类  Class annotationClass() default ReflectDemo.class;  }  
@SunAnnotation(annotationClass=ReflectDemo2.class,annotationAttr=@MetaAnnotation("flx"),color="red",value="abc",arrayArr={1,3,9})       //注解:为注解添加属性值  
//若在设置值时只有一个value属性需要设置 ,那么value可以省略,直接写所设置的值即可。  
public class AnnotationDemo {  /** * @param args */  @SunAnnotation("xyz")  @SuppressWarnings("deprecation")  //注解:告诉编译器或者开发工具……  //若在设置值时只有一个value属性需要设置 ,那么value可以省略,直接写所设置的值即可。  //上面"deprecation"即是省略的value后的值。  public static void main(String[] args)throws Exception {  System.runFinalizersOnExit(true);//中间带横线的部分,说明该方法已经过时了。  //检查某注解是否存在,使用反射;并返回该注解  if(AnnotationDemo.class.isAnnotationPresent(SunAnnotation.class))  {  //获取注解  SunAnnotation annotation=(SunAnnotation)AnnotationDemo.class.getAnnotation(SunAnnotation.class);  //获取属性值  System.out.println("属性color值:"+annotation.color());//调用color属性方法  System.out.println(annotation.value());  System.out.println(annotation.arrayArr().length);//这里输出的是数组长度,不能直接输出数组的每一个值,调用得到的是数组哈希地址值  System.out.println(annotation.lamp().nextLamp().name());//调用注解默认灯的nextLamp方法  annotation.annotationAttr().value();  //获取类类型注解中的 类名称  System.out.println(annotation.annotationClass());  }  }  @Deprecated //表示下面的方法过时了  public static void sayHello()  {  System.out.println("hi");  }  }  

二.扩展注解(JDK 8)

对于注解(也被称做元数据),Java 8 主要有两点改进:类型注解和重复注解。
1.类型注解
1)Java 8 的类型注解扩展了注解使用的范围。
在java 8之前,注解只能是在声明的地方所使用,java8开始,注解可以应用在任何地方。

eg:
创建类实例
new@Interned MyObject();
类型映射
myString = (@NonNull String) str;
implements 语句中
class UnmodifiableList<T> implements@Readonly List<@Readonly T> { ... }
throw exception声明
void monitorTemperature() throws@Critical TemperatureException { ... }

Note:
在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 表示该注解能写在使用类型的任何语句中(eg:声明语句、泛型和强制转换语句中的类型)。

eg:

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

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

eg:

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 注解。
实际上,重复注解不是一个语言上的改变,只是编译器层面的改动,技术层面仍然是一样的。
eg:

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(){    }    
}   

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/329228.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

框架写mysql插入为空_学习springMVC框架配置遇到的问题-数据写入不进数据库时的处理办法...

Idea简单SpringMVC框架配置前边已经介绍过了Struts在Idea上的配置,相对于Struts来说,我觉得SpringMVC有更多的优势,首先Struts是需要对action进行配置,页面发送不同的请求,就需要配置不同的acti ...hibernate学习之一 框架配置hibernate 框架 1.hibernate框架应用在javaee三层结…

“.Net 社区虚拟大会”(dotnetConf) 2016 Day 3 Keynote: Scott Hanselman

美国时间 6月7日--9日&#xff0c;为期三天的微软.NET社区虚拟大会正式在 Channel9 上召开&#xff0c;美国时间6.9 是第三天&#xff0c; Scott Hanselman 做Keynote。今天主题围绕的是.NET OpenSource 展开&#xff0c;Hanselman通过PowerBI分析了.NET社区这两年的发展&#…

Java注释@interface的用法

转载自 Java注释interface的用法java用 interface Annotation{ } 定义一个注解 Annotation&#xff0c;一个注解是一个类 Override&#xff0c;Deprecated&#xff0c;SuppressWarnings为常见的3个注解。注解相当于一种标记&#xff0c;在程序中加上了注解就等于为程序加上了某…

RPC的发展历史

服务器通讯原理就是一台socket服务器A,另一台socket客户端B,现在如果要通讯的话直接以流方式写入或读出。 这样能实现通讯&#xff0c;但有个问题。如何知道更多信息&#xff1f;比如需要发送流大小&#xff0c;编码&#xff0c;Ip等。 这样就有了协议&#xff0c;协议就是规范…

类的继承python 简明_[简明python教程]学习笔记2014-05-04

今天学习的内容&#xff1a;1.面向对象编程的概念1)面向对象的三个基本特征&#xff1a;封装、继承、多态2)类和对象是面向对象编程的2个主要方面。类使用class关键字创建。类的域和方法被列在一个缩进块中。2.类[rootreed 0504]# cat simpleclass.py#!/usr/bin/pythonclass Pe…

子类可以继承到父类上的注解吗

转载自 子类可以继承到父类上的注解吗?不了解注解基础知识的请先看《JDK 5 Annotation\注解\注释\自定义注解》子类可以继承到父类上的注解吗&#xff1f; 我们知道在编写自定义注解时&#xff0c;可以通过指定Inherited注解&#xff0c;指明自定义注解是否可以被继承。但实现…

java aop 实例_Spring aop 简单示例

简单的记录一下spring aop的一个示例基于两种配置方式&#xff1a;基于xml配置基于注解配置这个例子是模拟对数据库的更改操作添加事物其实并没有添加&#xff0c;只是简单的输出了一下记录首先看下整个例子的目录图全部代码就不贴了&#xff0c;数目有点多&#xff0c;不过很简…

用 Visual Studio 和 ASP.NET Core MVC 创建首个 Web API

原文&#xff1a;Building Your First Web API with ASP.NET Core MVC and Visual Studio作者&#xff1a;Mike Wasson 和 Rick Anderson翻译&#xff1a;谢炀(kiler)校对&#xff1a;何镇汐、刘怡(AlexLEWIS) HTTP 协议不仅仅提供网页服务。它也是一个构建公开服务和数据 API …

java抽取pdf_java 抽取 word,pdf 的四种武器

转自:https://www.ibm.com/developerworks/cn/java/l-java-tips/ 感谢作者发布的文章用 jacob其实 jacob 是一个 bridage&#xff0c;连接 java 和 com 或者 win32 函数的一个中间件&#xff0c;jacob 并不能直接抽取 word,excel 等文件&#xff0c;需要自己写 dll 哦&…

SuperSocket与Netty之实现protobuf协议,包括服务端和客户端

今天准备给大家介绍一个c#服务器框架&#xff08;SuperSocket&#xff09;和一个c#客户端框架&#xff08;SuperSocket.ClientEngine&#xff09;。这两个框架的作者是园区里面的江大渔。 首先感谢他的无私开源贡献。之所以要写这个文章是因为群里经常有人问这个客户端框架要如…

Java 注解指导手册 – 终极向导

转载自 Java 注解指导手册 – 终极向导译文出处&#xff1a; Toien Liu 原文出处&#xff1a;Dani Buiza编者的话&#xff1a;注解是java的一个主要特性且每个java开发者都应该知道如何使用它。我们已经在Java Code Geeks提供了丰富的教程, 如Creating Your Own Java Annota…

ajax调用后台java类_ajax调用java后台方法是什么

ajax是一种基于 JavaScript和HTTP请求(HTTP requests)&#xff0c;广泛应用在浏览器的网页开发技术。那么&#xff0c;ajax调用java后台方法是什么?var http_requestfalse;function sendRequest(method,url,content,processResponse){http_requestfalse;if(window.XMLHttpRequ…

用 Visual Studio 发布一个 Azure 云 Web 应用程序

原文&#xff1a;Getting Started 作者&#xff1a;Rick Anderson 翻译&#xff1a;谢炀(Kiler) 校对&#xff1a;孟帅洋(书缘)、刘怡(AlexLEWIS)、何镇汐 设置开发环境 安装最新版本的 Azure SDK for Visual Studio 2015。如果你之前没有装过 Visual Studio 2015&#xff0c;S…

Java中的注解是如何工作的

转载自 Java中的注解是如何工作的&#xff1f;自Java5.0版本引入注解之后&#xff0c;它就成为了Java平台中非常重要的一部分。开发过程中&#xff0c;我们也时常在应用代码中会看到诸如Override&#xff0c;Deprecated这样的注解。这篇文章中&#xff0c;我将向大家讲述到底什…

impdp导入mysql_Oracle数据库的impdp导入操作以及dba_directories使用方法

Oracle数据库的impdp导入操作以及dba_directories使用方法今天从同事那里拿到了导出的dmp文件&#xff0c;当导入时发现了很多问题&#xff0c;记下来以免以后忘记&#xff0c;以下是本人的操作过程&#xff1a;1.首先是创建一个文件夹dump&#xff0c;用来存放dmp文件&#xf…

ASP.NET Core MVC 与 Visual Studio 入门

原文&#xff1a;Getting started with ASP.NET Core MVC and Visual Studio作者&#xff1a;Rick Anderson翻译&#xff1a;娄宇(Lyrics)校对&#xff1a;刘怡(AlexLEWIS)、夏申斌 、张硕(Apple) 这篇教程将告诉你如何使用 Visual Studio 2015 构建一个 ASP.NET Core MVC Web …

深入理解Java:注解(Annotation)自定义注解入门

转载自 深入理解Java&#xff1a;注解&#xff08;Annotation&#xff09;自定义注解入门要深入学习注解&#xff0c;我们就必须能定义自己的注解&#xff0c;并使用注解&#xff0c;在定义自己的注解之前&#xff0c;我们就必须要了解Java为我们提供的元注解和相关定义注解的语…

java快排原理_Java数据结构与算法——快速排序

声明&#xff1a;码字不易&#xff0c;转载请注明出处&#xff0c;欢迎文章下方讨论交流。前言&#xff1a;Java数据结构与算法专题会不定时更新&#xff0c;欢迎各位读者监督。本篇文章介绍排序算法中最常用也是面试中最容易考到的排序算法——快排&#xff0c;包括快排的思想…

厚积薄发,拥抱 .NET 2016

厚积薄发这个词是高三英语老师在高考前写在黑板上&#xff0c;高中三年努力这么久&#xff0c;是时候迎面而上&#xff0c;冲刺向前。所以&#xff0c;一想到.NET 2016&#xff0c;脑海里蹦出的第一个词就是它。 .NET 2016 是 .NET 一次质的飞跃&#xff0c;不管难易&#xff0…

CGLIB 实现代理对象API

转载自 CGLIB 实现代理对象API1. 加入库cglib库cglib-2.2.jarasm库(cglib 需要asm库,如果没有加入asm的jar文件,就会报asm错误)asm-3.1.jar 2. 定义CGLIB操作类package com.machome.cglibtest;import java.lang.reflect.Method;import com.machome.model.StuService;import net…