todo Java注解

概论

1、注解、注释annotation
2、是一种引用数据类型。编译之后也是xxx.class文件
3、怎么自定义注解,语法
[修饰符列表] @interface 注解类型名{

}
4、注解怎么使用
使用时语法格式: @注解类型名
可以出现在:类上、属性上、方法上、变量上、注解上
5、需要学:Override、Deprecated、Target、Retention
6、元注解:用来标注“注解类型”的注解。例如@Target、@Retention
关于Target注解
这是元注解,用来标注”元注解“
这个注解标注 被标注的注解可以出现在哪些位置
@Target(ElementType.METHOD):表示被标注的注解只能出现在方法
例如:Override 注解
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.SOURCE)
public @interface Override {
}
关于Retention注解
这是元注解,用来标注”元注解“
这个注解标注 被标注的注解保存在什么位置上。
例如:@Retention(RetentionPolicy.SOURCE),则表示保存在源文件中
@Retention(RetentionPolicy.CLASS),则表示保存在class文件中
@Retention(RetentionPolicy.RUNTIME),则表示保存在class文件中,并可以被反射机制读取

@Override

/*
关于Override注解
    @Override只能注解方法
    这个注解是给编译器参考的,和运行阶段没有关系
    凡是带有这个注解的,编译器都会检查,不是重写父类方法,编译器报错
源代码:
    public @interface Override {
    }
 */

public class AnnotationTest2 {

    //@Override 方法写错了,这里会有提醒
    public String tostring() {
        return "AnnotationTest2{}";
    }
}

@Deprecated

//@Deprecated 表示类过时
public class AnnotationTest3 {
    public static void main(String[] args) {
        AnnotationTest3.doSome();
    }

    //@Deprecated 表示方法过时
    public static void doSome(){
        System.out.println("doSome");
    }
    public static void doOther(){
        System.out.println("doOther");
    }
}

@Deprecated的源代码:

@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(value={CONSTRUCTOR, FIELD, LOCAL_VARIABLE, METHOD, PACKAGE, MODULE, PARAMETER, TYPE})
public @interface Deprecated {
@Target(value={CONSTRUCTOR, FIELD, LOCAL_VARIABLE, METHOD, PACKAGE, MODULE, PARAMETER, TYPE})
//表示可以出现在构造函数、属性、局部变量、方法.......

元注解

@Target,@Retention

自定义

示例1

public @interface MyAnotation {
    //称为注解当中的属性,不是方法
    //以下是MyAnotation的name属性
    String name();
    //给属性默认值
    int age() default 25;
}
使用自定义注解
import com.javacode.classcode.MyAnotation;

public class MyAnnotationTest {
    //直接写@MyAnotation,会报错,原因是:如果注解中有属性,则必须给属性赋值
    @MyAnotation(name="zhangsan")//有默认值的可以不写,属性名=属性值的格式
    public static void doSome(){
    }
}

示例2

public @interface MyAnnotation {
    String value();
}

//使用自定义注解2

package com.javacode.annotation2;

public class MyAnnotationTest {
    @MyAnnotation(value="1")
    public static void doSome(){
        
    }

    //没有报错。**因为:如果注解只有一个属性,且属性名是value,可以不写value= 直接写后面的值
    @MyAnnotation("1")
    public static void doOther(){

    }
}

自定义注解的属性

可以是:byte short int long float double boolean char String Class 枚举,以及以上各项的数组形式

反射注解

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

使用自定义注解

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
package com.javacode.annotation4;

public class MyAnnotationTest {
    //@MyAnnotation 无法使用在Field上。如果要使用
    //需要将@Target(value={ElementType.TYPE,ElementType.METHOD})
    //改为@Target(value={ElementType.TYPE,ElementType.METHOD,ElementType.FIELD})
    int i;

    //@MyAnnotation  也无法使用
    public MyAnnotationTest(int i) {
        this.i = i;
    }

    @MyAnnotation //可以使用
    public void doSome(){

    }
}

反射机制读取注解

package com.javacode.annotation4;

public class ReflectAnnotationTest {
    public static void main(String[] args) throws Exception{
        //获取类
        Class c=Class.forName("com.javacode.annotation4.MyAnnotationTest");
        //判读类上是否有注解
        //System.out.println(c.isAnnotationPresent(MyAnnotation.class));
        if(c.isAnnotationPresent(MyAnnotation.class)){
            MyAnnotation ma=(MyAnnotation) c.getAnnotation(MyAnnotation.class);
            System.out.println("类上面的注解对象"+ma);//类上面的注解对象@com.javacode.annotation4.MyAnnotation()
            //获取注解对象的属性
            String s=ma.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(value={ElementType.TYPE,ElementType.METHOD})
//希望注解可以被反射
@Retention(RetentionPolicy.RUNTIME)
public @interface MyAnnotation {
    String value() default "北京";
    String username();
    String password();
}

使用改写注解

//@MyAnnotation
public class MyAnnotationTest {
    //@MyAnnotation 无法使用在Field上。如果要使用
    //需要将@Target(value={ElementType.TYPE,ElementType.METHOD})
    //改为@Target(value={ElementType.TYPE,ElementType.METHOD,ElementType.FIELD})
    int i;

    //@MyAnnotation  也无法使用
    public MyAnnotationTest(int i) {
        this.i = i;
    }

    @MyAnnotation(username = "asd",password = "123") //可以使用
    public void doSome(){

    }

}

获取注解

import java.lang.reflect.Method;

public class ReflectAnnotationTest {
    public static void main(String[] args) throws Exception{
        //获取类
        Class c=Class.forName("com.javacode.annotation4.MyAnnotationTest");
        //获取doSomoe()方法
        Method doSomeMethod=c.getDeclaredMethod("doSome");
        if(doSomeMethod.isAnnotationPresent(MyAnnotation.class)){
            MyAnnotation ma=(MyAnnotation) doSomeMethod.getAnnotation(MyAnnotation.class);
            System.out.println(ma.username());
            System.out.println(ma.password());
        }
    }
}

实际使用

需求:@ID注解,只能出现在类上面,当类上有这个注解的时候。要求类必须有一个int类型的id值
没有这个属性就报异常,有就继续执行

定义注解

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

//元注解的使用
//表示只能出现在类上
@Target(value= ElementType.TYPE)//ID只能用在类和方法上面
//该注解可以被反射机制读取
@Retention(RetentionPolicy.RUNTIME) //RUNTIME写成source说明只保留在Java源文件中不保留在编译生成的.class文件中,写的class说明注解被保留到字节码文件中,RUNTIME说明注解被保留到字节码文件中并可以被反射机制读到
public @interface ID {
}
//这个注解@ID用来标注类,被标注的类必须有一个int类型的ID

使用注解的类

@ID
public class User {
	//@ID 
    //int ID;//会报错,因为ID不能用在属性
    String name;

}

定义异常

public class NotHasIDPRopertyException extends RuntimeException{
    public NotHasIDPRopertyException() {
    }

    public NotHasIDPRopertyException(String message) {
        super(message);
    }
}

测试

import java.lang.reflect.Field;

public class Test {
    public static void main(String[] args) throws Exception{
        Class userClass=Class.forName("com.javacode.annotation5.User");
        //判断类上是否存在ID注解
        boolean islegal=false;//给个默认标记
        if(userClass.isAnnotationPresent(ID.class)){
            //当一个类上面有ID注解的时候,要求类中存在int类型的ID属性。如果没有则报异常
            Field[] fields=userClass.getDeclaredFields();
            for(Field f:fields){
                if("ID".equals(f.getName())&&"int".equals(f.getType().getSimpleName())){
                    //表示合法
                    islegal=true;
                    System.out.println("合法");
                    break;
                }
            }
            //判断是否合法
            if(!islegal){
                throw new NotHasIDPRopertyException("被@ID注解标注的类必须有int类型ID属性");
            }
        }
    }
}

输出:
Exception in thread “main” com.javacode.annotation5.NotHasIDPRopertyException: 被@ID注解标注的类必须有int类型ID属性
at com.javacode.annotation5.Test.main(Test.java:23)

总结:
注解作用:做参考作用,相当于一种标记“有这个注解怎么办,没有注解怎么办”

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值