自学内容网 自学内容网

【JavaSE】Java注解

什么是注解 

        我们最早使用的注解有:方法重写 @Override,在编译期间进行硬性检测,加在方法上就表明该方法是从父类重写过来的。

        Java 注解(Annotation)又称 Java 标注,它可以用来对类、方法、属性、参数、包等进行标注,然后让编译器或运行时其他类进行解析,完成某个功能,注解也可以编译到字节码文件中。 当然它也支持自定义 Java 标注。

内置注解

        Java 语言中已经定义好的注解。

        @Override - 检查该方法是否是重写方法。如果发现其父类,或者是引用的接口中并没有该方法时,会报编译错误。

        @Deprecated - 标记过时方法。如果使用该方法,会报编译警告。

        @SuppressWarnings - 指示编译器去忽略注解中声明的警告。

        @FunctionalInterface 用于指示被修饰的接口是函数式接口。

元注解

        元注解是 java API 提供的,是用于修饰注解的注解,通常用在注解的定义上。

@Target(ElementType.METHOD) // 定义这个注解只能用在方法上
@Retention(RetentionPolicy.SOURCE) // 定义这个注解在源文件中有效(编译期间)
public @interface Override {
}

        @Retention - 标识这个注解怎么保存,是只在代码中,还是编入 class 文件中,或者是在运行时可以通过反射访问。

        @Documented - 标记这些注解是否包含在用户文档中。

        @Target - 标记这个注解应该是哪种 Java 成员。

        @Inherited - 标记这个注解是继承于哪个注解类(默认注解并没有继承于任何类)

        @Repeatable - 标识某注解可以在同一个声明上使用多次。

重点掌握

        @Target:用于描述注解的使用范围(即:被描述的注解可以用在什么地方.         ElementType.TYPE 可以应用于类的任何元素。
        ElementType.CONSTRUCTOR 可以应用于构造函数。
        ElementType.FIELD 可以应用于字段或属性。
        ElementType.LOCAL_VARIABLE 可以应用于局部变量。
        ElementType.METHOD 可以应用于方法级注释。
        ElementType.PACKAGE 可以应用于包声明。
        ElementType.PARAMETER 可以应用于方法的参数。

        @Retention:@Retention 定义了该注解被保留的时间长短:某些注解仅出现在源代码中,而被编译器丢弃;而另一些却被编译在 class 文件中;编译在 class文件中的注解可能会被虚拟机忽略,而另一些在 class 被装载时将被读取(请注意并不影响 class 的执行,因为注解与 class 在使用上是被分离的)。用于描述注解的生命周期(即:被描述的注解在什么范围内有效)取值有:
        1.SOURCE:在源文件中有效(即源文件保留)
        2.CLASS:在 class 文件中有效(即 class 保留)
        3.RUNTIME:在运行时有效(即运行时保留)

自定义注解

        对注解进行定义:

package annotation;

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

    String message() default "";

    int length() default 0;

    String lengthmessage() default "";

}

        对注解进行使用:

package annotation;

public class User {

    private int num;

    @NotNull(length = 2, message = "名字不能为空", lengthmessage = "名字不能小于2位")
    private String name;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getNum() {
        return num;
    }

    public void setNum(int num) {
        this.num = num;
    }

}

        对注解进行解析: 

package annotation;

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

public class Test {

    public static void main(String[] args) throws NoSuchMethodException, SecurityException, Exception {
        User user = new User();
        user.setName("j");
        Field[] fields = user.getClass().getDeclaredFields(); // 通过反射拿到类中所有的属性
        for (Field field : fields) { // 循环所有的属性
            NotNull notNull = field.getAnnotation(NotNull.class); // 获取属性上的指定的注解
            if (notNull != null) {
                // 通过name属性名字获得对应的get方法名字,再用get方法名字获得方法
                Method m = user.getClass().getMethod("get" + getMethodName(field.getName()));
                Object obj = m.invoke(user); // 调用获得到的方法,获得返回值
                if (obj == null) {
                    System.err.println(field.getName() + notNull.message()); // 获取注解属性值
                    throw new NullPointerException(notNull.message());
                } else {
                    if (String.valueOf(obj).length() < (notNull.length())) {
                        System.err.println(field.getName() + notNull.lengthmessage());
                    }
                }
            }
        }
    }

    /**
     * 把一个字符串的第一个字母大写
     */
    private static String getMethodName(String fildeName) throws Exception {
        byte[] items = fildeName.getBytes();
        items[0] = (byte) ((char) items[0] - 'a' + 'A');
        return new String(items);
    }
    
}

原文地址:https://blog.csdn.net/qq_58023907/article/details/142442296

免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!