java中的注解

1. 注解概述

1.1 注解解释

 

注释:
    解释代码,给程序员看

注解:
    Java语言中的类、方法、变量、参数和包等都可以被标注。和Javadoc不同,Java标注可以通过反射获取标注内容。在编译器生成类文件时,标注可以被嵌入到字节码中。Java虚拟机可以保留标注内容,在运行时可以获取到标注内容。 当然它也支持自定义Java标注
    JDK1.5之后的特征
    用于说明程序
    一般在框架中使用
    格式:
        @AnnotationName

文档注释:
    @param @return @Exeception 从根本上是一个注释,不存在代码编译,不会生成对应的.class字节码问题,只是提供给JavaDoc API文件生成工具。作为标记生成对应的文档。
    
注解是有一部分参与编译
    @Override并不是没编译就有效果了,是因为不管是Eclipse还是IDEA都可以预编译Java代码生成对应的.class文件的

 

1.2 注解作用

 

生成文档:
    代码中生成对应的JavaDoc API文档
    @param @return 
    
    【IDEA JavaDoc工具使用参数】
        Other  Command Line Arguments : -encoding utf-8 -charset utf-8
        解决中文乱码,因为IDEA默认编码集为UTF-8 Windows GKB

代码检查:
    继承重写,或者说接口遵从之后的实现中,存在@Override
    
代码数据获取: [小框架]
    通过反射获取指定注解中的一些内容,例如 配置,数据,操作,验证。。。

 

1.3 Java中预定义的一些注解

@Override:
    重写/实现方法的情况下,检查方法声明是否和父类或者接口中的方法声明一致。强制格式检查。
    
@Deprecated
    标注当前方法已过时,例如 Data日期类内的一些方法
    
@SuppressWarnings("all")
    压制警告,可以用于一些代码中存在明确无异常的情况下,压制一些警告

 

2. Java中自定义注解

2.1 Java中自定义注解的方式

 

格式:
    public @interface AnnotationName {
        属性列表;
    }
    
Annotation注解是可以编译得到对应的.class字节码文件,验证了注解是可以参与编译过程的

通过反编译工具可以得到一下内容
【Annotation本质】
public interface MyAnnotation1 extends java.lang.annotation.Annotation {
}

MyAnnotation1
    本质是一个interface,同时java.lang.annotation.Annotation 子接口

 

/**
 * 自定义注解!!!
 * public interface MyAnnotation1 extends java.lang.annotation.Annotation {
 * }
 *
 * @author Anonymous
 * @date 2020/3/10 11:01
 */
public @interface MyAnnotation1 {
    // 属性 ==> 方法形式
}

 

 

2.2 Annotation注解属性【难点】

 

属性:
    开发书写代码使用注解的方式中,数据使用方式更加偏向于属性概念。
        使用 
            1. 在书写代码中使用
                @MyAnnotation(id=1, name="小小", age=16)
            2. 利用反射时,会涉及到getXXX方法
                通过属性名获取对应值的概念来完成的
                
    【但是实际上是利用abstract方法来完成属性概念的】

属性使用的格式[实际按照方法格式操作]
    1. 属性的值数据类型和对应具体数据 ==> 返回值类型和返回的数据
        属性类型支持:
            a. 基本数据类型
            b. String类型
            c. 其他的注解类型
            d. 枚举类型 
                枚举就是一个带有名字的常量,为了更好的域阅读性和操作
            e. 以上类型对相应的数组
        
        属性值要求
            a. 定义属性时可以使用default关键字,加上默认值,该属性在使用的过程中是
            没有强制要求属性值,如果没有赋予属性值,采用对应的默认值操作,如果赋
            值,使用对应值
            
            b. 如果注解中有且只有一个value属性,或者说注解中除value属性之外,都有
            默认值,不管是类,方法,成员变量,包使用当前注解是可以直接在括号内加入
            对应数据类型数值、
            
            c. 如果属性是数组类型, {}大括号保存,并且不同的内容,使用,隔开
    2. 属性的键名字 ==> 方法的名字

2.3 元注解

 

给予注解的解释,用于约束注解的一些操作问题
@Retention - 
    标识这个注解怎么保存,是只在代码中,还是编入class文件中,或者是在运行时可以通过反射访问。
    RetentionPolicy.RUNTIME:当前注解会编译生成对应的.class字节码文件,并且可以加
    载到JVM中,参与代码执行
    RetentionPolicy.CLASS: 
    
别纠结,记下就好:
    RetentionPolicy.SOURCE:注解将被编译器丢弃(该类型的注解信息只会保留在源码里,源码经过编译后,注解信息会被丢弃,不会保留在编译好的class文件里)
    @Override
    对应属性RetentionPolicy.SOURCE
    在代码编译过程中,检查方法格式是否正确,不参与代码运行和解析。
    
@Documented 
    标记这些注解是否包含在用户文档中。
    是否可以通过JavaDoc工具,生成对应的API文档
    
@Target 
    标记这个注解应该是哪种 Java 成员。
    属性:
        ElementType
            TYPE: 当前注解可以用于类声明
            METHOD: 当前注解可以用于方法声明位置
            FIELD:当前注解可以用于成员变量声明位置
@Inherited 
    标记这个注解是继承于哪个注解类(默认 注解并没有继承于任何子类)
    
【重点】
    @Target目标
        可以作用范围 类,方法,成员变量...
    @Retention
        RetentionPolicy.RUNTIME 常用

 

@Override底层注解

 

 

 

 

2.4 使用反射获取注解中的内容【用途】

 

driverClass=com.mysql.jdbc.Driver
user=root
password=123456
url=jdbc:mysql://localhost:3306/db_name
# 配置文件保存到properties文件中,使用文件中内容读取配置获取属性
# properties Properties System.getProperties();
# Properties ==> driverClass ==> com.mysql.jdbc.Driver ==> 完整的包名.类名
# Class.forName 

 


import java.io.FileInputStream;
import java.io.IOException;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.util.Properties;

/**
 * 解析properties文件读取内容,使用反射创建对象,赋值成员变量
 *
 * @author Anonymous
 */
public class ReflectFile {
    public static void main(String[] args) throws IOException, ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException, NoSuchFieldException {
        Properties properties = new Properties();
        properties.load(new FileInputStream("./src/1.properties"));

        String className = properties.getProperty("className");
        String id = properties.getProperty("id");
        String name = properties.getProperty("name");
        System.out.println(className);
        Class<?> aClass = Class.forName(className);

        Person person = (Person) aClass.getConstructor().newInstance();

        System.out.println(person);

        Field declaredField = aClass.getDeclaredField("id");
        declaredField.setAccessible(true);
        declaredField.set(person, Integer.parseInt(id));

        Field declaredField2 = aClass.getDeclaredField("name");
        declaredField2.setAccessible(true);
        declaredField2.set(person, name);

        System.out.println(person);
    }
}

 

 


import java.io.IOException;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;

/**
 * 通过注解方式,获取注解的属性,创建对象,读取数据
 * 通常用于代码配置
 *      Servlet Listener Filter
 * @author Anonymous
 */
@MyAnnotation5(className = "com.qfedu.a_annotation.Person",
        id = 2,
        name = "骚磊")
public class ReflectAnnotatiaon {
    public static void main(String[] args) throws IOException, ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException, NoSuchFieldException {
        // 加载ReflectAnnotatiaon
        Class<ReflectAnnotatiaon> cls = ReflectAnnotatiaon.class;

        // 因为注解是在类名之上,通过Class获取对应的Annotation
        MyAnnotation5 annotation = cls.getAnnotation(MyAnnotation5.class);
        /*
        类似于注解的实现类
        class XXX implements MyAnnotation5 {
            public String className() {
                return "com.qfedu.a_annotation.Person";
            }
            public int id() {
                return 2;
            }
            public String name() {
                return "骚磊";
            }
        }
         */
        // 感觉是在执行对应的方法,获取注解的属性
        String s = annotation.className();
        int id = annotation.id();
        String name = annotation.name();

        System.out.println(s);
        System.out.println(id);
        System.out.println(name);

        Class<?> aClass = Class.forName(s);

        Constructor<?> constructor = aClass.getConstructor(Integer.class, String.class);

        Object o = constructor.newInstance(id, name);
        System.out.println(o);
    }
}

 

3. 注解使用总结

 

1. 注解以后大多数情况下,都是使用过程,而不是自定义,会使用到框架中预处理好的注解。
2. 注解是给谁用的?
    a. 编译器
    b. 解析代码使用
    c. JVM运行代码使用
3. 注解是一个标签,有时候是做标记的,有时候标签是有属性的。

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值