Java注解数据类型
1.注解的定义
注解:或者叫做注释类型,英文单词是Annotation(不是//或者/**/)
注解Annotation是一种引用数据类型。编译之后也是xxx.class文件
怎么定义自己的注解呢?语法格式如下:
[修饰符列表] @interface 注解类型名{
}
2.注解的使用
2.1使用时的语法格式
@注解类型名:@Override
注解可以出现在类上,属性上,方法上,变量上…
注解还可以出现在注解类型上。
@MyAnnotation
public class AnnotationTest01 {
@MyAnnotation
private int no;
public AnnotationTest01() {
}
public static void m1(){
@MyAnnotation
int i = 0;
}
public void m2(@MyAnnotation String name){
}
}
@MyAnnotation
public @interface OtherAnnotation {
}
2.2 JDK中的内置注解
2.2.1 Override注解
@Override这个注解只能注解方法
@Override是给编译器参考的,和运行阶段没有关系
凡是java中带有这个注解的,编译器都会进行检查,假如不是重写父类的方法,那么会报错
这个注解只是在编译期有作用,和运行期无关。
/*
关于JDK lang包下的Override注解
源代码:
public @interface Override{
}
*/
//@Override
public class AnnotationTest02 {
@Override
public String toString() {
return "AnnotationTest02{}";
}
}
2.2.2 元注解
什么是元注解?
用来标准注解类型的注解称为“元注解”
常见的元注解有哪些?
- Target
- Retention
2.2.2.1关于Target注解
这是一个元注解,用来标注“注解类型”的注解
这个Target注解用来标注“被标注的注解”可以出现在哪些位置上
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.SOURCE)
public @interface Override {
}
@Target(ElementType.METHOD)
表明注解只能出现在方法上
2.2.2.2关于Retention注解
Rentention:这是一个元注解,表示“被标注的注解”最终保存到哪里
@Retention(RetentionPolicy.SOURCE)
:表示该注解只保存在java源文件中
@Retention(RetentionPolicy.CLASS)
:表示该注解被保存在class文件中
@Retention(RetentionPolicy.RUNTIME)
:表示该注解被保存在class文件中,且可以被反射机制获取
2.2.3 Deprecated注解
Deprecated这个注解表明被标注的元素已经过时
这个注解向其他程序员传达一个信息:告知已过时,有更好的解决方法存在。
//表示这个类已经过时
@Deprecated
public class AnnotationTest03 {
@Deprecated
public static void doSome(){
System.out.println("do something!");
}
public static void doOther(){
System.out.println("do other....");
}
}
class T {
public static void main(String[] args) {
AnnotationTest03 annotationTest03 = new AnnotationTest03();
AnnotationTest03.doSome();
AnnotationTest03.doOther();
}
}
2.3 自定义注解
2.3.1 属性值
/*
自定义注解:MyAnnotation
*/
public @interface MyAnnotation {
/**
* 我们通常在注解中可以定义属性,以下这个是MyAnnotation的name属性
* 看着是一个方法,实际上是一个属性
*/
String name();
}
当注解中定义了属性之后,之后在需要的地方写注解时就要加上属性值:@MyAnnotatioon(name = "张山")
,否则会报错。除非这个属性有defult默认值。示例代码如下:
/*
自定义注解:MyAnnotation
*/
public @interface MyAnnotation {
/**
* 我们通常在注解中可以定义属性,以下这个是MyAnnotation的name属性
* 看着是一个方法,实际上是一个属性
*/
String name();
/*
颜色属性
*/
String color();
/*
注解还可以默认,默认的注解不写值也行
*/
int age() default 25;
}
public class AnnotationTest01 {
private int no;
@MyAnnotation(name = "张三",color = "红色")
public AnnotationTest01() {
}
public static void m1(){
int i = 0;
}
public void m2(String name){
}
}
2.3.2 属性值为value
当属性值为value,且只有这一个属性时,属性名可以省略,其他的属性名不行:
public @interface MyAnnotation2 {
String value();
//String name;
}
public class MyAnnotationTest {
//报错原因:注解为赋属性值
// @MyAnnotation2
// public void doSome(){
//
// }
@MyAnnotation2(value = "hahaha")
public void doSme(){
}
@MyAnnotation2("yiyiyi~~")
public void doOther(){
}
}
2.3.1属性的类型
注解中的属性可以是哪一种类型?
可以是一下的所有,以及每一种类型的数组:
byte short int long float double boolean char
String Class
public @interface MyAnnotation3 {
/*
注解中的属性可以是哪一种类型?
可以是一下的所有,以及每一种类型的数组:
byte short int long float double boolean char
String Class
*/
String[] myString();
int value1();
Class parameterType();
Class parameterTypes();
Season season();
Season[] seasons();
}
- 数组形式的 { } 的省略
public @interface OtherAnnotation2 {
//年龄属性
int age();
/*
* 邮箱地址属性,支持多个
*/
String[] email();
Season[] season();
}
public class OtherAnnotation2Test {
@OtherAnnotation2(age = 25, email = {"2232143462@qq.com","lisi@qq.com"},season = Season.AUTUMN)
public void doSome(){
}
//如果数组中只有一个元素,那么{}可以省略
@OtherAnnotation2(age = 2,email = "Blanche@qq.com",season = {Season.SPRING,Season.SUMMER,Season.WINTER})
public void doOther(){
}
}
2.4 反射机制获取注解
- 注解类
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
//只允许注解标注类和方法
@Target({ElementType.TYPE,ElementType.ANNOTATION_TYPE,ElementType.FIELD,ElementType.METHOD})
//希望这个注解可以被反射
@Retention(RetentionPolicy.RUNTIME)
public @interface MyAnnotation5 {
String address() default "北极";
}
- 被测试类
@MyAnnotation5
public class MyAnnotationTest4 {
@MyAnnotation5
int i;
@MyAnnotation5
public void doSome(){
}
}
- 测试类
通过反射机制获取注解
public class ReflectAnnotationTest {
public static void main(String[] args) throws Exception{
//获取类
Class c = Class.forName("MyAnnotationTest4");
//判断类上是否有Annotation
//System.out.println(c.isAnnotationPresent(MyAnnotation5.class));
if(c.isAnnotationPresent(MyAnnotation5.class)){
MyAnnotation5 myAnnotation5 = (MyAnnotation5) c.getAnnotation(MyAnnotation5.class);
System.out.println("类上的注解:" + myAnnotation5);
//要获取注解对象的属性怎么办?和调接口一样
String address = myAnnotation5.address();
System.out.println(address);
}
//判断String类上是否有这个注解
Class str = Class.forName("java.lang.String");
System.out.println(str.isAnnotationPresent(MyAnnotation5.class));
}
}
3.注解的作用
需求:假设有这样的一个注解,叫做@id
这个注解只能出现在类上面,当一个类上面有这个注解的时候,这个类中必须有一个int类型的id属性,否则就报异常
如果有这个属性,就正常执行。
- 注解类
package AnnatationExample;
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.TYPE)
public @interface Id {
}
//这个注解用来标注类,被标注的类必须有一个int类型的id属性,否则报异常
package AnnatationExample;
@Id
public class User {
int id;
String name;
}
- 测试类
package AnnatationExample;
import java.lang.reflect.Field;
public class Test {
public static void main(String[] args) throws ClassNotFoundException {
//获取类
Class userClass = Class.forName("AnnatationExample.User");
boolean flag = false;//默认的标记,默认值是false;
//判断类上是否存在Id注解
if(userClass.isAnnotationPresent(Id.class)){
//当一个类上有Id注解的时候要求类中必须存在int类型的id属性,否则报异常
Field[] fields = userClass.getDeclaredFields();
for(Field field:fields){
if("id".equals(field.getName()) && "int".equals(field.getType().getSimpleName())){
//表示是一个正确的类
flag = true;
break;
}
}
}
if(!flag){
throw new HaventIDPropertyException("被Id注解标注的类中必须有一个int类型的id属性!");
}
}
}
- 异常类
package AnnatationExample;
public class HaventIDPropertyException extends RuntimeException{
public HaventIDPropertyException(){
}
public HaventIDPropertyException(String s){
super(s);
}
}
break;
}
}
}
if(!flag){
throw new HaventIDPropertyException("被Id注解标注的类中必须有一个int类型的id属性!");
}
}
}
- 异常类
```java
package AnnatationExample;
public class HaventIDPropertyException extends RuntimeException{
public HaventIDPropertyException(){
}
public HaventIDPropertyException(String s){
super(s);
}
}