Java注解基础学习笔记
程序员文章站
2024-02-16 09:43:46
...
Java注解基础学习笔记
文章目录
1.注解基本概念
注解是一种引用数据类型,它编译后的文件是.class文件。注解的基本用法是@注解类型名(参数赋值),注解的作用范围可以是类,域,方法,构造函数,局部变量等,不过特定的注解的作用范围需要看该注解的具体规定。
了解注解基础对后期注解开发有很大的帮助。
2.JDK1.8常见的注解
aaa@qq.com
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.SOURCE)
public @interface Override {
}
该注解只能放在方法上,用于编译阶段判定该方法是不是对父类或是接口重写的方法,这样可以避免程序员打错字或是对不存在的方法进行重写。
aaa@qq.com
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(value={CONSTRUCTOR, FIELD, LOCAL_VARIABLE, METHOD, PACKAGE, PARAMETER, TYPE})
public @interface Deprecated {
}
该注解主要表示构造函数,域,方法等是否已经过期。过期不代表不能使用。如果使用,则会在代码中出现删除线,编译时会有警告。
2.3元注解
元注解就是注解的注解,常见的有@Target和@Retention。前者表示注解的范围,后者表示注解保存的地方。
@Target
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Target {
/**
* Returns an array of the kinds of elements an annotation type
* can be applied to.
* @return an array of the kinds of elements an annotation type
* can be applied to
*/
ElementType[] value();
}
该元注解里面有一个value属性,它表示被@Target修饰的注解的作用范围,比如类上或是构造函数上等
ElementType的类型如下所示
ElementType
public enum ElementType {
/** Class, interface (including annotation type), or enum declaration */
TYPE,
/** Field declaration (includes enum constants) */
FIELD,
/** Method declaration */
METHOD,
/** Formal parameter declaration */
PARAMETER,
/** Constructor declaration */
CONSTRUCTOR,
/** Local variable declaration */
LOCAL_VARIABLE,
/** Annotation type declaration */
ANNOTATION_TYPE,
/** Package declaration */
PACKAGE,
/**
* Type parameter declaration
*
* @since 1.8
*/
TYPE_PARAMETER,
/**
* Use of a type
*
* @since 1.8
*/
TYPE_USE
}
@Retention
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Retention {
/**
* Returns the retention policy.
* @return the retention policy
*/
RetentionPolicy value();
}
该元注解有一个value属性,该值表示被@Retention修饰的注解最终存在的位置。
RetentionPolicy类型如下:
RetentionPolicy
public enum RetentionPolicy {
/**
* Annotations are to be discarded by the compiler.
*/
SOURCE,
/**
* Annotations are to be recorded in the class file by the compiler
* but need not be retained by the VM at run time. This is the default
* behavior.
*/
CLASS,
/**
* Annotations are to be recorded in the class file by the compiler and
* retained by the VM at run time, so they may be read reflectively.
*
* @see java.lang.reflect.AnnotatedElement
*/
RUNTIME
}
其中
- SOURCE表示被@Retention修饰的注解只能保存在源代码中,并不能存储到class文件中,比如@Override。
- CLASS表示被@Retention修饰的注解能存储到class文件中。
- RUNTIME表示表示被@Retention修饰的注解能存储到class文件中,而且还能在运行时被反射。
3.自定义注解
3.1基本格式
[可见性修饰符] @interface 自定义注解名{
属性1;
属性2;
属性3;
}
3.2关于属性
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface MyAnnotation {
String value();
//设置默认值
// String name() default “Lord_Bao";
}
@MyAnnotation("lord_bao")
class TestMyAnnotation{
public static void main(String[] args) {
}
}
- 属性的类型范围
- 8大基本类型:byte short int long float double boolean char
- Class String
- 枚举类型
- 上述类型的数组形式
- 在外部用注解的时候,必须要对相应的属性进行设值。不过可以在注解类里面自己设置默认值。
- 特殊情况:当注解类里面只有一个value属性的时候,在外部使用注解的时候可以不用显式写value。
- 特殊情况:当属性是数组的形式且该数组只有一个元素的时候,可以不用写{}
4.反射+注解创建对象
场景描述
通过反射,创建自定义类的对象实例。
要求 该类必须被 @MyBean修饰
其次 该类必须要有一个id域,且该id域要被@MyValue注解修饰 并赋值
MyBean
package com.lordbao.DIYAnnotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* @Author Lord_Bao
* @Date 2020/9/14 14:32
* @Version 1.0
*/
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface MyBean {
}
MyValue
package com.lordbao.DIYAnnotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* @Author Lord_Bao
* @Date 2020/9/14 14:33
* @Version 1.0
*/
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface MyValue {
int value();
}
自定义的Student类
@MyBean
class Student{
@MyValue(1)
private int id;
@Override
public String toString() {
return "Student{" +
"id=" + id +
'}';
}
}
测试代码
package com.lordbao.DIYAnnotation;
import java.lang.reflect.Field;
/**
* @Author Lord_Bao
* @Date 2020/9/14 14:35
* @Version 1.0
*
* 场景模拟:
*
* 通过反射,创建自定义类的对象实例。
* 要求 该类必须被 @MyBean修饰
* 其次 该类必须要有一个id域,且该id域要被@MyValue注解修饰 并赋值
*
*
*/
public class TestDIYAnnotation {
public static void main(String[] args) throws Exception {
Class studentClass = Class.forName("com.lordbao.DIYAnnotation.Student");
//判断studentClass 是不是被自定义的注解修饰
if (studentClass.isAnnotationPresent(MyBean.class)){
Student student = (Student) studentClass.newInstance();
Field idField = studentClass.getDeclaredField("id");
idField.setAccessible(true);
//判断idField是否被自定义的注解修饰
if (idField.isAnnotationPresent(MyValue.class)){
//value()方法 与 MyValue类的value对应
int id = idField.getAnnotation(MyValue.class).value();
idField.set(student,id);
System.out.println(student);
}else {
throw new Exception("该类的id没有被@MyValue注解修饰,无法实例化该对象");
}
}else {
throw new Exception("该类没有被@MyBean注解修饰,无法实例化该对象");
}
}
}
结果
Student{id=1}