一.什么是注解,注解作用
注解就是符合一定格式的语法 @xxxx
如:
-
@override
:重写父类的方法 -
@Test
:测试模块 -
@webServlet
:代替web.xml的文件内容
注解作用:可以代替配置文件
注解:主要是给JVM查看,具有一定的功能作用。注解是给程序员进行提示使用。
关于配置文件与注解开发的优缺点:
- 优点:开发效率高,成本低。
- 缺点:耦合性大并且不利于后期维护。
例如我们在使用@webServlet
的时候,会在源代码中修改文件的路径位置。然而web.xml
就不要使用编译器打开源码进行修改。我们只需要打开响应xml文件即可。
二.JDK5提供的注解
-
@Override
:告知编译器此方法是覆盖父类的。如果方法名或方法未实现会报错 -
@Deprecated
:标注过时 -
@SuppressWarnings
:压制警告,可以压制不加泛型,或者压制未使用。或者@SuppressWarnings(“all”)
,表示压制所有。
不同的注解只能在不同的位置使用(方法上、字段上、类上)
三.自定义注解
需要掌握三个方面的内容,
- 编写一个自定义的注解
- 使用注解
- 解析注解——使用反射知识
3.1如何编写一个自定义的注解
- 关键字:
@interface
- 注解的属性的写法:
返回值 名称()
;
注意:如果属性的名字是value,并且注解的属性值有一个,那么在使用注解时可以省略value
- 注解属性类型只能是以下几种
1.基本类型
2.String
3.枚举类型
4.注解类型
5.Class类型
6.以上类型的一维数组类型
案例:
public @interface first{
//String name();
//int age default 28;
String [] value()//使用注解的话只需要书写@first("a","b")即可
}
3.2使用注解
创建一个类,或者方法,或者一个字段上
案例:
当注解中使用String name(),我们需要在此使用第一个注解
@first(name ="张三")//————————第一个注解
当注解中使用String [] value(),我们可以省略他的属性名称
@first({"a","b","c"})//——————第二个注解
public void show(){
}
3.3解析使用了注解的类
我们查看注解的源码会发现注解上面仍有注解,以下为注解的源码。以此引入元注解的概念
元注解:代表修饰注解的注解,作用:限制定义的注解的特性
- @Retention
- SOURCE: 注解在源码级别可见
- CLASS:注解在字节码文件级别可见
- RUNTIME:注解在整个运行阶段都可见
- @Target
代表注解修饰的范围:类上使用,方法上使用,字段上使用
- FIELD:字段上可用此注解
- METHOD:方法上可以用此注解
- TYPE:类/接口上可以使用此注解
所以,我们
注意:要想解析使用了注解的类 , 那么该注解的Retention必须设置成Runtime
案例:(目的是解析注解)
第一步:先自己写一个注解
@Target({ElementType.METHOD,ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME) //必须设置到Runtime级别,才能进行获取
public @interface MyAnno {
//注解的属性
String name();
int age() default 28;
}
第二步:使用自己书写的注解
@MyAnno(name = "zhangsan")//在类上使用
public class MyAnnoTest {
@SuppressWarnings("all")
@MyAnno(name = "zhangsan")//在方法中使用
public void show(String str){
System.out.println("show running...");
}
}
第三步:做测试解析自己的注解
public class MyAnnoParser {
public static void main(String[] args) throws NoSuchMethodException, SecurityException {
//解析show方法上面的@MyAnno
//直接的目的是 获得show方法上的@MyAnno中的参数
//获得show方法的字节码对象
Class clazz = MyAnnoTest.class;
Method method = clazz.getMethod("show", String.class);
//获得show方法上的@MyAnno
MyAnno annotation = method.getAnnotation(MyAnno.class);
//获得@MyAnno上的属性值
System.out.println(annotation.name());//zhangsan
System.out.println(annotation.age());//28
//根据业务需求写逻辑代码
//若需要获得多个注解的方法
Method[] methods= clazz.getMethods();
if(methods!=null){
//获得注解使用了@xxx的方法
for(Method method:methods){
//判断该方法是否使用了某注解的方法
boolean anotationPresent = method.isAnnotationPresent(MyAnno.class);
if(anotationPresent){
//该方法使用MyTest注解
method.invoke(clazz.newInstance(),null)//输入的参数
}
}
}
}
}