注解

注解

注解就是给类、属性、方法、参数 加的标记

标记如果没有被读取,则完全没有作用

作用体现在被读取的时候

一、我们的见过的注解

@Override

被这个注解标记的方法必须满足方法重写的语法,如果不满足则编译错误

二、自定义注解

修饰符 @interface 注解名{
	...
}

1.指定注解的特征

这个注解能标记什么

这个注解的生命周期

这个注解能被继承吗

这个注解能被生成到文档

声明的方式:使用元注解

元注解:

标记注解的注解  

2.声明注解的属性

可以为注解声明属性。

没有属性的注解相当于空白标签

有了属性的注解相当于有内容的标签

数据类型 属性名();

注意:
1.如果给注解声明了属性
则在使用注解的时候必须给属性赋值

2.输入属性名为value
则在使用该注解时,为该属性赋值的时候可以省略属性名

3.使用注解

元注解:

@Target : 指定自定义注解能标记什么
属性: ElementType.Type 表示能标记类
ElementType.Method 表示能标记方法
ElementType.Field 表示能标记属性
ElementType.Parameter 表示能标记方法参数
@Retention : 指定自定义注解的生命周期
属性: RetentionPolicy.SOURCE 表示生命周期只在编译期有效
RetentionPolicy.RUNTIME 表示生命周期持续到运行期
@Inherited : 指定自定义注解可以被继承
@Documented : 指定自定义注解可以被生成到文档中

@注解名(属性名 = 值)
package com.qianfeng.annotationDemo;

import java.lang.annotation.*;

/*
元注解:
    @Target  :  指定自定义注解能标记什么
        属性: ElementType.Type    表示能标记类
              ElementType.Method   表示能标记方法
              ElementType.Field     表示能标记属性
              ElementType.Parameter  表示能标记方法参数
    @Retention : 指定自定义注解的生命周期
        属性: RetentionPolicy.SOURCE   表示生命周期只在编译期有效
               RetentionPolicy.RUNTIME  表示生命周期持续到运行期
    @Inherited : 指定自定义注解可以被继承
    @Documented : 指定自定义注解可以被生成到文档中
 */


@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@Documented
public @interface MyAnnotation {
    /*
    声明注解的属性
    属性可以有默认值,如果没有为该属性指定值,则使用默认值
     */
    String name() default "";
    String value() default "";
}
package com.qianfeng.annotationDemo;

@MyAnnotation(name = "jay")
public class Demo1 {

    /*
    使用MyAnnotation注解
    为value属性赋值(没有指定属性名时,则默认赋值的就是value属性)
     */
    @MyAnnotation("aaa")
    public void test(){

    }
}

4.读取注解

boolean 反射对象.isAnnotationPresent(注解的类对象):判断当前反射对象是否被指定的注解标记

反射对象.getAnnotation(注解的类对象):取出标记该反射对象的注解对象

注解对象.属性名():取出注解对象的属性值

package com.qianfeng.annotationDemo;

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 InvokeCount {
    int value();
}
package com.qianfeng.annotationDemo;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

public class Main {
    public static void main(String[] args) throws IllegalAccessException, InstantiationException, InvocationTargetException {
        /*
        读取Demo2类中每一个方法,
        判断每一个方法是否有InvokeCount的注解
        如果有:
            则执行该方法,执行注解的属性那么多次
         如果没有:
            不处理
         */
        //1.获取Demo2的类对象
        Class<Demo2> clazz = Demo2.class;

        Demo2 demo2 = clazz.newInstance();

        //2.获取该类对象的所有方法对象
        Method[] methods = clazz.getDeclaredMethods();
        //3.取出每一个方法对象
        for (Method m : methods) {
            //4. 判断该方法是否被InvokeCount注解修饰
            if(m.isAnnotationPresent(InvokeCount.class)){//表示被该注解标记了
                //5.取出标记的注解对象
                InvokeCount ic = m.getAnnotation(InvokeCount.class);
                //6.取出注解的属性
                int count = ic.value();
                for (int i = 0; i < count; i++) {
                    m.invoke(demo2);
                }


            }
        }

    }
}
package com.qianfeng.annotationDemo;


public class Demo2 {
    /*
    被@InvokeCount修饰的方法,自动的被调用
    被调用的次数与这个注解的属性值一致
     */
    @InvokeCount(3)
    public void test1(){
        System.out.println("test1");
    }
    @InvokeCount(4)
    public void test2(){
        System.out.println("test2");
    }
    @InvokeCount(5)
    public void test3(){
        System.out.println("test3");
    }
    @InvokeCount(6)
    public void test4(){
        System.out.println("test4");
    }
    @InvokeCount(7)
    public void test5(){
        System.out.println("test5");
    }
}

三、练习

使用properties配置类的全路径名

读取到全路径名名,然后找到该类中使用@invoke注解修饰的方法,并执行

package com.qianfeng.annotationDemo;

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

}
package com.qianfeng.annotationDemo;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.lang.reflect.Method;
import java.util.Properties;

public class Pratise {
    public static void main(String[] args) throws Exception {
        //1.读取类的全路径名
        Properties properties = new Properties();
        properties.load(new FileInputStream("classInfo.properties"));

        //2.取出类的全路径名
        String classname = properties.getProperty("classname");
        //3.获取类对象
        Class<Demo3> clazz = (Class<Demo3>) Class.forName(classname);
        //4.创建Demo3对象
        Demo3 demo3 = clazz.newInstance();
        //5.获取类对象的所有方法对象
        Method[] methods = clazz.getDeclaredMethods();
        //6.取出每一个方法对象
        for (Method m : methods) {
            //7.判断当前方法对象是否被Invoke注解修饰
            if(m.isAnnotationPresent(Invoke.class)){
                //如果被修饰了
                //8.执行当前方法
                m.invoke(demo3);
            }
        }

    }
}
package com.qianfeng.annotationDemo;

public class Demo3 {
    public void test1(){
        System.out.println("test1");
    }
    @Invoke
    public void test2(){
        System.out.println("test2");
    }
    public void test3(){
        System.out.println("test3");
    }
    @Invoke
    public void test4(){
        System.out.println("test4");
    }
}
posted @ 2022-06-30 00:21  snail05  阅读(31)  评论(0)    收藏  举报