一、注解概述
注解(Annotation)作为元数据,相当于一种特殊的标记,可以被添加到源代码中,用于类、属性、方法,不会直接影响程序的进程,但可用简化代码,降低耦合度。
二、基本注解
基本注解是由jdk提供的,一共5个。
1、@Override
该注解用于子类的方法,表示重写了父类或接口的方法,若在子类在方法名出错,则idea在编译时会报错。(父类的静态方法不能被重写)
package com.etime01;
//父类
public class Father {
public void test(){
System.out.println("father:hello");
}
}
package com.etime01;
//子类继承了父类
public class Son extends Father {
//父类方法的重写
@Override
public void test(){
System.out.println("son:hello");
}
}
2、@Deprecated
该注解表示不建议使用,若类或方法加上该注解,那么该类和方法就不再建议使用,在调用时会出现删除线,但也可以使用,只是已过时,有更好的方法。
@Deprecated
public static void test2(){
System.out.println("test2");
}
3、@SuppressWarnings
该注解用于关闭编译器对类、方法、成员变量、变量初始化的警告。
4、@SafeVarargs
该注解用于处理可变长参数中的泛型
5、@FunctionalInterface
该注解用于指定接口是函数式接口。
三、元注解
元注解是用于标记注解的。
1、@Target
@Target用于被标记注解的目标对象,即被标记注解所适用的对象。
2、@Retention
@Retention表示被标记的注解可以保留至哪个阶段,Java文件从生成到运行需要经历三个阶段,java源文件、.class文件、JVM运行阶段。
@Retention(RetentionPolicy.SOURCE ):保留至源码阶段,编译时丢弃;
@Retention(RetentionPolicy.CLASS ):保留至编译阶段,但不会被加载到JVM中;
@Retention(RetentionPolicy.RUNTIME ):保留至程序运行阶段,会被加载到JVM中。
3、@Inherited
@Inherited用于注释类型的自动继承,如果某个注解用了@Inherited标记,那么用了该注解类的子类也自动具有该注解。
4、@Documented
@Documented表示在生成javadoc文档时,把被标记的注解也写进帮助文档。
四、自定义注解
自定义注解的三大步骤:定义注解、使用注解、解析注解
注解可用于类、属性、方法,这里以注解实现计算器功能为例。
1、定义注解
**
* 计算机操作注解定义
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface Annotation {
public String oper();
}
2、使用注解
给操作接口的加、减、乘、除实现类添加自定义注解
public interface Operation {
double operation(double a, double b);
@Annotation(oper = "+")
public class AddImpl implements Operation {
@Override
public double operation(double a, double b) {
return a+b;
}
}
@Annotation(oper = "-")
public class SubImpl implements Operation {
@Override
public double operation(double a, double b) {
return a-b;
}
}
@Annotation(oper = "*")
public class MulImpl implements Operation {
@Override
public double operation(double a, double b) {
return a*b;
}
}
@Annotation(oper = "/")
public class DivImpl implements Operation {
@Override
public double operation(double a, double b) {
return a/b;
}
}
3、解析注解
这里解析注解时,需要先找到同一个包下的被注解标记的类,所以先导入了一个依赖包,通过maven的pom.xml文件配置。
<dependencies>
<dependency>
<groupId>org.reflections</groupId>
<artifactId>reflections</artifactId>
<version>0.9.11</version>
</dependency>
</dependencies>
public static Double cal(double a,double b,String oper) throws IllegalAccessException, InstantiationException, InvocationTargetException {
//通过包下任意一个类获取class对象
Class<Test> testClass = Test.class;
//通过class对象获取包名
String packageName = testClass.getPackage().getName();
//这里导入了一个依赖包,通过包名获取的一个类
Reflections ref = new Reflections(packageName);
//通过反射获取同一个包下的所有被注解标记的类的class对象
Set<Class<?>> set = ref.getTypesAnnotatedWith(Annotation.class);
Double rtn =null;
for (Class<?> c : set) {
//获取注解
Annotation annotation = c.getAnnotation(Annotation.class);
//通过比较注解的oper与传入的oper是否相等,来找到所需要的class对象
if (annotation.oper().equals(oper)) {
//通过class对象创建实现类实例
Object obj = c.newInstance();
//通过class对象获取实现类的方法
Method[] method = c.getMethods();
//实现类只有一个方法,通过method[0].invoke调用计算方法
rtn = (Double) method[0].invoke(obj, a, b);
}
}
return rtn;
}
4、测试
public class Test {
public static void main(String[] args) throws IllegalAccessException, InvocationTargetException, InstantiationException {
Double cal = cal(1.2, 2.3, "-");
System.out.println(cal);
}
测试结果
该文章为学习记录文章,参考了许多其他文章,如有不正之处请指教。