java框架解析注解_【框架基础】:全面解析Java注解(一)

Java注解概述

要了解Java注解要先知道Java的反射,反射是运行时获取类的成员,注解也是类的成员,以此达到动态编码的效

果,多用在框架,或者使用框架时候添加注解让框架调用。

注解定义:注解(Annotation),也叫元数据。Java提供了一种原程序中的元素关联任何信息和任何元数据的途

径和方法,一种代码级别的说明。它是JDK1.5及以后版本引入的一个特性,与类、接口、枚举是在同一个层次。它可

以声明在包、类、字段、方法、局部变量、方法参数等的前面,用来对这些元素进行说明,注释。

Annotation(注解)是JDK1.5及以后版本引入的。它可以用于创建文档,跟踪代码中的依赖性,甚至执行基本编译

时检查。注解是以‘@注解名’在代码中存在的,根据注解参数的个数,我们可以将注解分为:标记注解、单值注

解、完整注解三类。它们都不会直接影响到程序的语义,只是作为注解(标识)存在,我们可以通过反射机制编程实

现对这些元数据(用来描述数据的数据)的访问。另外,你可以在编译时选择代码里的注解是否只存在于源代码级,

或者它也能在class文件、或者运行时中出现(SOURCE/CLASS/RUNTIME)。

注解的作用

如果要对于注解的作用进行分类,还没有明确的定义,不过我们可以根据它所起的作用,大致可分为三类:

编写文档:通过代码里标识的元数据生成文档【生成文档doc文档】

代码分析:通过代码里标识的元数据对代码进行分析【使用反射】

编译检查:通过代码里标识的元数据让编译器能够实现基本的编译检查【Override】

为什么学习注解

1、能够读懂别人写的代码,特别是框架相关的代码,增加代码的阅读性;

2、让编程更加简洁,代码更加清晰,理清自己的思路;

3、生成API文档;

Java中的常见注解

JDK内置注解

4e65c0d38d5df6bcad783c9337d4ea14.png

@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 {

@Override

public String name() {

// TODO Auto-generated method stub

return null;

}

@Override

public int age() {

// TODO Auto-generated method stub

return 0;

}

@Override

public 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();

@Deprecated

public void sing();

}

class Child implements Person {

@Override

public String name() {

// TODO Auto-generated method stub

return null;

}

@Override

public int age() {

// TODO Auto-generated method stub

return 0;

}

@Override

public 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:关于以上所有情况的警告

这里的演示在上面已经出现过。

961fc5929f033c638f1277d8e9fb6245.png

常见的第三方注解

be8b4b90d775f37cd9a42fcc9dcfde9c.png

在这里只是简单的演示一下,在学习框架的过程中再详细说明。

按照过去的方式就是写一个配置文件:

286ad93b0710466a64e33bf3cceb61d2.png

使用注解方式不再使用配置文件:

8bfef6e36213788af125ae1d994ae809.png

Java注解的分类

按照运行机制分类

源码注解:注解只在源码中存在,编译成.class文件就不存在了;

编译时注解:注解在源码和.class文件中都存在,比如@SuppressWarnings、@Override和@Deprecated只在

编译时刻起作用;

运行时注解:源码、编译后以及运行时都存在的注解,在运行阶段还起作用,甚至会影响运行逻辑的注解,比如

spring框架的@Autowired注解。

按照来源分类

来自JDK的注解:@SuppressWarnings、@Override和@Deprecated

来自第三方的注解:比如spring框架的@Autowired注解

自定义注解:我们自己定义的注解。

元注解

注解的注解:自定义注解中比较常见。

Java自定义注解

先来看一个模板:

b7ad2a7f6cd3fb96f34fe61d0f82a5d7.png

自定义注解语法要求

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时会包含注解

使用自定义注解

使用注解的语法:@(=,=,...)

一个简单的例子:

定义@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

@Documented

public @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();

}

}

}

运行结果:

8f73d4393be8c8571914045c69d9f244.png

关于@Inherited元注解

父子类继承注解这块分两种情况,一个是注解定义了@Inherited,一个是没定义。在每种情况中又分类上的注

解,子类实现父类抽象方法,继承了父类方法,覆盖了父类方法这四种情况,具体继承规则如下:

编写自定义注解时未写@Inherited的运行结果:

子类的类上能否继承到父类的类上的注解?    否

子类方法,实现了父类上的抽象方法,这个方法能否继承到注解?    否

子类方法,继承了父类上的方法,这个方法能否继承到注解?    能

子类方法,覆盖了父类上的方法,这个方法能否继承到注解?    否

编写自定义注解时写了@Inherited的运行结果:

子类的类上能否继承到父类的类上的注解?     能

子类方法,实现了父类上的抽象方法,这个方法能否继承到注解?      否

子类方法,继承了父类上的方法,这个方法能否继承到注解?      能

子类方法,覆盖了父类上的方法,这个方法能否继承到注解?      否

仅供参考!

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值