1.自定义注解
/*
自定义注解:MyAnnotation
*/
public @interface MyAnnotation {
// ??????
}
2.注解修饰注解
// 注解修饰注解。
@MyAnnotation
public @interface OtherAnnotation {
}
3.注解出现位置
// 默认情况下,注解可以出现在任意位置。
@MyAnnotation
public class AnnotationTest01 {
@MyAnnotation
private int no;
@MyAnnotation
public AnnotationTest01(){}
@MyAnnotation
public static void m1(){
@MyAnnotation
int i = 100;
}
@MyAnnotation
public void m2(@MyAnnotation
String name,
@MyAnnotation
int k){
}
}
@MyAnnotation
interface MyInterface {
}
@MyAnnotation
enum Season {
SPRING,SUMMER,AUTUMN,WINTER
}
4.Override注解
/*
关于JDK lang包下的Override注解
源代码:
public @interface Override {
}
标识性注解,给编译器做参考的。
编译器看到方法上有这个注解的时候,编译器会自动检查该方法是否重写了父类的方法。
如果没有重写,报错。
这个注解只是在编译阶段起作用,和运行期无关!
*/
// @Override这个注解只能注解方法。
// @Override这个注解是给编译器参考的,和运行阶段没有关系。
// 凡是java中的方法带有这个注解的,编译器都会进行编译检查,如果这个方法不是重写父类的方法,编译器报错。
//@Override
public class AnnotationTest02 {
//@Override
private int no;
@Override
public String toString() {
return "toString";
}
}
5.@Deprecated
// 表示这个类已过时。
@Deprecated
public class AnnotationTest03 {
@Deprecated
private String s;
public static void main(String[] args) {
AnnotationTest03 at = new AnnotationTest03();
at.doSome();
}
@Deprecated
public void doSome(){
System.out.println("do something!");
}
// Deprecated这个注解标注的元素已过时。
// 这个注解主要是向其它程序员传达一个信息,告知已过时,有更好的解决方案存在。
@Deprecated
public static void doOther(){
System.out.println("do other...");
}
}
class T {
public static void main(String[] args) {
AnnotationTest03 at = new AnnotationTest03();
at.doSome();
AnnotationTest03.doOther();
try {
Class c = Class.forName("java.util.Date");
Object obj = c.newInstance();
} catch (Exception e) {
e.printStackTrace();
}
}
}
6.注解当中定义属性
public @interface MyAnnotation {
/**
* 我们通常在注解当中可以定义属性,以下这个是MyAnnotation的name属性。
* 看着像1个方法,但实际上我们称之为属性name。
* @return
*/
String name();
/*
颜色属性
*/
String color();
/*
年龄属性
*/
int age() default 25; //属性指定默认值
}
7.注解中属性赋值
public class MyAnnotationTest {
// 报错的原因:如果一个注解当中有属性,那么必须给属性赋值。(除非该属性使用default指定了默认值。)
/*@MyAnnotation
public void doSome(){
}*/
//@MyAnnotation(属性名=属性值,属性名=属性值,属性名=属性值)
//指定name属性的值就好了。
@MyAnnotation(name = "zhangsan", color = "红色")
public void doSome(){
}
}
8.注解的属性的名字是value
/*
如果一个注解的属性的名字是value,并且只有一个属性的话,在使用的时候,该属性名可以省略。
*/
public class MyAnnotationTest {
// 报错原因:没有指定属性的值。
/*@MyAnnotation
public void doSome(){
}*/
@MyAnnotation(value = "hehe")
public void doSome(){
}
@MyAnnotation("haha")
public void doOther(){
}
}
public @interface MyAnnotation {
/*
指定一个value属性。
*/
String value();
}
9.注解中属性类型
public @interface MyAnnotation {
/*
注解当中的属性可以是哪一种类型?
属性的类型可以是:
byte short int long float double boolean char String Class 枚举类型
以及以上每一种的数组形式。
*/
int value1();
String value2();
int[] value3();
String[] value4();
Season value5();
Season[] value6();
Class parameterType();
Class[] parameterTypes();
}
10.属性为数组时
public @interface OtherAnnotation {
/*
年龄属性
*/
int age();
/*
邮箱地址属性,支持多个
*/
String[] email();
/**
* 季节数组,Season是枚举类型
* @return
*/
Season[] seasonArray();
}
public class OtherAnnotationTest {
// 数组是大括号
@OtherAnnotation(age = 25, email = {"zhangsan@123.com", "zhangsan@sohu.com"}, seasonArray = Season.WINTER)
public void doSome(){
}
// 如果数组中只有1个元素:大括号可以省略。
@OtherAnnotation(age = 25, email = "zhangsan@123.com", seasonArray = {Season.SPRING, Season.SUMMER})
public void doOther(){
}
}
public enum Season {
SPRING,SUMMER,AUTUMN,WINTER
}
11.Target Retention
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
//只允许该注解可以标注类、方法
@Target({ElementType.TYPE, ElementType.METHOD})
// 希望这个注解可以被反射
@Retention(RetentionPolicy.RUNTIME)
public @interface MyAnnotation {
/*
value属性。
*/
String value() default "北京大兴区";
}
@MyAnnotation("上海浦东区")
public class MyAnnotationTest {
//@MyAnnotation
int i;
//@MyAnnotation
public MyAnnotationTest(){
}
@MyAnnotation
public void doSome(){
//@MyAnnotation
int i;
}
}
public class ReflectAnnotationTest {
public static void main(String[] args) throws Exception{
// 获取这个类
Class c = Class.forName("com.bjpowernode.java.annotation5.MyAnnotationTest");
// 判断类上面是否有@MyAnnotation
//System.out.println(c.isAnnotationPresent(MyAnnotation.class)); // true
if(c.isAnnotationPresent(MyAnnotation.class)){
// 获取该注解对象
MyAnnotation myAnnotation = (MyAnnotation)c.getAnnotation(MyAnnotation.class);
//System.out.println("类上面的注解对象" + myAnnotation); // @com.bjpowernode.java.annotation5.MyAnnotation()
// 获取注解对象的属性怎么办?和调接口没区别。
String value = myAnnotation.value();
System.out.println(value);
}
// 判断String类上面是否存在这个注解
Class stringClass = Class.forName("java.lang.String");
System.out.println(stringClass.isAnnotationPresent(MyAnnotation.class)); // false
}
}
12.利用反射机制获取注释中的属性
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface MyAnnotation {
/*
username属性
*/
String username();
/*
password属性
*/
String password();
}
import java.lang.reflect.Method;
public class MyAnnotationTest {
@MyAnnotation(username = "admin", password = "456456")
public void doSome(){
}
public static void main(String[] args) throws Exception{
// 获取MyAnnotationTest的doSome()方法上面的注解信息。
Class c = Class.forName("com.bjpowernode.java.annotation6.MyAnnotationTest");
// 获取doSome()方法
Method doSomeMethod = c.getDeclaredMethod("doSome");
// 判断该方法上是否存在这个注解
if(doSomeMethod.isAnnotationPresent(MyAnnotation.class)) {
MyAnnotation myAnnotation = doSomeMethod.getAnnotation(MyAnnotation.class);
System.out.println(myAnnotation.username());
System.out.println(myAnnotation.password());
}
}
}