java注解的介绍、认识与基本使用
注解Annotation是什么(What)
Annotation是从JDK5.0开始引入的新技术
nnotation不是程序本身,可以对程序作出解释(这点和注释很像)
Annotation可以被其他程序(eg:编译器等)读取。
注解与注释最大的区别就是:注解信息处理流程
为什么要用注解(Why)
优点
1,开发速度快
2,编译期间容易发现错误的出处
缺点
1,管理分散,基本每个类上都有;
2,扩展功能时,没有遵循OCP开发原则。
注解在哪里用(Where)
可以附加在package,class,method,field等上面,相当于给他们添加了额外的辅助信息,我们可以通过反射机制编程实现对这些元数据的访问。
注解怎么用(How)
Annotation的格式:
注解是以“@注解名”在代码中存在的,还可以添加一些参数值,例如:@SuppressWarnings(value=“unchecked”)。
注解分类
-
内置注解
**常用内置注解如下:**
*@Override* 定义在java.lang.Override中,此注解只适用于修饰方法,表示一个方法声明打算重写父类中的另一个方法声明
*@Deprecated* 定义在java.lang.Deprecated中,此注解可用于修饰方法,属性,类表示不鼓励程序员使用这样的元素,通常是因为它很危险或存在更好的选择(引用时一般有删除线提示)
*@SuppressWarnings* 定义在java.lang.SuppressWarnings中,用来抑制编译时的警告信息 与前两个注解有所不同,需要添加一个参数才能正确使用,这些参数都是已经定义好的,可以自己选择。参数如下:
参数 | 说明 |
deprecation | 使用了过时的类或方法的警告 |
unchecked | 执行了未检查的转换时的警告,eg:使用集合时未指定泛型 |
fallthrough | 当在switch语句使用时发生case穿透(忘写break) |
path | 在类路径、源文件路径等中有不存在路径的警告 |
serial | 当在可序列化的类上缺少serialVersionUID定义时的警告 |
finally | 任何finally子句不能完成时的警告 |
all | 关于以上所有情况的警告 |
@SuppressWarnings(value={“unchecked”,“deprecation”})
示意图:
-
元注解
元注解的作用就是负责注解其他注解。
Java定义了4个标准的meta-annotation类型:
– @Target
– @Retention
– @Documented
– @Inherited
这些类型和它们所支持的类都在java.lang.annotation包
@Target
作用:用于描述注解的使用范围(被描述的注解可以用在什么地方)
所修饰的范围 | 取值 ElementType |
package 包 | ElementType.PACKAGE |
类、接口、枚举、Annotation类型 | ElementType.TYPE |
方法 | ElementType.METHOD |
构造方法 | ElementType.CONSTRUCTOR |
成员变量 | ElementType.FIELD |
方法参数 | ElementType.PARAMETER |
局部变量 | ElementType.LOCAL_VARIABLE |
– @Target(value= {ElementType.METHOD,ElementType.TYPE})
@Retention
作用:表示需要在什么级别保存该注释信息,用于描述注解的生命周期
取值 RetentionPolicy | 作用 |
RetentionPolicy.SOURCE | 在源文件中有效 |
RetentionPolicy.CLASS | 在class文件中有效 |
RetentionPolicy.RUNTIME | 在运行时有效(为RUNTIME可以被反射机制读取) |
示意图:
-
自定义注解
使用*@interface*自定义注解时, 自动继承了java.lang.annotation.Annotation接口
示意图:
使用反射获取注解信息
使用注解完成类和表结构的映射关系,然后再使用反射读取注解信息。
ORM(Object Relationship Mapping)对象关系映射
类和表结构对应
属性和字段对应
对象和记录对应
代码实现如下:
package com.xyj.annotation;
/**
* 实体类 对应数据库的表
* @author Administrator
*
*/
@Table("studb")
public class Student {
//属性 对应数据库的字段
@Field(columnName="id",type="int",length=10)
private int id;
@Field(columnName="name",type="varchar",length=10)
private String name;
@Field(columnName="age",type="int",length=3)
private int age;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public Student(int id, String name, int age) {
super();
this.id = id;
this.name = name;
this.age = age;
}
public Student() {
}
@Override
public String toString() {
return "Student [id=" + id + ", name=" + name + ", age=" + age + "]";
}
}
package com.xyj.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 Table {
String value();//表名
}
package com.xyj.annotation;
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 {
String columnName();//列名
String type();//类型
int length();//长度
}
package com.xyj.annotation;
import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
/**
* 使用反射读取注解的信息,模拟处理注解信息的流程
*/
@SuppressWarnings("all")
public class Demo03 {
public static void main(String[] args) {
try {
Class c=Class.forName("com.xyj.annotation.Student");//获取运行类
//获取该类使用的注解
Annotation[] annotations = c.getAnnotations();
for (Annotation a : annotations) {
System.out.println(a);
}
//获取类的指定的注解
Table t=(Table) c.getAnnotation(Table.class);//通过注解.class 获取指定注解
System.out.println(t.value());
//获得类的属性的注解
Field f = c.getDeclaredField("name");
com.xyj.annotation.Field f2 = f.getAnnotation(com.xyj.annotation.Field.class);//这里写包名的原因是Field和别的包中的类重名啦
System.out.println(f2.columnName()+"--"+f2.type()+"--"+f2.length());
} catch (Exception e) {
e.printStackTrace();
}
}
}