开幕:初见
首先看一下家喻户晓的@Override注解:添加此注解,如果是非覆写的方法,就会报错
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.SOURCE)
public @
interface Override {
}
再先看一下@Deprecated注解:添加此注解,如果是过时的方法,就会画线提示
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(value={CONSTRUCTOR, FIELD, LOCAL_VARIABLE, METHOD, PACKAGE, MODULE, PARAMETER, TYPE})
public @
interface Deprecated {
String since()
default "";
boolean forRemoval()
default false;
}
我们这个群体应该很擅长归纳事物的共性,然后总结出一丝规律
可以看到的是:
public @
interface 注解名{
}
因此,可依照这样自己写一个注解类:
public @
interface APerson {
}
然后新建一个Person类看看能不能用:
@APerson
public class Person {
}
编译器没报错,看了可以,于是你的第一个没用的注解就由此诞生,开幕止。
第一幕:相识:
原标签
1:@Retention(注解存活期):接受一个RetentionPolicy类型的枚举常量
public enum RetentionPolicy {
/**
* Annotations are to be discarded by the compiler.
* 注解将会被编译器删除
*/
SOURCE,
/**
* Annotations are to be recorded in the class file by the compiler
* but need not be retained by the VM at run time. This is the default
* behavior.
* 编译器会将注解保留在字节码文件中,但VM会再运行期间保留它。这是默认行为
*/
CLASS,
/**
* Annotations are to be recorded in the class file by the compiler and
* retained by the VM at run time, so they may be read reflectively.
* 编译器会将注解保留在字节码文件中,VM也会在运行期间保留它。(所以他们可以通过反射性被读取)
* @see java.lang.reflect.AnnotatedElement
*/
RUNTIME
}
创建一个运行期的注解
@Retention(RetentionPolicy.RUNTIME)
public @
interface APerson {
}
2:@Target(目标):接受一个ElementType类型的枚举常量
public enum ElementType {
/** Class, interface (including annotation type), or enum declaration */
TYPE,
/** Field declaration (includes enum constants) */
FIELD,
/** Method declaration */
METHOD,
/** Formal parameter declaration */
PARAMETER,
/** Constructor declaration */
CONSTRUCTOR,
/** Local variable declaration */
LOCAL_VARIABLE,
/** Annotation type declaration */
ANNOTATION_TYPE,
/** Package declaration */
PACKAGE,
/**
* Type parameter declaration
* 声明参数类型
* @since 1.8
*/
TYPE_PARAMETER,
/**
* Use of a type
*
* @since 1.8
*/
TYPE_USE,
/**
* Module declaration.
* 声明模块
* @since 9
*/
MODULE
}
3:@Inherited(继承):子类继承父类的注解
4:@Repeatable(可重复)
5:@Documented:能够将注解中的元素包含到 Javadoc。
已经同注解进行了基本的对话(了解),第二幕止。
第三幕:交涉
改善一下我们的注解
package top.toly.注解;
import java.lang.annotation.*;
/**
* 作者:张风捷特烈
* 时间:2018/5/22:8:20
* 邮箱:1981462002@qq.com
* 说明:注解类
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @
interface APerson {
public String
name()
default "捷特";
public int age()
default 24;
}
使用反射获取APerson对象,再得到其方法
package top.toly.注解;
/**
* 作者:张风捷特烈
* 时间:2018/5/22:8:21
* 邮箱:1981462002@qq.com
* 说明:注解测试端
*/
@APerson(name =
"捷特", age =
24)
public class Person {
APerson aPerson = getClass().getAnnotation(APerson.class);
public void say() {
String name = aPerson.name();
int age = aPerson.age();
System.out.println(
"my name is "+name+
",and I am "+age+
"years old");
}
public static void main(String[] args) {
Person person =
new Person();
person.say();
}
}
输出结果
my name is 捷特,
and I am
24 years old.
现在测试一下@Inherited(继承):
package top.toly.注解;
/**
* 作者:张风捷特烈
* 时间:2018/5/22:8:21
* 邮箱:1981462002@qq.com
* 说明:注解测试端
*/
@APerson(name =
"捷特", age =
24)
public
class Person {
APerson aPerson = getClass().getAnnotation(APerson.
class);
public void say() {
String name = aPerson.name();
int age = aPerson.age();
System.out.println(
"my name is "+name+
",and I am "+age+
" years old.");
}
public static void main(String[] args) {
Student student =
new Student();
student.say();
}
}
class Student extends Person {
}
运行:报错
Exception
in thread
"main" java
.lang.NullPointerException
at top
.toly.注解
.Person.say(Person
.java:
14)
at top
.toly.注解
.Person.main(Person
.java:
22)
添加@Inherited注解
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@Inherited
public @
interface APerson {
public String
name()
default "捷特";
public int age()
default 24;
}
运行:
my name
is 捷特,
and I am
24 years
old.
这时你已经可以通过注解来获取信息了
第四幕:共鸣
人类创造了刀,有些人用它雕精美的艺术品,有人依靠它成为江湖浪客,有人以它护生,有人用它杀生。
成败善恶并非工具的荣辱,也非是锻造它的人,一切只取决于握刀人的本性与技艺。
下面通过两个简单示例实战一下
示例一:声明:下面的案例借鉴并修改于:https://blog.csdn.net/briblue/article/details/73824058
package top.toly.注解;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
/**
* 作者:张风捷特烈
* 时间:2018/5/22:10:16
* 邮箱:1981462002@qq.com
* 说明:注解类
*/
@Retention(RetentionPolicy.RUNTIME)
public @
interface ADebug {
}
package top.toly.注解;
import java.lang.reflect.Method;
/**
* 作者:张风捷特烈
* 时间:2018/5/22:10:17
* 邮箱:1981462002@qq.com
* 说明:测试工具类
*/
public class Debug {
public static void debug(String clazz_name) {
Class<?> clazz =
null;
Object testobj =
null;
try {
clazz = Class.forName(clazz_name);
testobj = clazz.newInstance();
}
catch (Exception e) {
e.printStackTrace();
}
Method[] method = clazz.getDeclaredMethods();
StringBuilder log =
new StringBuilder();
int errornum =
0;
for (Method m : method) {
if (m.isAnnotationPresent(ADebug.class)) {
try {
m.setAccessible(
true);
m.invoke(testobj,
null);
}
catch (Exception e) {
errornum++;
log.append(
"错误"+errornum+
":"+m.getName()+
"() has error:");
log.append(
"\n\r caused by ");
log.append(e.getCause().getClass().getSimpleName());
log.append(
"\n\r");
log.append(e.getCause().getMessage());
log.append(
"\n\r");
}
}
}
log.append(clazz.getSimpleName());
log.append(
" has ");
log.append(errornum);
log.append(
" error.");
System.out.println(log.toString());
}
}
package top.toly.注解;
/**
* 作者:张风捷特烈
* 时间:2018/5/22:10:18
* 邮箱:1981462002@qq.com
* 说明:待测试类
*/
public class BugTest {
@ADebug
public void say(){
System.out.println(Integer.parseInt(
"a"));
}
@ADebug
public void jia(){
System.out.println(
"1+1="+
1+
1);
}
@ADebug
public void jian(){
System.out.println(
"1-1="+(
1-
1));
}
@ADebug
public void cheng(){
System.out.println(
"3 x 5="+
3*
5);
}
@ADebug
public void chu(){
System.out.println(
"6 / 0="+
6 /
0);
}
public void resay(){
say();
}
}
package top.toly.注解;
/**
* 作者:张风捷特烈
* 时间:2018/5/22:10:28
* 邮箱:1981462002@qq.com
* 说明:运行端
*/
public class Client {
public static void main(String[] args) {
Debug.debug(
"top.toly.注解.BugTest");
}
}
输出:
1-
1=
0
3 x
5=
15
1+
1=
11
错误
1:say() has
error:
caused
by NumberFormatException
For input
string:
"a"
错误
2:chu() has
error:
caused
by ArithmeticException
/
by zero
BugTest has
2 error.
可以看到未加注解的方法,即使错了也不会检查到。
注解更像提示你一下到这要不要做些什么事,具体逻辑还需要具体的类来实现。
唯一的优势在于你知道了程序已经运行到注解处,还有你可以获取到注解中的字段值。
示例二:根据一个bean对象,来输处MySQL的查询语句
1.数据库列(字段)注解
package top.toly.注解.test;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* 作者:张风捷特烈
* 时间:2018/5/22:23:27
* 邮箱:1981462002@qq.com
* 说明:数据库列(字段)注解
*/
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @
interface Column {
String value();
}
2.数据库表注解
package top.toly.注解.test;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* 作者:张风捷特烈
* 时间:2018/5/22:23:27
* 邮箱:1981462002@qq.com
* 说明:数据库表注解
*/
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @
interface Table {
String value();
}
3.bean对象Sworld:曾经创建过一个sword的数据库,正好拿来用。(对MySQL不熟悉的可以看我的MySQL篇)
package top.toly.注解.test.bean;
import top.toly.注解.test.Column;
import top.toly.注解.test.Table;
/**
* 作者:张风捷特烈
* 时间:2018/5/23:14:47
* 邮箱:1981462002@qq.com
* 说明:
*/
@Table(
"sword")
public class Sword {
@Column(
"id")
private int id;
@Column(
"name")
private String name;
@Column(
"atk")
private int atk;
@Column(
"hit")
private int hit;
@Column(
"crit")
private int crit;
@Column(
"attr_id")
private int attr_id;
@Column(
"type_id")
private int type_id;
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 getAtk() {
return atk;
}
public void setAtk(
int atk) {
this.atk = atk;
}
public int getHit() {
return hit;
}
public void setHit(
int hit) {
this.hit = hit;
}
public int getCrit() {
return crit;
}
public void setCrit(
int crit) {
this.crit = crit;
}
public int getAttr_id() {
return attr_id;
}
public void setAttr_id(
int attr_id) {
this.attr_id = attr_id;
}
public int getType_id() {
return type_id;
}
public void setType_id(
int type_id) {
this.type_id = type_id;
}
}
4.核心类:QueryUtil:使用注解辅助得到查询语句
package top
.toly.注解
.test
import java
.lang.reflect.Field
import java
.lang.reflect.Method
public class QueryUtil {
public static String query(Object o) {
StringBuffer sb = new StringBuffer()
//
1.获取class
Class<?> aClass = o
.getClass()
//
2.获取表名
boolean exist = aClass
.isAnnotationPresent(Table
.class)
if (exist) {
Table table = aClass
.getAnnotation(Table
.class)
String tableName = table
.value()
sb
.append(
"SELECT * FROM ")
.append(tableName)
.append(
" WHERE 1=1")
//
3.遍历字段
Field[] fields = aClass
.getDeclaredFields()
for (Field field : fields) {
//
4.处理字段对应的sql
boolean b = field
.isAnnotationPresent(Column
.class)
if (!b) {
continue
}
Column column = field
.getAnnotation(Column
.class)
String columnName = column
.value()
String fieldName = field
.getName()
String getMethodName =
"get" + fieldName
.substring(
0,
1)
.toUpperCase() + fieldName
.substring(
1)
Object fieldValue = null
try {
Method getMethod = aClass
.getMethod(getMethodName)
fieldValue = getMethod
.invoke(o)
} catch (Exception e) {
e
.printStackTrace()
}
//拼装sql
if (fieldValue == null || (fieldValue instanceof Integer && (Integer) fieldValue ==
0)) {
continue
}
sb
.append(
" and ")
.append(fieldName)
if (fieldValue instanceof String) {
String value = (String) fieldValue
if (value
.contains(
",")) {
String[] strings = value
.split(
",")
sb
.append(
" in(")
for (String string : strings) {
sb
.append(
"'")
.append(string)
.append(
"'")
.append(
",")
}
sb
.deleteCharAt(sb
.length() -
1)
sb
.append(
")")
}else {
sb
.append(
"=")
.append(
"'" + fieldValue +
"'")
}
}else {
sb
.append(
"=")
.append(fieldValue)
}
}
}
return sb
.toString()
}
}
5.测试端
package top.toly.注解.test;
import top.toly.注解.test.bean.Sword;
/**
* 作者:张风捷特烈
* 时间:2018/5/23:14:54
* 邮箱:1981462002@qq.com
* 说明:测试端
*/
public class Client {
public static void main(String[] args) {
Sword sabar =
new Sword();
sabar.setName(
"炽燃");
sabar.setAtk(
2000);
System.out.println(QueryUtil.query(sabar));
}
}
6.打印结果
SELECT * FROM sword WHERE 1=1 and name='炽燃' and atk=2000
用MySQL验证一下:
终幕
转载于:https://www.cnblogs.com/toly-top/p/9782025.html