【java提高】(16)---java注解(Annotation)
java提高(16)---java注解
注解含义
注解是JDK1.5之后才有的新特性,它相当于一种标记,在程序中加入注解就等于为程序打上某种标记,之后又通过类的反射机制
来解析注解。
一、JDK自带注解
JDK1.5之后内部提供的三个注解
@Deprecated #废弃,过时。
@Override #重写、覆盖。
@SuppressWarnings #压缩警告。
示例
@SuppressWarnings("deprecation")
public class AnnotationTest {
//4、这里称为压缩警告注解,可以在类上也可以放在方法上,因为该方法用了个已经过期的方法.getYear(),所以会发出警告
//加上这个注解表明取消对deprecation的警告,那么该方法里有过时方法也不会发出预警。同时getYear()的那条横线也消失了。
@SuppressWarnings("deprecation")
public static void main(String[] args) {
//1、这里的.getYear()方法画了一条横线表示此方法已经过时了,里面方法加上了@Deprecated注解
new Date().getYear();
}
//2、这里我通过@Deprecated注解自定义一个已经过时不建议使用的方法。
@Deprecated
public String getName() {
return "小小";
}
//3、重写(覆盖)父类Object的toString()方法
@Override
public String toString() {
return "小小";
}
}
注解示意图
二、自定义注解
示例
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@Documented
public @interface AnCode {//使用@interface关键字定义注解
//如果只有一个属性 强烈建议取名为value
String value() default "";
}
在自定义注解上面有四个注解,我们称为元注解
,下面一个一个解释。
1、@Target 用于描述注解的使用范围
取值(ElementType)有:
1、CONSTRUCTOR: 用于描述构造器
2、FIELD: 用于描述域(字段申明)
3、LOCAL_VARIABLE:用于描述局部变量
4、METHOD: 用于描述方法
5、PACKAGE: 用于描述包
6、PARAMETER: 用于描述参数
7、TYPE: 用于描述类、接口(包括注解类型) 或enum声明
8、TYPE_PARAMETER:输入参数申明(JDK1.8)
9、TYPE_USE: 使用类型(JDK1.8)
2、@Retention 定义了该注解生命周期
取值(RetentionPoicy)有:
1、SOURCE: 在源文件中有效(即源文件保留)
2、CLASS: 在class文件中有效(即class保留)
3、RUNTIME: 注解永久保留,可以被VM加载时加载到内存中
一般框架注解和我们自定义注解采用的几乎都是RUNTIME
,因为只有这个才能运行时通过反射来获取注解中的数据。
3、@Inherited
概念
: @Inherited阐述了某个被标注的类型是被继承的。如果一个使用了@Inherited修饰的annotation类型被用于一个class,则这个annotation将被用于该class的子类。
注意
:@Inherited annotation类型是被标注过的class的子类所继承。类并不从它所实现的接口继承annotation,方法并不从它所重载的方法继承annotation
解释
: 比如A继承B,B类的上面有一个注解@A带有元注解@Inherited 那么A也可以拥有B父类的这个注解@A,但接口实现是不可以的。同时需要指出@A注解是需要元注解@Retention(RetentionPolicy.RUNTIME)。
参考文章:java @Inherited注解的作用
4、@Documented
概念
:描述其它类型的annotation应该被作为被标注的程序成员的公共API,因此可以被例如javadoc此类的工具文档化。
5、自定义注解参数
1、只能用public或默认(default)这两个访问权修饰.例如,String value();这里把方法设为defaul默认类型;
2、参数成员只能用基本类型byte,short,char,int,long,float,double,boolean八种基本数据类型和
String,Enum,Class,annotations等数据类型,以及这一些类型的数组;
3、如果只有一个参数成员,最好把参数名称设为"value",后加小括号(也可以不加小括号)
三、自定义注解案例
目标
实现一个简单的通过注解生成SQL查询语句。
先创建两个注解
@Table表名注解
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface Table {
//数据库表名属性
String value() default "";
}
@Column字段名注解
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Column {
//数据库表字段名称和实体属性映射
String value() default "";
}
User实体
@Table("t_user")
public class User {
/**
* 用户Id
*/
@Column("user_id")
private Integer userId;
/**
* 用户年龄
*/
@Column("age")
private Integer age;
public User(Integer userId, Integer age) {
this.userId = userId;
this.age = age;
}
//添加get和set方法
}
解析注解类
public class Query {
public static String query(Object object) throws Exception{
StringBuilder sql = new StringBuilder();
//1.利用反射获取Class
Class c = object.getClass();
//2.获取Table的名字
boolean isExist = c.isAnnotationPresent(Table.class);
if (!isExist) {
return null;
}
Table t = (Table) c.getAnnotation(Table.class);
//3、获取注解上的value值
String tableName = t.value();
sql.append("select * form ").append(tableName).append(" where 1 = 1 ");
//4.遍历所有的属性字段
Field[] fArray = c.getDeclaredFields();
for (Field field : fArray) {
//处理每个字段对应的sql
boolean fExist = field.isAnnotationPresent(Column.class);
if (!fExist) {
continue;
}
Column column = field.getAnnotation(Column.class);
//数据库字段名
String columnName = column.value();
//5、将user_id 变成 userId
String[] columns = columnName.split("_");
StringBuilder columnBuilder = new StringBuilder();
for (int i = 0; i < columns.length; i++) {
String s = columns[i];
columnBuilder.append(s.substring(0, 1).toUpperCase()).append(s.substring(1));
}
//6、活动属性值
String getMethodName = "get" + columnBuilder.toString(); //get方法名
Method getMethod = c.getMethod(getMethodName);
Object fieldValue = getMethod.invoke(object);//类字段值
//7、拼装sql
sql.append(" and ").append(columnName).append(" = ").append(fieldValue);
}
return sql.toString();
}
}
测试类
public static void main(String[] args) throws Exception {
User user = new User(001, 4);
String query = Query.query(user);
System.out.println("query = " + query);
}
运行结果
通过这个小案例实现了通过注解的方式,生成sql语句。
只要自己变优秀了,其他的事情才会跟着好起来(少将20)