【框架基础】:全面解析Java注解(一)
来源:互联网 发布:ubuntu复制到命令行 编辑:程序博客网 时间:2024/05/02 02:50
Java注解概述
要了解Java注解要先知道Java的反射,反射是运行时获取类的成员,注解也是类的成员,以此达到动态编码的效
果,多用在框架,或者使用框架时候添加注解让框架调用。
注解定义:注解(Annotation),也叫元数据。Java提供了一种原程序中的元素关联任何信息和任何元数据的途
径和方法,一种代码级别的说明。它是JDK1.5及以后版本引入的一个特性,与类、接口、枚举是在同一个层次。它可
以声明在包、类、字段、方法、局部变量、方法参数等的前面,用来对这些元素进行说明,注释。
Annotation(注解)是JDK1.5及以后版本引入的。它可以用于创建文档,跟踪代码中的依赖性,甚至执行基本编译
时检查。注解是以‘@注解名’在代码中存在的,根据注解参数的个数,我们可以将注解分为:标记注解、单值注
解、完整注解三类。它们都不会直接影响到程序的语义,只是作为注解(标识)存在,我们可以通过反射机制编程实
现对这些元数据(用来描述数据的数据)的访问。另外,你可以在编译时选择代码里的注解是否只存在于源代码级,
或者它也能在class文件、或者运行时中出现(SOURCE/CLASS/RUNTIME)。
注解的作用
如果要对于注解的作用进行分类,还没有明确的定义,不过我们可以根据它所起的作用,大致可分为三类:
编写文档:通过代码里标识的元数据生成文档【生成文档doc文档】
代码分析:通过代码里标识的元数据对代码进行分析【使用反射】
编译检查:通过代码里标识的元数据让编译器能够实现基本的编译检查【Override】
为什么学习注解
1、能够读懂别人写的代码,特别是框架相关的代码,增加代码的阅读性;
2、让编程更加简洁,代码更加清晰,理清自己的思路;
3、生成API文档;
Java中的常见注解
JDK内置注解
@Override
它的作用是对覆盖超类中方法的方法进行标记,如果被标记的方法并没有实际覆盖超类中的方法,则编译器会发
出错误警告。下面的例子是实现类Child实现了接口Person的方法 使用了@Override。
package com.demo.annotation;/** * 测试@Override注解 * @author Administrator * @date 2016年12月9日 */public interface Person {public String name();public int age();public void sing();}class Child implements Person {@Overridepublic String name() {// TODO Auto-generated method stubreturn null;}@Overridepublic int age() {// TODO Auto-generated method stubreturn 0;}@Overridepublic void sing() {// TODO Auto-generated method stub }}
@Deprecated
它的作用是对不应该再使用的方法添加注解,当编程人员使用这些方法时,将会在编译时显示提示信息,它与
javadoc里的@deprecated标记有相同的功能,准确的说,它还不如javadoc @deprecated,因为它不支持参数,
使用@Deprecated的示例代码示例如下:
package com.demo.annotation;/** * 测试@Deprecated注解 * @author Administrator * @date 2016年12月9日 */public interface Person {public String name();public int age();@Deprecatedpublic void sing();}class Child implements Person {@Overridepublic String name() {// TODO Auto-generated method stubreturn null;}@Overridepublic int age() {// TODO Auto-generated method stubreturn 0;}@Overridepublic void sing() {// TODO Auto-generated method stub}}class Test {@SuppressWarnings("deprecation")public void sing(){Person person = new Child();person.sing();//sing()方法已经过时}}
Person接口使用了@Deprecated修饰了一个已经过时的方法,此时强行调用超类继承来的方法就会有个代码过
时的横线,并且报一个代码过时的警告,但不会影响正常使用。如果要去掉警告可以使用
@suppressWarings("deprecation") 来忽略这个警告。
@SuppressWarnings
其参数有:
deprecation:使用了过时的类或方法时的警告
unchecked:执行了未检查的转换时的警告
fallthrough:当 switch 程序块直接通往下一种情况而没有 break 时的警告
path:在类路径、源文件路径等中有不存在的路径时的警告
serial:当在可序列化的类上缺少serialVersionUID 定义时的警告
finally :任何 finally 子句不能正常完成时的警告
all:关于以上所有情况的警告
这里的演示在上面已经出现过。
常见的第三方注解
在这里只是简单的演示一下,在学习框架的过程中再详细说明。
按照过去的方式就是写一个配置文件:
使用注解方式不再使用配置文件:
Java注解的分类
按照运行机制分类
源码注解:注解只在源码中存在,编译成.class文件就不存在了;
编译时注解:注解在源码和.class文件中都存在,比如@SuppressWarnings、@Override和@Deprecated只在
编译时刻起作用;
运行时注解:源码、编译后以及运行时都存在的注解,在运行阶段还起作用,甚至会影响运行逻辑的注解,比如
spring框架的@Autowired注解。
按照来源分类
来自JDK的注解:@SuppressWarnings、@Override和@Deprecated
来自第三方的注解:比如spring框架的@Autowired注解
自定义注解:我们自己定义的注解。
元注解
注解的注解:自定义注解中比较常见。
Java自定义注解
先来看一个模板:
自定义注解语法要求
1)使用@Interface关键字定义注解;
2)成员以无参无异常方式声明;
3)可以用default为成员指定一个默认值;
4)成员类型是受限的,合法的类型包括原始类型及String、Class、Annotation、Enumeration;
5)如果注解只有一个成员,则成员必须取名为value(),在使用时可以忽略成员名和赋值号(=);
6)注解类可以没有成员,没有成员的注解称为标识注解;
注解的注解(元注解)
@Target({ElementType.METHOD,ElementType.TYPE})
CONSTRUCTOR:构造方法声明
FIELD:字段声明
LOACL_VARIABLE:局部变量声明
METHOD:方法声明
PACKAGE:包声明
PARAMETER:参数声明
TYPE:类或者接口声明
@Retention(RetentionPolicy.RUNTIME)
SOURCE:只在源码显示,编译时会丢弃
CLASS:编译时会记录到class中,运行时忽略
RUNTIME:运行时存在,可以通过反射读取
@Inherited
允许子类继承
@Documented
生成javadoc时会包含注解
使用自定义注解
使用注解的语法:@<注解名>(<成员名1>=<成员值1>,<成员名2>=<成员值2>,...)
一个简单的例子:
定义@Description注解:
package com.demo.annotation;import java.lang.annotation.Documented;import java.lang.annotation.ElementType;import java.lang.annotation.Inherited;import java.lang.annotation.Retention;import java.lang.annotation.RetentionPolicy;import java.lang.annotation.Target;@Target({ElementType.METHOD,ElementType.TYPE})@Retention(RetentionPolicy.RUNTIME)@Inherited@Documentedpublic @interface Description {String desc();String author();int age() default 18;}
使用注解:
package com.demo.annotation;@Description(desc="I am class annotation",author="Mooc boy",age=18)public class AnnotationTest {@Description(desc="I am method annotation",author="Mooc boy",age=18)public String eyeColor(){return "red";}}
@Description注解在eyeColor()方法上使用,可以在类或者接口上使用
解析注解
概念:通过反射获取类,函数或成员上的运行时注解信息,从而实现动态控制控制程序运行的逻辑。
对于@RetentionRetention表示作用范围,我们知道:SOURCE表示只在源码显示,编译时会丢弃;
CLASS表示编译时会记录到class中,运行时忽略;RUNTIME表示运行时存在,可以通过反射读取。前两个都不会显
示结果,只有最后一个会显示结果。
一个例子:
package com.demo.annotation;import java.lang.annotation.Annotation;import java.lang.reflect.Method;/** * 解析注解 * @author Administrator * @date 2016年12月9日 */public class Demo {public static void main(String[] args) {//1.使用类加载器加载类try {Class< ?> clazz = Class.forName("com.demo.annotation.AnnotationTest"); //2.找到类上面的注解boolean flag1 = clazz.isAnnotationPresent(Description.class);if(flag1){//3.拿到注解实例Description description1 = (Description)clazz.getAnnotation(Description.class);System.out.println(description1.desc());System.out.println(description1.author());System.out.println(description1.age());}//4.解析找到方法上的注解Method[] methods = clazz.getMethods();for (Method method : methods) {boolean flag2 = method.isAnnotationPresent(Description.class);if(flag2){//5.拿到注解实例Description description2 = (Description)method.getAnnotation(Description.class);System.out.println(description2.desc());System.out.println(description2.author());System.out.println(description2.age());}}//另外一种解析方法for (Method method : methods) {Annotation[] annotations = method.getAnnotations();for (Annotation annotation : annotations) {if(annotation instanceof Description){Description description3 = (Description)annotation;System.out.println(description3.desc());System.out.println(description3.author());System.out.println(description3.age());}}}} catch (ClassNotFoundException e) {e.printStackTrace();}}}
运行结果:
关于@Inherited元注解
父子类继承注解这块分两种情况,一个是注解定义了@Inherited,一个是没定义。在每种情况中又分类上的注
解,子类实现父类抽象方法,继承了父类方法,覆盖了父类方法这四种情况,具体继承规则如下:
编写自定义注解时未写@Inherited的运行结果:
子类的类上能否继承到父类的类上的注解? 否
子类方法,实现了父类上的抽象方法,这个方法能否继承到注解? 否
子类方法,继承了父类上的方法,这个方法能否继承到注解? 能
子类方法,覆盖了父类上的方法,这个方法能否继承到注解? 否
编写自定义注解时写了@Inherited的运行结果:
子类的类上能否继承到父类的类上的注解? 能
子类方法,实现了父类上的抽象方法,这个方法能否继承到注解? 否
子类方法,继承了父类上的方法,这个方法能否继承到注解? 能
子类方法,覆盖了父类上的方法,这个方法能否继承到注解? 否
仅供参考!
- 【框架基础】:全面解析Java注解(一)
- 【框架基础】:全面解析Java注解(二)
- 框架基础——全面解析Java注解
- Java 基础注解全面解析
- 全面解析Java注解
- 全面解析Java注解
- 全面解析Java注解
- 全面解析 Java 注解
- 全面解析Java注解
- 全面解析Java注解
- Java注解全面解析
- 全面解析Java注解
- Java注解全面解析
- Java 注解全面解析
- 全面解析java注解
- 全面解析Java注解
- 全面解析Java注解
- 全面解析Java注解
- Debian下安装sqlplus 工具
- MySQL里的set global wait_timeout
- zmq中的 zmq_curve_keypair
- PHP设计模式系列 - 外观模式
- 【行业】移动市场变化迅速,如何以不变应万变,把握生存先机?
- 【框架基础】:全面解析Java注解(一)
- 封装继承
- zmq 中的 zmq_disconnect
- RDK中HLOS与RTOS的区别
- Linux下查看MySQL的安装路径
- zmq中的 zmq_errno
- android telephony 之 UICC 卡数据读写及 UICC 框架结构
- debian+kvm+vnc安装
- linux 启动 终止 tomcat,查看进程