1、注解入门
2、内置注解
3、自定义注解、元注解
4、小案例(使用反射读取注解的信息,模拟处理注解信息的流程)
1、注解入门
Annotation是从JDK5.0开始引入的新技术
Annotation的作用:
不是程序本身,可以对程序作出解释(其实这一点,和注释很像)可以被其他程序(比如:编译器)读取(注解信息处理流程,是注解和注释的重大区别,如果没有注解信息处理流程,则注解毫无意义)
Annotation的格式:
注解是以”@注释名”在代码中存在的,还可以添加一些参数值,例如SuppressWarnings(value=”all”)
Annotation在哪里使用
可以附加在package、class、mehod、field等上面,相当于给它们添加了额外的辅助信息,我们可以通过反射机制实现对这些元数据的访问
2、内置注解
@Override
定义在java.lang.Override中,此注释只适用于修辞方法,表示一个方法声明打算重写超类中的另一个方法声明
/*
* Copyright (c) 2003, 2006, Oracle and/or its affiliates. All rights reserved.
* ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
*/
package java.lang;
import java.lang.annotation.*;
/**
* 表示方法声明的目的是重写
* 在父类方法声明。如果一个方法被注释
* 此注释类型编译器将生成一个错误
* 除非下列情况中至少有下列情况之一:
*
* <ul><li>
* 该方法是否重写或实现在一个声明中声明的方法
* 超类.
* </li><li>
* 该方法具有一个与该等效的签名
* 任何公开声明的方法在 {@linkplain Object}.
* </li></ul>
*
* @author Peter von der Ahé
* @author Joshua Bloch
* @jls 9.6.1.4 Override
* @since 1.5
*/
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.SOURCE)
public @interface Override {
}
@Depercated
定义在java.lang.Deprecated中,此注释用户修辞方法、属性、类表示不鼓励程序员使用这样的元素,通常是因为它很危险或存在更好的选择
/*
* Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
* ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
*/
package java.lang;
import java.lang.annotation.*;
import static java.lang.annotation.ElementType.*;
/**
* @Deprecated<strong> </strong>程序元素的注释 是一个程序员使用
* 不要使用,通常是因为它是危险的,
* 或因为一个更好的选择存在。编译器发出警告
* 过时的程序元素的使用或重写非过时的代码。
*
* @author Neal Gafter
* @since 1.5
*/
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(value={CONSTRUCTOR, FIELD, LOCAL_VARIABLE, METHOD, PACKAGE, PARAMETER, TYPE})
public @interface Deprecated {
}
@SuppressWarnings
定义在java.lang.SuppressWarnings中,用来抑制编译时的警告信息
/*
* Copyright (c) 2004, 2011, Oracle and/or its affiliates. All rights reserved.
* ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
*/
package java.lang;
import java.lang.annotation.*;
import static java.lang.annotation.ElementType.*;
/**
* 指示将被命名为编译器警告
* 注释的元素(以及在注释中包含的所有程序元素中的
* 元素)。请注意,在一个给定的元素中被抑制的一组警告
* 警告抑制所有包含元素的一个超集。对于
* 例如,如果您注释一个类,以抑制一个警告和注释
* 方法来抑制另一个,这两个警告将被抑制的方法。
*
* <p>作为一种风格,程序员应该经常使用这个注释
* 在最深层嵌套元素,它是有效的。如果你想
* 在特定的方法中抑制警告,您应该批注
* 方法,而不是其类。
*
* @since 1.5
* @author Josh Bloch
*/
@Target({TYPE, FIELD, METHOD, PARAMETER, CONSTRUCTOR, LOCAL_VARIABLE})
@Retention(RetentionPolicy.SOURCE)
public @interface SuppressWarnings {
/**
* 在编译器中被抑制的警告集
* 注释元素。允许重复名称。第二
* 连续出现的名称被忽略。在场的
* 无法识别的警告名称是不一个错误:编译器必须
* 忽略任何警告名称,他们不承认。然而,他们是,
* 如果一个注释包含一个未被识别的,*发出警告
* 警告名称。
*
* <p>编译器供应商应该记录他们支持的警告名称
* 与此注释类型一起使用。鼓励他们合作
* 确保在多个编译器上工作相同的名称。
*/
String[] value();
}
使用这些内置注解
package com.lyy.test.annotion;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
@SuppressWarnings("all")
public class Demo1 /*extends Object*/{
@Override
public String toString(){
return "";
}
@Deprecated
public static void <del>testoo1</del>(){
System.out.println("test.001");
}
public static void test002(){
List list = new ArrayList<>();
}
public static void main(String[] args) {
Date d = new Date();
<del>testoo1</del>();
}
}
@SuppressWanings
定义在java.lang.SuppressWarnings中,用来抑制编译时的警告信息与前两个注释有所不同,你需要添加一个参数才能正确使用,这些参数值都是已经定义好了的,我们选择性的使用就好了
参数 说明
Deprecation 使用了过时的类或方法的警告
Unchecked 执行了为检查的转换时的警告,如使用集合时未指定泛型
Fallthrouqh 当在switch语句使用时发生case穿透
Path 在类路径、源文件路径等中有不存在路径的警告
Serial 当在可序列化的类上缺少serialVersionUID定义时的警告
Finally 任何filally子句不能完成时的警告
All 关于以上所有情况的警告
3、自定义注解和元注解
使用@interface自定义注解时,自动继承了java.lang.annotation.Annotation接口
要点:
@interface用来声明一个注解
格式为:public @interface 注解名(定义体)
其中的每一个方法实际上是声名了一个配置参数
方法的名称就是参数的名称
返回值类型就是参数的类型(返回值类型只能是基本类型、Class、String、enum)
可以通过default来声明参数的默认值
如果只有一个参数成员,一般参数名为value
package com.lyy.test.annotion;
@SxtMyAnnotation
public class Demo2 {
@SxtMyAnnotation(age=19,studentName="泡泡", id=1001,schools={"北京大学","孝感学院"})
public void test(){
}
@SxtAnnotation2("1")
public void test2(){
}
}
package com.lyy.test.annotion;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target(value={ElementType.METHOD,ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface SxtMyAnnotation {
String studentName() default "";
int age() default 18;
int id() default -1;
String[] schools() default {"清华大学","湖北学院"};
}
package com.lyy.test.annotion;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target(value={ElementType.METHOD,ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface SxtAnnotation2 {
String value();
}
最常用到的就是@Target和@Retenion两个元注解
4、小案例
使用反射读取注解的信息,模拟处理注解信息的流程
<span style="font-size:14px;">package com.lyy.test.annotion;
import java.lang.annotation.Annotation;
/**
* 使用反射读取注解的信息,模拟处理注解信息的流程
* @author lyy
*
*/
public class Demo3 {
public static void main(String[] args) {
try {
Class cls = Class.forName("com.lyy.test.annotion.Student");
//获取类的所有注解
Annotation[] annction = cls.getAnnotations();
for (Annotation a :annction) {
System.out.println(a);
}
//获取类中指定的注解
Table tab = (Table)cls.getAnnotation(Table.class);
System.out.println(tab.value());
//获得类的属性的注解
java.lang.reflect.Field f = cls.getDeclaredField("studentName");
Field fx = f.getAnnotation(Field.class);
System.out.println(fx.columName()+"====="+fx.type()+"====="+fx.length());
//根据获取的表名、字段的信息、拼出DDL语句、然后,使用JDBC执行这个SQL,在数据库中生成相关的表
} catch (Exception e) {
e.printStackTrace();
}
}
}
</span>
package com.lyy.test.annotion;
@Table("tb_student")
public class Student {
@Field(columName="id",type="int",length=100)
private int id;
@Field(columName="sname",type="varchar",length=100)
private String studentName;
@Field(columName="age",type="int",length=3)
private int age;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getStudentName() {
return studentName;
}
public void setStudentName(String studentName) {
this.studentName = studentName;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
<strong>
}
</strong>
package com.lyy.test.annotion;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import javax.lang.model.element.Element;
@Target(value={ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface Table {
String value();
}
package com.lyy.test.annotion;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target(value={ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
public @interface Field {
String columName();
String type();
int length();
}
输出结果:
当然光使用自定义注解是不行的,你会发现当我们定义了这些自定义注解后,好像没有什么作用,这是因为没有让注解生效,我们需要利用反射来对注解进行解析生效,这个会在下篇文章中详细讲出!
了解完这些后,你会发现,这个和hibernate的原理是不是很像,使用注解来标识,利用反射获取表名、字段和类型然后动态的创建sql语句封装,最后给程序员们使用,如果自己多做一点,你也可以做出一个简易的hibernate,学完这些发现自己仿佛又发现了一个好玩的东西,学无止境,加油!
案例下载:http://download.csdn.net/detail/qq_14996421/9539972