Java进阶第十一章(完结)——注解

发布时间:2024年01月24日

注解

1.注解概念

  • 注解:是一种注释类型。英文单词AnnotationTest。是一种引用数据类型,编译后生成也xxx.class文件。

  • 自定义注解语法格式:

    [修饰符列表] @interface 注解类型名{ }

  • 注解使用语法格式:@ 注解类型名

  • 注解可以出现在类上、属性上、方法上、变量上……

public @interface MyAnnotation {  }
//注解或者叫注释
@MyAnnotation
public class AnnotationTest01 {
    @MyAnnotation
    private int no;
    @MyAnnotation
    public AnnotationTest01(){ }
    @MyAnnotation
    public AnnotationTest01(@MyAnnotation int no){
        @MyAnnotation
        int i = 100;
    }
}
@MyAnnotation
interface MyInterface{   }
@MyAnnotation
enum  Season{
    SPRING,SUM,FALL,WINTER
}
@MyAnnotation
public @interface OtherAnnotation {  }

2.Override注解

  • JDK的lang包下的Override注解

    源代码:public @interfoace Override{ }

  • 这个注解只能注解方法,这个注解是给编译器参考的,和运行阶段没有关系。

  • 带有@Override注解的方法,编译器会进行编译检查,如果不是重写父类方法编译器报错。

public class AnnotationTest {
    @Override  //这里是重写父类的toString方法,可以标记
    public String toString(){
        return "toString";
    }
    
    //@Override不是重写父类方法,这里报错
    public String tostring(){
        return "toString";
    }
}

3.元注解

  • 用来标注“注解类型”的注解,称为元注解。

  • 常用的元注解:

    @Target:用来标注“注解类型”的注解,用来标注被标注的注解可以出现在哪些位置上。

    @Target(ElementType.METHOD)
    //这句表示这个注解类型只能出现在方法上
    @Target(value={FIELD,METHOD,……})
    //这句表示这个注解可以出现在属性、方法……
    

    @Retention:用来标注“注解类型”的注解,用来标注被标注的注解最终保存哎哪里。

    @Retention(RetentionPolicy.SOURCE)//表示该注解只被保留在java源文件中
    @Retention(RetentionPolicy.CLASS)//表示该注解只被保留在class文件中
    @Retention(RetentionPolicy.RUNTIME)//表示该注解只被保留在class文件中,并且可以被反射机制所读取
    

4.Deprecated注解

  • @Deprecated注解标注的元素已过时,向其他程序员传达已过时,有更好的解决方案。
@Deprecated//表示这个类已过时
public class AnnotationTest02 {
    public static void main(String[] args) {
        
    }
    @Deprecated
    public void doSome(){
        System.out.println("do something...");
    }
    @Deprecated
    public static void doOther(){
        System.out.println("do other...");
    }
}

class T {
    public static void main(String[] args) {
        AnnotationTest02 at = new AnnotationTest02();//在编译器中这里会出现一个横线
        at.doSome();  //在编译器中这里会出现一个横线
        //在运行时,会出现一个警告,提醒作用。
    }
}

5.注解中的属性

  • 通常在注解当中可以定义属性,看着像一个方法,实际上称之为属性。
public @interface MyAnnotation {
    /**
     * 以下是MyAnnotation的name属性
     * @return
     */
    String name();

    /*
    颜色属性
     */
    String color();

    /*
    年龄属性
     */
    int age() default 25; //属性指定默认值,指定默认值后使用该注解可以不写
}
public class MyAnnotationTest {
    //@MyAnnotation如果一个注解当中有属性,必须给属性赋值
    //@MyAnnotation(属性名=属性值,属性名=属性值……)
    @MyAnnotation(name="coffee",color = "黄色")
    public void doSome(){
    }
}
  • value属性:如果注解中是value属性,且只有value属性时,在使用时可以直接写值不需要写属性名。
public @interface MyAnnotation {
    String value();
    //注解属性可以是基本数据类型、String、Class、枚举类型
    //以及以上类型的数组
}
public class MyAnnotationTest {
    @MyAnnotation("coffee")//属性是value值,可以不用写属性名
    public void doSome(){
    }
}
  • 注解属性可以是基本数据类型、String、Class、枚举类型、以及以上类型的数组

  • 属性作为数组,使用时需要大括号括起来,只有一个时可以省略大括号。

public enum Season {
    SPIRING,SUMMER,FALL,WINTER
}
public @interface OtherAnnotation {
    int age();
    String[] email();
    Season[] season();
}
public class OtherAnnotationTest {
    //数组是大括号
    @OtherAnnotation(age = 23,email = {"123456@123.com","icecoffee.@123.com"},season = {Season.SPIRING,Season.SUMMER})
    public void doSome(){  }
    //数组中只有一个元素,大括号可以省略
    @OtherAnnotation(age = 23,email = "123456@123.com",season = Season.SPIRING)
    public void doOther(){  }
}

6.反射注解

//只允许该注解可以标注类、方法
@Target({ElementType.TYPE,ElementType.METHOD})
//希望这个注解可以被反射RUNTIME
@Retention(RetentionPolicy.RUNTIME)
public @interface MyAnnotation {
    String value() default "咖啡";
}

@MyAnnotation
public class MyAnnotationTest {
    int i;
    public MyAnnotationTest(){  }
    @MyAnnotation
    public void doSome(){
        int i;
    }
}

package annotation3;

public class ReflectAnnotationTest {
    public static void main(String[] args) throws Exception {
        //获取这个类
        Class c = Class.forName("annotation3.MyAnnotationTest");
        //判断类上是否有@MyAnnotation这个注解
        //如果注解上元注解@Retention(RetentionPolicy.RUNTIME)的属性不是RUNTIME,则反射不到,这里为false 		  
         System.out.println(c.isAnnotationPresent(MyAnnotation.class));  //true
        if(c.isAnnotationPresent(MyAnnotation.class)){
            //获取该注解对象
            MyAnnotation myAnnotation = (MyAnnotation)c.getAnnotation(MyAnnotation.class);
            System.out.println("类上面的注解对象" + myAnnotation);  //类上面的注解对象@annotation3.MyAnnotation(value=咖啡)
            //获取注解属性
            System.out.println(myAnnotation.value());//咖啡
        }

        //判断String类上是否有这个注解
        Class c2 = Class.forName("java.lang.String");
        System.out.println(c2.isAnnotationPresent(MyAnnotation.class));//false
    }
}

7.注解作用

  • 注解在程序当中等同于一种标记,给程序员参考的作用。

  • 练习:编写一个需求,一个类被@Id注解标记需要有一个int类型的id属性,如果没有抛出异常。

//编写一个@Id注解
//表示这个注解只能在类上面
@Target(ElementType.TYPE)
//表示这个注解可以被反射
@Retention(RetentionPolicy.RUNTIME)
public @interface Id {
}

//编写一个User类
@Id
public class User {
    int id; //这个如果不在抛出异常,在运行正常
    String name;
    String password;

}

//自定义一个异常,用来抛出没有int类型的id属性异常
//自定义异常
public class HasNotIdPropertyException extends RuntimeException{
    public HasNotIdPropertyException(){ }
    public HasNotIdPropertyException(String s){
        super(s);
    }
}

public class Test {
    public static void main(String[] args) throws Exception{
        //获取类
        Class userClass = Class.forName("Test.User");
        //判断类上是否有@Id注解
        if(userClass.isAnnotationPresent(Id.class)){
            //当一个类上有@Id注解时,要求必须存在int类型属性
            //如果没有int类型属性报异常
            Field[] fields = userClass.getDeclaredFields();
            //一个默认标记是否有int属性的id
            boolean isOK = false;
            for (Field field:
                 fields) {
                //判断是否有一个int类型的id,如果有修改标记
                if("id".equals(field.getName()) && "int".equals(field.getType().getSimpleName())){
                    isOK = true;
                    break;
                }
            }
            //如果没有int类型的id,抛出异常
            if(!isOK){
                throw new HasNotIdPropertyException("被@Id注解标注的类中必须有一个int类型的id属性");
            }
        }
    }
}

——本章节为个人学习笔记。学习视频为动力节点Java零基础教程视频:动力节点—JAVA零基础教程视频

文章来源:https://blog.csdn.net/weixin_46016581/article/details/135818891
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。