注解与反射01
注解
注意:注解和反射是所有框架都要用的底层技术。
说到注解
,必然会想起注释
。
注释(comment)
:顾名思义是给开发者来查看的。
注解(annotation)
:除了给开发者查看外,还给程序看与读取。
注解入门
- 什么是注解?
- Annotation 是从JDK 5.0开始引入的新技术;
- Annotation 的作用:
- 不是程序本身,可以对程序做出解释(这一点和注释 (comment) 没什么区别 )
可以被其他程序(比如:编译器等)读取
- Annotation 的格式:
- 注解是以 “
@注释名
” 在代码中存在的,还可以添加一些参数值,例如:@SuppressWarning(value=" unchecked ")
- 注解是以 “
- Annotation 在那里使用?
- 可以附加在
package,class,method,field
等上面,相当于给他们添加了额外的辅助信息,我们可以通过反射机制编程
实现对这些元数据的访问。
- 可以附加在
// 示例
public class Test01 extends Object{
// 定义一个类默认继承Object类,不写默认也继承Object
// @Override 重写的注解
// 注解还有约束的作用,例如下面的toString()方法写成tostring()会发生报错!
@Override
public String toString() {
return super.toString();
}
}
内置注解
三个常用的内置注解:
@Override(重写)| @Deprecated(废弃) | @SuppressWarnings(镇压警告)
@Override
:定义在Java.lang.Override
中,此注释只适用于修辞方法,表示一个方法声明打算重写超类中的另一个方法声明。@Deprecated
:定义在Java.lang.Deprecated
中,此注释可以用于修辞方法,属性,类,表示不鼓励程序员使用这样的元素,通常是因为它很危险或者存在更好的选择。@SuppressWarnings
:定义在Java.lang.SuppressWarnings
中,用来抑制编译时的警告信息。- 与前两个注释有所不同,你需要添加一个参数才能正确使用,这些参数都是已经定义好了的,我们选择性的使用就好了。
@SuppressWarnings("all")
@SuppressWarnings("unchecked")
@SuppressWarnings(value={"unchecked","deprecation"})
- 等等。
// @Deprecated 不推荐程序员使用,但是可以使用,或者存在更好的方式
@SuppressWarnings("all")// 不推荐使用
@Deprecated
public static void test(){
System.out.println("Deprecated");
}
public static void main(String[] args) {
test();//已过期
}
查看三个内置注解的源码:
package java.lang;
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.SOURCE)
public @interface Override {
}
package java.lang;
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(value={CONSTRUCTOR, FIELD, LOCAL_VARIABLE, METHOD, PACKAGE, PARAMETER, TYPE})
public @interface Deprecated {
}
package java.lang;
@Target({TYPE, FIELD, METHOD, PARAMETER, CONSTRUCTOR, LOCAL_VARIABLE})
@Retention(RetentionPolicy.SOURCE)
public @interface SuppressWarnings {
/**
* The set of warnings that are to be suppressed by the compiler in the
* annotated element. Duplicate names are permitted. The second and
* successive occurrences of a name are ignored. The presence of
* unrecognized warning names is <i>not</i> an error: Compilers must
* ignore any warning names they do not recognize. They are, however,
* free to emit a warning if an annotation contains an unrecognized
* warning name.
*
* <p> The string {@code "unchecked"} is used to suppress
* unchecked warnings. Compiler vendors should document the
* additional warning names they support in conjunction with this
* annotation type. They are encouraged to cooperate to ensure
* that the same names work across multiple compilers.
* @return the set of warnings to be suppressed
*/
String[] value();
}
元注解
- 元注解的作用就是负责注解其他注解,Java定义了4个标准的meta-annotation类型,他们被用来提供对其他annotation类型做说明。
- 这些类型和他们所支持的类在
java.lang.annotation
包中可以找到(@Target,@Retention,@Documented,@Inherited
)- @Target:用于描述注解的使用范围(即:被描述的注解可以用在什么地方)
- @Retention:表示需要在什么级别保存该注释信息,用于描述注解的生命周期
- SOURCE < CLASS < RUNTIME
- @Document:说明该注解将被包含在javadoc中
- @Inherited:说明子类可以继承父类中的注解
各注解源码:
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Target {
/**
* Returns an array of the kinds of elements an annotation type
* can be applied to.
* @return an array of the kinds of elements an annotation type
* can be applied to
*/
ElementType[] value();
}
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Retention {
/**
* Returns the retention policy.
* @return the retention policy
*/
RetentionPolicy value();
}
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Documented {
}
其中@Target中的参数值类型有:
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
}
其中@Retention中的参数类型有:
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.
*/
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.
*
* @see java.lang.reflect.AnnotatedElement
*/
RUNTIME
}
测试元注解+自定义简单注解
// 测试元注解+测试自定义元注解
public class Test02 {
@MyAnnotation
private void test(){}
}
// 定义一个注解
// 一个小的注意点:一个类中只能有一个公共的方法
//public @interface MyAnnotation{
//@Target (目标) 表示我们的注解可以用在哪些地方。
// value值可以是一个数组【枚举其实就相当于数组的值!】
@Target(value = {ElementType.METHOD,ElementType.TYPE})
//@Retention 表示我们的注解在什么地方还有效。
// 规定:runt ime > class > source
@Retention(value = RetentionPolicy.RUNTIME)
// @Document 表示是否将我们的注解生成在javadoc中
@Documented
//@Inherited 表示子类可以继承父类的注解
@Inherited
@interface MyAnnotation{
}
自定义注解
- 使用
@interface
自定义注解时,自动继承了Java.lang.annotation.Annotation
接口 - 分析:(
着重记忆
)- @interface 用来声明一个注解,格式:public @interface 注解名{ 定义内容 }
- 其中的每一个方法实际上是声明了一个配置参数。
- 方法的名称就是参数的名称。
- 返回值类型就是参数的类型(返回值只能是基本类型:class,string,enum)
- 可以通过default 来声明参数的默认值
- 如果只有一个参数成员,一般参数名为value
- 注解元素必须要有值,我们定义注解元素时,经常使用空字符串,0作为默认值
实战练习
// 自定义注解
public class Test03 {
//注解可以显示赋值,如果没有默认值,我们就必须给注解赋值。
@MyAnnotation2(name = "#倾·浪漫老爷#Yolo-Qing",age = 18)
public void test() {
}
@MyAnnotation3(value = "")
public void test1() {
}
}
@Target(value = {ElementType.TYPE,ElementType.METHOD})
@Retention(value = RetentionPolicy.RUNTIME)
@interface MyAnnotation2{
// 注解的参数:参数类型 + 参数名();
// 一定要注意:在注解中的一定不是方法,而是参数与参数名
String name() default "";
int age() default 0;
int id() default -1;//如果默认值为-1,代表不存在;类似indexof:如果找不到就返回-1
// 数组类型
String[] school() default {"清华大学","宁波大学"};
}
@Target(value = {ElementType.TYPE,ElementType.METHOD})
@Retention(value = RetentionPolicy.RUNTIME)
@interface MyAnnotation3{
// 如果参数只有一个时,默认参数名称为value值。
String value() ;
}