Java注解
- 概念:说明程序的,给计算机看的
- 注释:用文字去描述程序,给程序员看。
- 概念描述:注解JDK1.5之后的新特性,与类、接口、枚举是在同一个层次。
- 作用分类:
- 编写文档:通过代码里的标识的注解生成的文档【生成doc文档】
- 代码分析:通过代码里的标识的注解对代码进行分析【使用反射】
- 编译检查:通过代码里的标识的注解让编译器能过实现基本的编译检查【Override】
//1.编写文档 在类的前面注解,或者在方法前面注解,可以自动生成API
/**
*
* @param a 整数
* @param b 整数
* @return 两数的和
*
*/
public int add(int a,int b)
{
return a+b;
}
- JDK中预定义的一些注解
- @ Override:检测被该注解标注的方法是否是继承自父类(接口)
- @Deprecated:该注解标注的内容,表示已经过时
- @SuppressWarnings:压制警告
@SuppressWarnings("all") //压制所有的警告
public class AnnoDemo2 {
@Override
public String toString() //检测是否继承自父类,如果没有注解@Override会报错。例如:toString()写成了toString1()
{
return super.toString();
}
@Deprecated //方法会被打上横杠表示废弃
public void show1()
{
//有缺陷
}
public void show2()
{
//新方法
}
}
-
自定义注解
Ⅰ格式:
元注解
public @interface 注解名称()
Ⅱ本质:注解本质上就是一个接口,该接口默认继承Annotation接口
public interface Anno extend java.lang.annotation.Annotation{}
Ⅲ属性:接口中抽象方法
1.属性的返回值类型
- 基本数据类型
- String
- 枚举
- 注解
public @interface Anno {
String show1(); //属性show1 字符串类型
int show();
Person per();
Anno2 anno2(); //属性类型为Anno2注解
String [] str();
}
2.需要给属性赋值
- 如果定义属性时,使用default关键字给属性默认初始化值,使用注解时,自动使用默认值
- 如果只有一个属性需要赋值,并且属性的名称是value+,并且只有一个属性value,可以省略名字
- 数组赋值时,值使用()包裹,如果数组中只有一个值,则{ }省略
@Anno(show = 12,per = Person.p1,show1 = "12312",anno2 = @Anno2,str = {"21323","123","123"})
public int add(int a,int b)
{
return a+b;
}
Ⅳ元注解:用于描述注解的注解
@Target:描述注解能够作用的位置
ElementType取值:
*TYPE:可以作用于类上
*METHOD:可以作用于方法上
*FIELD:可以作用于成员变量上
@Retention:描述注解能被保留的位置
*@Retention(RetentionPolicy.RUNTIME):当前被描述的注解,会保留class字节码文件中,并被JVM读取到。
RetentionPolicy.CLASS——>会被保留在class字节码文件中,但不会被JVM读取到
RetrntionPolicy.SOURCE——>不会保留在class字节码文件中
@Documented:描述注解是否能被抽取到API文档中
@Inherited:描述注解是否被子类继承
@Target(value ={ElementType.TYPE,ElementType.METHOD, ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
@Documented()
@Inherited()
public @interface Anno3 {
}
- 在程序中使用(解析)注解:获取注解中定义的属性值
- 获取注解定义的位置的对象(Class,Method,Field)
- 获取指定注解
- 调用注解中的抽象方法获取配置属性值
小案例:
需求:
- 新建一个Person类,定义一个anno注解
- 在AnnoTest类中获取注解
- 使用反射创建对象,使用Person类里面的方法
Person类
package com.cwstd.domain;
public class Person {
private String name;
private String password;
private void eat()
{
System.out.println("eat.....");
}
}
anno注解类
package com.cwstd.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target(value = {ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface anno {
String className();//注解中两个属性类名和方法名
String methodName();
}
AnnoTest测试类
package com.cwstd.reflect;
import com.cwstd.annotation.anno;
import com.cwstd.domain.Person;
import java.lang.reflect.Method;
@anno(className = "com.cwstd.domain.Student",methodName = "study")
public class AnnoTest {
public static void main(String[] args) throws Exception {
//解析注解
//获取类的字节码文件对象
Class<AnnoTest> annoTestClass=AnnoTest.class;
//获取上边的注解对象
//其实就是在内存中生成了一个该注解接口的子类实现对象
anno a=annoTestClass.getAnnotation(anno.class);
//调用注解对象中定义的抽象方法,获取返回值
String className=a.className();
String methodName=a.methodName();
Class cla=Class.forName(className);
Object obj=cla.newInstance();
Method method=cla.getDeclaredMethod(methodName);
method.setAccessible(true);
method.invoke(obj);
}
}