Java的自定义注解使用实例

概念

Java有五个元注解,自动继承java.lang.annotation.Annotation。

什么是元注解,可以理解为其他普通注解进行解释说明

@Target  该注解的使用范围,限定应用场景。枚举类 ElemenetType 中

  1. TYPE:类,接口
  2. FIELD:字段,枚举的常量
  3. METHOD:函数(方法)
  4. PARAMETER:参数
  5. CONSTRUCTOR:构造函数
  6. ANNOTATION_TYPE:注解类型
  7. LOCAL_VARIABLE:局部变量
  8. PACKAGE:包

@Retention  该注解的生存周期,相当于时间戳。枚举类型 RetentionPolicy 中

  1. SOURCE:在源文件中有效,编译后会被丢弃(如@Override,@Deprecated)
  2. CLASS:在class文件中有效,在jvm丢弃
  3. RUNTIME:在运行时有效,class文件保留,jvm运行时保留(很多框架运用反射调用)

@Documented

javadoc文档生成工具的使用

@Inherited

允许子类继承父类中的注解。

@Repeatable

同一种注解可多次使用

作用

  1. 注释,解释,通过代码的标识元数据生成doc文档;
  2. 使用反射,通过代码标识的元数据对代码进行分析;
  3. 编译检查,通过代码标识的元数据让编译器进行基本检查。

实例

定义一个普通的注解,

public @interface Test
{ }

使用我们自定义的注解

@Test
public class Person
{
@Test
private String name; @Test
private int age; @Test
public void say()
{
System.out.println("Hello,Java Annotation");
}
}

@Target(ElementType.PACKAGE) 注解作用的目标>包

这个注解要理解什么是友好声明类和包常量,包中有很多的内部访问的类或常量,就可以统一的放到友好声明类中,这样就方便,而且集中管理,减少friendly类到处游走的情况。

可以参考这个 https://www.cnblogs.com/DreamDrive/p/5428573.html

import java.lang.annotation.ElementType;
@Target(ElementType.PACKAGE)
public @interface Test
{
}
@Test
package test; class Person
{ private String name; private int age; public void say()
{
System.out.println("Hello,Java Annotation");
}
}

@Target(ElementType.CONSTRUCTOR) 注解作用的目标>构造函数

package test;

import java.lang.annotation.ElementType;
import java.lang.annotation.Target;
@Target(ElementType.CONSTRUCTOR)
public @interface Test
{ }
package test;

public class Person
{ private String name; private int age;
@Test
public Person()
{ } public void say()
{
System.out.println("Hello,Java Annotation");
}
}

其他范围就不一一列举,都是相同的。

@Retention(RetentionPolicy.RUNTIME)   生存周期

代码运行时动态获取注解的信息

package test;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target(ElementType.CONSTRUCTOR)
@Retention(RetentionPolicy.RUNTIME)
public @interface Test
{ }
package test;

public class Person
{ private String name; private int age;
@Test
public Person()
{ } public void say()
{
System.out.println("Hello,Java Annotation");
}
}

注解的属性-->成员变量

方法名是成员变量的的名字,变量的类型是他的返回值。

package test;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface Test
{
public int age() default ; public String name() default ""; public String className();
}
package test;

import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.lang.reflect.Method; @Test(age = 15,name = "zhangsan",className = "高三(3)班")
public class Person
{ private String name; private int age; public Person()
{ } private void say()
{
System.out.println("Hello,Java Annotation");
}
}

既然给了注解,我们要做的工作必然是要提取注解上面的内容,要拿到这些注解就要用到反射。

package test;

import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.lang.reflect.Method; @Test(age = 15,name = "zhangsan",className = "高三(3)班")
public class Person
{private String name; private int age; public Person()
{ } private void say()
{
System.out.println("Hello,Java Annotation");
} public static void main(String[] args)
{
boolean hasAnnotation = Person.class.isAnnotationPresent(Test.class); if (hasAnnotation)
{
Test test = Person.class.getAnnotation(Test.class); System.out.println("age:" + test.age());
System.out.println("name:" + test.name());
System.out.println("className:" + test.className());
}
}
}

输出结果

age:15
name:zhangsan
className:高三(3)班

对于类的属性和方法,都是同样的道理。

成员注解

package test;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target; @Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Field
{
public String name();
}

函数注解

package test;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target; @Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Method
{
public String say();
}

Person类

package test;

import java.lang.annotation.Annotation;

@Test(age = 15,name = "zhangsan",className = "高三(3)班")
public class Person
{
@Field(name = "lisi")
private String name; private int age; public Person()
{ }
@Method(say = "hello")
private void say()
{
System.out.println("Hello,Java Annotation");
} public static void main(String[] args)
{
boolean hasAnnotation = Person.class.isAnnotationPresent(Test.class); if (hasAnnotation)
{
Test test = Person.class.getAnnotation(Test.class); System.out.println("age:" + test.age());
System.out.println("name:" + test.name());
System.out.println("className:" + test.className());
} try
{
java.lang.reflect.Field field = Person.class.getDeclaredField("name"); field.setAccessible(true); Field check = field.getAnnotation(Field.class); if (check != null)
{
System.out.println("check value:" + check.name());
} java.lang.reflect.Method method = Person.class.getDeclaredMethod("say"); if (method != null)
{
Annotation[] ans = method.getAnnotations();
for (int i = 0; i < ans.length; i++)
{
System.out.println("method annotation:" + ans[i].annotationType().getSimpleName());
}
} } catch (NoSuchFieldException e)
{
e.printStackTrace();
}catch (Exception e){
e.printStackTrace();
} }
}

输出

age:15
name:zhangsan
className:高三(3)班
check value:lisi
method annotation:Method

可以看出我们获取了注解上的值,现在都没有实际意义,我们可以用注解来做些什么?

这些我没办法给出确切答案,只能说根据各人需求去合理利用注解。

实例

注解参数赋值

@Test注解

package test;

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.FIELD})
public @interface Test
{
String value();
}

Person类属性赋值

package test;

import org.apache.poi.ss.formula.functions.T;

import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.lang.reflect.Method; public class Person
{
@Test("zhangsan")
private String name; @Test("15")
private int age; public Person()
{ } private void say()
{
System.out.println("Hello,Java Annotation");
} @Override
public String toString()
{
return "name = " + name + "\n" + "age = " + age;
} public static void main(String[] args)
{
Person person = new Person();
try
{
//取得成员变量的值
Field field = Person.class.getDeclaredField("name");
//打开权限
field.setAccessible(true);
//判断属性是否有注解
if (field.isAnnotationPresent(Test.class))
{
//获取属性上的注解值
Test test = field.getAnnotation(Test.class);
String name = test.value();
//赋值
field.set(person,name);
} Field field1 = Person.class.getDeclaredField("age");
field1.setAccessible(true);
if (field1.isAnnotationPresent(Test.class))
{
Test test = field1.getAnnotation(Test.class);
int age = Integer.valueOf(test.value());
field1.set(person,age);
}
System.out.println(person); }catch (Exception e)
{
e.printStackTrace();
} }
}

输出

name = zhangsan
age = 15

用注解去检查函数等等。。

lz不善于用语言表达,所以可能有很多人没看懂,可以看下

一个大佬讲解的注解说明(简单易懂)

https://blog.csdn.net/briblue/article/details/73824058

上一篇:Python 学习(1) 简单的小爬虫


下一篇:关于android中透明、半透明、百分比转换