概论
1、注解、注释annotation
2、是一种引用数据类型。编译之后也是xxx.class文件
3、怎么自定义注解,语法
[修饰符列表] @interface 注解类型名{
}
4、注解怎么使用
使用时语法格式: @注解类型名
可以出现在:类上、属性上、方法上、变量上、注解上
5、需要学:Override、Deprecated、Target、Retention
6、元注解:用来标注“注解类型”的注解。例如@Target、@Retention
关于Target注解
这是元注解,用来标注”元注解“
这个注解标注 被标注的注解可以出现在哪些位置
@Target(ElementType.METHOD):表示被标注的注解只能出现在方法
例如:Override 注解
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.SOURCE)
public @interface Override {
}
关于Retention注解
这是元注解,用来标注”元注解“
这个注解标注 被标注的注解保存在什么位置上。
例如:@Retention(RetentionPolicy.SOURCE),则表示保存在源文件中
@Retention(RetentionPolicy.CLASS),则表示保存在class文件中
@Retention(RetentionPolicy.RUNTIME),则表示保存在class文件中,并可以被反射机制读取
@Override
/*
关于Override注解
@Override只能注解方法
这个注解是给编译器参考的,和运行阶段没有关系
凡是带有这个注解的,编译器都会检查,不是重写父类方法,编译器报错
源代码:
public @interface Override {
}
*/
public class AnnotationTest2 {
//@Override 方法写错了,这里会有提醒
public String tostring() {
return "AnnotationTest2{}";
}
}
@Deprecated
//@Deprecated 表示类过时
public class AnnotationTest3 {
public static void main(String[] args) {
AnnotationTest3.doSome();
}
//@Deprecated 表示方法过时
public static void doSome(){
System.out.println("doSome");
}
public static void doOther(){
System.out.println("doOther");
}
}
@Deprecated的源代码:
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(value={CONSTRUCTOR, FIELD, LOCAL_VARIABLE, METHOD, PACKAGE, MODULE, PARAMETER, TYPE})
public @interface Deprecated {
@Target(value={CONSTRUCTOR, FIELD, LOCAL_VARIABLE, METHOD, PACKAGE, MODULE, PARAMETER, TYPE})
//表示可以出现在构造函数、属性、局部变量、方法.......
元注解
@Target,@Retention
自定义
示例1
public @interface MyAnotation {
//称为注解当中的属性,不是方法
//以下是MyAnotation的name属性
String name();
//给属性默认值
int age() default 25;
}
使用自定义注解
import com.javacode.classcode.MyAnotation;
public class MyAnnotationTest {
//直接写@MyAnotation,会报错,原因是:如果注解中有属性,则必须给属性赋值
@MyAnotation(name="zhangsan")//有默认值的可以不写,属性名=属性值的格式
public static void doSome(){
}
}
示例2
public @interface MyAnnotation {
String value();
}
//使用自定义注解2
package com.javacode.annotation2;
public class MyAnnotationTest {
@MyAnnotation(value="1")
public static void doSome(){
}
//没有报错。**因为:如果注解只有一个属性,且属性名是value,可以不写value= 直接写后面的值
@MyAnnotation("1")
public static void doOther(){
}
}
自定义注解的属性
可以是:byte short int long float double boolean char String Class 枚举,以及以上各项的数组形式
反射注解
//只允许这个注解标注类、方法
@Target(value={ElementType.TYPE,ElementType.METHOD})
//希望注解可以被反射
@Retention(RetentionPolicy.RUNTIME)
public @interface MyAnnotation {
}
使用自定义注解
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
package com.javacode.annotation4;
public class MyAnnotationTest {
//@MyAnnotation 无法使用在Field上。如果要使用
//需要将@Target(value={ElementType.TYPE,ElementType.METHOD})
//改为@Target(value={ElementType.TYPE,ElementType.METHOD,ElementType.FIELD})
int i;
//@MyAnnotation 也无法使用
public MyAnnotationTest(int i) {
this.i = i;
}
@MyAnnotation //可以使用
public void doSome(){
}
}
反射机制读取注解
package com.javacode.annotation4;
public class ReflectAnnotationTest {
public static void main(String[] args) throws Exception{
//获取类
Class c=Class.forName("com.javacode.annotation4.MyAnnotationTest");
//判读类上是否有注解
//System.out.println(c.isAnnotationPresent(MyAnnotation.class));
if(c.isAnnotationPresent(MyAnnotation.class)){
MyAnnotation ma=(MyAnnotation) c.getAnnotation(MyAnnotation.class);
System.out.println("类上面的注解对象"+ma);//类上面的注解对象@com.javacode.annotation4.MyAnnotation()
//获取注解对象的属性
String s=ma.value();
System.out.println(s);
}
}
}
获取方法上的注解
改写注解
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
//只允许这个注解标注类、方法
@Target(value={ElementType.TYPE,ElementType.METHOD})
//希望注解可以被反射
@Retention(RetentionPolicy.RUNTIME)
public @interface MyAnnotation {
String value() default "北京";
String username();
String password();
}
使用改写注解
//@MyAnnotation
public class MyAnnotationTest {
//@MyAnnotation 无法使用在Field上。如果要使用
//需要将@Target(value={ElementType.TYPE,ElementType.METHOD})
//改为@Target(value={ElementType.TYPE,ElementType.METHOD,ElementType.FIELD})
int i;
//@MyAnnotation 也无法使用
public MyAnnotationTest(int i) {
this.i = i;
}
@MyAnnotation(username = "asd",password = "123") //可以使用
public void doSome(){
}
}
获取注解
import java.lang.reflect.Method;
public class ReflectAnnotationTest {
public static void main(String[] args) throws Exception{
//获取类
Class c=Class.forName("com.javacode.annotation4.MyAnnotationTest");
//获取doSomoe()方法
Method doSomeMethod=c.getDeclaredMethod("doSome");
if(doSomeMethod.isAnnotationPresent(MyAnnotation.class)){
MyAnnotation ma=(MyAnnotation) doSomeMethod.getAnnotation(MyAnnotation.class);
System.out.println(ma.username());
System.out.println(ma.password());
}
}
}
实际使用
需求:@ID注解,只能出现在类上面,当类上有这个注解的时候。要求类必须有一个int类型的id值
没有这个属性就报异常,有就继续执行
定义注解
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
//元注解的使用
//表示只能出现在类上
@Target(value= ElementType.TYPE)//ID只能用在类和方法上面
//该注解可以被反射机制读取
@Retention(RetentionPolicy.RUNTIME) //RUNTIME写成source说明只保留在Java源文件中不保留在编译生成的.class文件中,写的class说明注解被保留到字节码文件中,RUNTIME说明注解被保留到字节码文件中并可以被反射机制读到
public @interface ID {
}
//这个注解@ID用来标注类,被标注的类必须有一个int类型的ID
使用注解的类
@ID
public class User {
//@ID
//int ID;//会报错,因为ID不能用在属性
String name;
}
定义异常
public class NotHasIDPRopertyException extends RuntimeException{
public NotHasIDPRopertyException() {
}
public NotHasIDPRopertyException(String message) {
super(message);
}
}
测试
import java.lang.reflect.Field;
public class Test {
public static void main(String[] args) throws Exception{
Class userClass=Class.forName("com.javacode.annotation5.User");
//判断类上是否存在ID注解
boolean islegal=false;//给个默认标记
if(userClass.isAnnotationPresent(ID.class)){
//当一个类上面有ID注解的时候,要求类中存在int类型的ID属性。如果没有则报异常
Field[] fields=userClass.getDeclaredFields();
for(Field f:fields){
if("ID".equals(f.getName())&&"int".equals(f.getType().getSimpleName())){
//表示合法
islegal=true;
System.out.println("合法");
break;
}
}
//判断是否合法
if(!islegal){
throw new NotHasIDPRopertyException("被@ID注解标注的类必须有int类型ID属性");
}
}
}
}
输出:
Exception in thread “main” com.javacode.annotation5.NotHasIDPRopertyException: 被@ID注解标注的类必须有int类型ID属性
at com.javacode.annotation5.Test.main(Test.java:23)
总结:
注解作用:做参考作用,相当于一种标记“有这个注解怎么办,没有注解怎么办”