Java 注解

1 注解

1.1注解的理解

    1. 注解(Annotation)也被称为元数据(Metadata),用于修饰解释 包、类、方法、属性、构造器、局部变量等数据信息。
    1. 和注释一样,注解不影响程序逻辑,但注解可以被编译或运行,相当于嵌入在代码中的补充信息。
    1. 在 JavaSE 中,注解的使用目的比较简单,例如标记过时的功能,忽略警告等。在 JavaEE 中注解占据了更重要的角
      色,例如用来配置应用程序的任何切面,代替 java EE 旧版中所遗留的繁冗代码和 XML 配置等。

1.2基本的 Annotation 介绍

使用 Annotation 时要在其前面增加 @ 符号, 并把该 Annotation 当成一个修饰符使用。用于修饰它支持的程序元

三个基本的 Annotation:

    1. @Override: 限定某个方法,是重写父类方法, 该注解只能用于方法-
    1. @Deprecated: 用于表示某个程序元素(类, 方法等)已过时
    1. @SuppressWarnings: 抑制编译器警告

1.3基本的 Annotation 应用案例

1.3.1 Override实例

java 复制代码
package javaannotation;

public class OverrideDemo1 {
    public static void main(String[] args) {

    }
}

class Father{
    public void fly(){
        System.out.println("Father fly......");
    }
    public void say(){};
}

class Son extends Father{
    //1. @Override 注解放在 fly 方法上,表示子类的 fly 方法时重写了父类的 fly
    //2. 这里如果没有写 @Override 还是重写了父类 fly
    //3. 如果你写了@Override 注解,编译器就会去检查该方法是否真的重写了父类的
    // 方法,如果的确重写了,则编译通过,如果没有构成重写,则编译错误
    //4. 看看 @Override 的定义
    @Override
    public void fly() {
        super.fly();
    }

    @Override
    public void say() {
        super.say();
    }
}

1.3.2 SuppressWarnings实例

1. 当我们不希望看到这些警告的时候,可以使用 SuppressWarnings 注解来抑制警告信息
2. 在{""} 中,可以写入你希望抑制(不显示)警告信息
3. 可以指定的警告类型有
 all,抑制所有警告
 boxing,抑制与封装/拆装作业相关的警告
 cast,抑制与强制转型作业相关的警告
 dep-ann,抑制与淘汰注释相关的警告
 deprecation,抑制与淘汰的相关警告
 fallthrough,抑制与 switch 陈述式中遗漏 break 相关的警告
 finally,抑制与未传回 finally 区块相关的警告
 hiding,抑制与隐藏变数的区域变数相关的警告
 incomplete-switch,抑制与 switch 陈述式(enum case)中遗漏项目相关的警告
 javadoc,抑制与 javadoc 相关的警告
 nls,抑制与非 nls 字串文字相关的警告
 null,抑制与空值分析相关的警告
 rawtypes,抑制与使用 raw 类型相关的警告
 resource,抑制与使用 Closeable 类型的资源相关的警告
 restriction,抑制与使用不建议或禁止参照相关的警告
 serial,抑制与可序列化的类别遗漏 serialVersionUID 栏位相关的警告
 static-access,抑制与静态存取不正确相关的警告
 static-method,抑制与可能宣告为 static 的方法相关的警告
 super,抑制与置换方法相关但不含 super 呼叫的警告
 synthetic-access,抑制与内部类别的存取未最佳化相关的警告
 sync-override,抑制因为置换同步方法而遗漏同步化的警告
 unchecked,抑制与未检查的作业相关的警告
 unqualified-field-access,抑制与栏位存取不合格相关的警告
 unused,抑制与未用的程式码及停用的程式码相关的警告
4. 关于 SuppressWarnings 作用范围是和你放置的位置相关
java 复制代码
package javaannotation;

import java.util.ArrayList;
import java.util.List;

@SuppressWarnings({"all"})
public class SuppressWarningDemo {
    public static void main(String[] args) {
        List list=new ArrayList<>();
        list.add("jack");
        list.add("tom");
        list.add("mary");
        int i;
        System.out.println(list.get(1));
    }
}

1.4 自定义注解

public @interface 注解名称{

public 属性类型 属性名() default 默认值

java 复制代码
package javaannotation;

//自定义注解
public @interface MyAnnotation {
    //在注解中只能定义属性 public 属性类型 属性名() default 默认值
    /*
        属性类型必须是以下范围之一
        1.8种基本数据类型
        2.String类型
        3.Class类型
        4.枚举类型
        5.注解类型
        6.以上所有的类型的一维数组形式
    * */
    public String name();
    public double price() default 99.0;
}
@MyAnnotation(name = "测试") //没有指定price属性,默认为99
public class TestAnnotaion {
    @MyAnnotation(name="数据",price = 123)
    private String name;

    @MyAnnotation(name="构造方法")
    public TestAnnotaion(){

    }

    @MyAnnotation(name = "成员方法",price = 100)
    public void method(@MyAnnotation(name="参数") String msg){

    }
}

1.5元注解

元注解:就是修饰注解的注解

常见的元注解有两个

  • @Target:约束自定义注解只能在哪些地方使用
  • @Retention:声明注解的生命周期

Target中可以使用的值定义在ElementType枚举类中,常用的值如下

TYPE,类,接口

FIELD,成员变量

METHOD,成员方法

PARAMETER,方法参数

CONSTRUCTOR,构造器

LOCAL_VARIABLE,局部变量

java 复制代码
package javaannotation.demo;

import java.lang.annotation.ElementType;
import java.lang.annotation.Target;

@Target({ElementType.METHOD, ElementType.TYPE})
public @interface Book2 {
    public String value();

    public double price() default 99.0;

    public String[] author(); //有多个作者
}

Retention中可以使用的值定义在RetentionPolicy枚举类中,常用的值如下

SOURCE:注解只作用在源码阶段,生成的字节码文件中不存在

RUNTIME:注解作用在源码阶段,字节码文件阶段,运行阶段(开发常用)

CLASS:注解作用在源码阶段,字节码文件阶段,运行阶段不存在,默认值

1.6注解解析

注解的解析

  • 注解操作中经常需要进行解析,注解析解析就是判断是不否存在注解,存在注解就解析出内容

与注解解析相关的接口

  • AnnotatedElement:该接口定义了与注解解析相关的解析方法

Annotation[] getDeclaredAnnotations():获得当前对象上的所有注解,返回注解数组

T getDecaredAnnotation(Class)annotationClass):根据注解类型获得注解对象

boolean isAnnotationPresent(ClassannotationClass)判断当前对象是否使用了指定的注解,如果是的话返回true,否则返回false

代码演示

java 复制代码
package javaannotation.demo2;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Book {
    public String value();
}
package javaannotation.demo2;

public class BookStore {
    @Book("Java入门") //注解析特殊作用:把value的值赋给当前成员变量
    private String bookName;//成员变量

    public String getBookName() {
        return bookName;
    }

    public void setBookName(String bookName) {
        this.bookName = bookName;
    }

}
package javaannotation.demo2;

import org.junit.Test;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;

public class BookStroeTest {
    @Test
    public void testParse() throws NoSuchFieldException, InstantiationException, IllegalAccessException {
        //1.获取Class对象
        Class<BookStore> bookStoreClass=BookStore.class;
        BookStore bookStore = bookStoreClass.newInstance();
        //获取成员变量对象
        Field field=bookStoreClass.getDeclaredField("bookName");

        //私有成员变量
        field.setAccessible(true);

        //判断:成员变量上是否有BOOK注解
        if (field.isAnnotationPresent(Book.class)) {
            //有注解
            Book book=field.getDeclaredAnnotation(Book.class);
            //获取BOOK注解中的值
            String bookName=book.value();
            //使用反射技术给私有成员变量赋值
            field.set(bookStore,bookName);
        }
        System.out.println(bookStore.getBookName());
    }
}

1.7注解解析(扩展)

java 复制代码
package javaannotation.demo5.init;

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.FIELD)
public @interface CreateObject {
    public String value();
}

package javaannotation.demo5.dao;

import javaannotation.demo5.pojo.User;

import java.util.ArrayList;
import java.util.List;
//dao 层
public class UserDao {
    public List<User> findAllUser(){
        List<User> users=new ArrayList<>();
        users.add(new User(1,"熊大",23));
        users.add(new User(2,"熊二",23));
        users.add(new User(3,"张三",23));
        return users;
    }

    //添加
    public boolean addUser(){
        return true;
    }

    //删除
    public boolean deleteUser(){
        return true;
    }
}

package javaannotation.demo5.service;

import javaannotation.demo5.dao.UserDao;
import javaannotation.demo5.init.CreateObject;
import javaannotation.demo5.pojo.User;

import java.net.PortUnreachableException;
import java.util.List;
//service层
public class UserService {
    //成员变量(需要依赖userDao对象)
    @CreateObject("userDao")
    private UserDao userDao;
    public List<User> queryAllUser(){
        return userDao.findAllUser();
    }
    public boolean addUser(User user){
        return false;
    }

    public boolean deleteUser(int id){
        return false;
    }
}
package javaannotation.demo5.init;

import javaannotation.demo5.dao.UserDao;
import javaannotation.demo5.service.UserService;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;

public class App {
    public static void main(String[] args) throws NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
        //项目程序启动,就会初始化一些对象和参数

        //获取到UserService的Class对象
        Class<UserService> userServiceClass=UserService.class;

        //构造器
        Constructor<UserService> cons=userServiceClass.getConstructor();

        //成员变量
        Field[] fields = userServiceClass.getDeclaredFields();

        for (Field field:fields){
            //判断,成员变量是否有@CreateObject注妥
            if (field.isAnnotationPresent(CreateObject.class)) {
                //有注分则解析
                CreateObject obj=field.getDeclaredAnnotation(CreateObject.class);
                String objectValue=obj.value();

                if(objectValue.equals("userDao")){
                    UserDao userDao = new UserDao();

                    field.setAccessible(true);
                    field.set(cons.newInstance(),userDao);

                }
            }
        }
    }
}
相关推荐
尘浮生4 分钟前
Java项目实战II基于微信小程序的校运会管理系统(开发文档+数据库+源码)
java·开发语言·数据库·微信小程序·小程序·maven·intellij-idea
小白不太白9508 分钟前
设计模式之 模板方法模式
java·设计模式·模板方法模式
Tech Synapse11 分钟前
Java根据前端返回的字段名进行查询数据的方法
java·开发语言·后端
xoxo-Rachel17 分钟前
(超级详细!!!)解决“com.mysql.jdbc.Driver is deprecated”警告:详解与优化
java·数据库·mysql
乌啼霜满天24919 分钟前
JDBC编程---Java
java·开发语言·sql
色空大师32 分钟前
23种设计模式
java·开发语言·设计模式
闲人一枚(学习中)32 分钟前
设计模式-创建型-建造者模式
java·设计模式·建造者模式
2202_754421541 小时前
生成MPSOC以及ZYNQ的启动文件BOOT.BIN的小软件
java·linux·开发语言
蓝染-惣右介1 小时前
【MyBatisPlus·最新教程】包含多个改造案例,常用注解、条件构造器、代码生成、静态工具、类型处理器、分页插件、自动填充字段
java·数据库·tomcat·mybatis