注解
注解
注解就是给类、属性、方法、参数 加的标记
标记如果没有被读取,则完全没有作用
作用体现在被读取的时候
一、我们的见过的注解
@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");
}
}
浙公网安备 33010602011771号