java中的注解

1、概述
2、内置注解
---2.1Override注解
---2.2Deprecated注解
3、元注解
---3.1关于Target注解
---3.2关于Retention注解
4、注解中定义属性
5、反射注解
6、通过反射获取注解对象属性的值
7、注解在开发中的作用
更多关于注解见:
链接一
链接二

概述

1、注解:Annotation是一种引用数据类型。编译之后也是生成xx.class文件。
2、语法格式为:
[修饰符列表] @interface 注解类型名{}
3、注解怎么使用?
注解使用时的语法格式是:@注解类型名
Annotation可被用于 packages、types(类、接口、枚举、Annotation类型)、类型成员(方法、构造方法、成员变量、枚举值)、方法参数和本地变量(如循环变量、catch参数)。(默认情况下,注解可以出现在任意位置。)
4、例:

@DemoAnno
public class Demo {
    @DemoAnno
    private int no;
    @DemoAnno
    public Demo() {
    }
    @DemoAnno
    private void m(){
        @DemoAnno
        int a = 1;
    }
}

@DemoAnno
interface MyInterface{
}

@DemoAnno
enum S {
    ANN
}
@DemoA
public @interface DemoAnno {
}

5、一些内置注解
Deprecated
注释@Deprecated的程序元素是程序员不鼓励使用的程序元素,通常是因为它是危险的,或者因为存在更好的替代方法。
FunctionalInterface
使用的信息注释类型,以指示在接口类型声明旨在是一个 功能接口由Java语言规范所定义的。
Override
表示方法声明旨在覆盖超类型中的方法声明。
SafeVarargs
程序员断言注释方法或构造函数的正文不会对其varargs参数执行潜在的不安全操作。
SuppressWarnings
表示在注释元素(以及注释元素中包含的所有程序元素)中应该抑制命名的编译器警告。

内置注解

Override注解

1、源代码:
public @interface Override {}
2、是一个标识性注解,给编译器做参考。
方法上有这个注解的时候,编译器会自动检查该方法是否重写了父类的方法。如果没有重写会报错。这个注解只是在编译阶段起作用,和运行期无关。
3、只能注解方法,因为被Target限制了:
@Target(ElementType.METHOD)

Deprecated注解

1、被其标识后,表示被标识的元素已过时,告知程序员已过时,有更好的方案存在。
2、图例(其中过时的方法会加横杠):
在这里插入图片描述
运行后:
在这里插入图片描述
但是会有警告:
在这里插入图片描述

元注解

  • 概述
    1、用来标注“注解类型”的“注解”,称为元注解。
    2、常见元注解:
    @Retention
    @Target
关于Target注解

1、Target注解用来标注“被标注的注解”可以出现在哪些位置上。
2、@Target(ElementType.METHOD)
表示“被标注的注解“只能出现在方法上。

关于Retention注解

1、Retention注解用来标注“被标注的注解”最终保存在哪里。
2、@Retention(RetentionPolicy.SOURCE)
表示该注解只被保留在java源文件中。
@Retention(RetentionPolicy.CLASS)
表示该注解被保存在class文件中
@Retention(RetentionPolicy.RUNTIME)
表示该注解被保存在class文件中,并且可以被反射机制所读取。

注解中定义属性

  • 属性类型
    属性的类型可以是:byte、short、int、long、float、double、boolean、char、string、class、枚举类型,以及它们的每一种的数组形式。
  • 代码示例
public @interface DemoAnno {
    //定义name属性
    String name();
    //定义age属性
    int age();
    //定义性别(指定属性的默认值)
    String sex() default "男";
}
public class Demo {
    /*报错的原因:注解中有属性,没有给属性赋值。
    * (除非该属性使用default指定了默认值)*/
    /*@DemoAnno()
    public void doSome(){ }*/

    //@DemoAnno(属性名=属性值,属性名=属性值...)
    @DemoAnno(name = "zhangsan",age = 1)
    public void doSome(){
        
    }
}
  • 属性是value时可以省略
    1、限制条件:有且只有一个属性名叫value。
    2、代码示例:
public @interface DemoAnno {
    //定义value属性
    String value();
}
public class Demo {

    @DemoAnno(value = "v")
    public void doSome(){
    }

    //省略了“value = ”
    @DemoAnno("vv")
    public void doOther(){
    }
}

3、不止有value一个属性时:

public @interface DemoAnno {
    //定义value属性
    String value();
    //再加一个属性
    String name();
}
public class Demo {

    //此时就不能省略value
    @DemoAnno(value = "v", name = "zhangsan")
    public void doSome(){
    }
}
  • 属性是数组时
public enum Season {
    SPRING, SUMMER, AUTUMN, WINTER
}
public @interface DemoAnno {
    String name();
    String[] hobby();
    //枚举数组
    Season[] seasonArr();
}
public class Demo {

    //数组中只有一个元素时,大括号可以省略
    @DemoAnno(name = "v",
            hobby = "zhangsan",
            seasonArr = Season.SUMMER)
    public void doSome(){
    }

    @DemoAnno(name = "v",
            hobby = {"111@qq.com","222@qq.com"},
            seasonArr = {Season.SPRING, Season.AUTUMN})
    public void doOther(){
    }
}

反射注解

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

//该注解只能标注类、方法
@Target({ElementType.TYPE, ElementType.METHOD})
//该注解可以被反射
@Retention(RetentionPolicy.RUNTIME)
public @interface DemoAnno {
    String value() default "zhangsan";
}
@DemoAnno("lisi")
public class Demo {
    @DemoAnno
    public void doSome(){
        int i;
    }
}
public class DemoTest {
    public static void main(String[] args) throws Exception{
        Class c = Class.forName("Demo");
        /*判断类上面是否有@DemoAnno
        * 输出:true*/
        //System.out.println(c.isAnnotationPresent(DemoAnno.class));
        if (c.isAnnotationPresent(DemoAnno.class)){
            //获取该注解对象
            DemoAnno demoAnno = (DemoAnno)c.getAnnotation(DemoAnno.class);
            System.out.println("类上的注解对象是:"+ demoAnno);
            //获取注解对象的属性
            String s = demoAnno.value();
            System.out.println(s);
        }
    }
}

输出:
在这里插入图片描述

通过反射获取注解对象属性的值

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

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface DemoAnno {
    String username();
    String password();
}
import java.lang.reflect.Method;

public class Demo {
    @DemoAnno(username = "admin", password = "123")
    public void doSome(){
    }

    public static void main(String[] args) throws Exception{
        //获取Demo的doSome()方法上面的注解信息
        Class c = Class.forName("Demo");
        //获取doSome()方法
        Method doSomeMethod = c.getDeclaredMethod("doSome");
        //判断该方法上是否存在这个注解
        if (doSomeMethod.isAnnotationPresent(DemoAnno.class)){
            DemoAnno demoAnno = doSomeMethod.getAnnotation(DemoAnno.class);
            System.out.println(demoAnno.username());
            System.out.println(demoAnno.password());
        }
    }
}

输出:
在这里插入图片描述

注解在开发中的作用

1、假如以这样一个需求:
有一个注解叫:@DemoAnno。这个注解只能出现在类上面,当这个类上有这个注解的时候,要求这个类中必须有一个int类型的id属性。如果没有这个属性就报异常,如果有这个属性则正常执行。
2、代码示例:

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

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface DemoAnno {
}
@DemoAnno()
public class Demo {
    //int id;
    String name;
    String psw;
}
/*自定义异常*/
public class No_Id_Exception extends RuntimeException{
    public No_Id_Exception() {
    }

    public No_Id_Exception(String message) {
        super(message);
    }
}
import java.lang.reflect.Field;

public class DemoTest {
    public static void main(String[] args) throws Exception{
        Class demoClass = Class.forName("Demo");
        //布尔标记
        boolean isOk = false;
        if (demoClass.isAnnotationPresent(DemoAnno.class)){
            /*有注解的话,要求必须存在int类型的id属性*/
            //获取类的属性
            Field[] fields = demoClass.getDeclaredFields();
            for (Field field:fields) {
                if ("id".equals(field.getName())
                        && "int".equals(
                                field.getType().getSimpleName())){
                    //合法
                    isOk = true;
                    break;
                }
            }
            if (!isOk) {
                throw new No_Id_Exception(
                        "没有int类型的id属性");
            }
        }
    }
}

有int id时(无异常):
在这里插入图片描述
没有int id时:
在这里插入图片描述

posted @ 2020-06-27 16:48  YU_UY  阅读(202)  评论(0编辑  收藏  举报