Java注解与Typescript装饰器的比较
java注解在形式上和typescript的装饰器写法十分相像,java注解修饰类,类方法,类属性和其他注解,typescript装饰器可以分为修饰类装饰器,成员函数装饰器,成员参数装饰器。两者也存在很大不同,虽然两者都可以修改对象元数据,但是不同类型装饰器会修改修饰的东西,而java的注解不会。
Java注解执行时机
注解没有执行时机的说法,注解有存在生命周期,该周期由元注解定义。
Typescript装饰器执行时机
修饰器对类的行为的改变,是代码编译时发生的(不是TypeScript编译,而是js在执行机中编译阶段),而不是在运行时。这意味着,修饰器能在编译阶段运行代码。也就是说,修饰器本质就是编译时执行的函数。
在Node.js环境中模块一加载时就会执行。
Java注解详细介绍
注解在jdk1.5后引入
新建一个注解类型本质是新建一个接口,该接口继承Annotation接口
package java.lang.annotation;
public interface Annotation {
boolean equals(Object obj);
int hashCode();
String toString();
Class<? extends Annotation\> annotationType();
}
作用在其他注解的注解(或者说 元注解)是:
- @Retention - 标识这个注解怎么保存,是只在代码中,还是编入class文件中,或者是在运行时可以通过反射访问。
- @Documented - 标记这些注解是否包含在用户文档中。
- @Target - 标记这个注解应该是哪种 Java 成员。
- @Inherited - 标记这个注解是继承于哪个注解类(默认 注解并没有继承于任何子类)
新建一个注解类型
新建一个注解类型MyAnnotation1 如下
@Documented
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface MyAnnotation1 {
}
MyAnnotation1的生命周期由@Retention元注解定义
package java.lang.annotation;
public enum RetentionPolicy {
SOURCE, /\* Annotation信息仅存在于编译器处理期间,编译器处理完之后就没有该Annotation信息了 \*/
CLASS, /\* 编译器将Annotation存储于类对应的.class文件中。默认行为 \*/
RUNTIME /\* 编译器将Annotation存储于class文件中,并且可由JVM读入 \*/
}
MyAnnotation1可以定义属性,属性的返回值类型有下列取值
- 基本数据类型
- String
- 枚举
- 注解
- 以上类型的数组
注解的属性可以通过default 设置默认值
@Documented
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface MyAnnotation1 {
String a1();
int a2() default 1;
}
Java注解作用
- Annotation 具有"让编译器进行编译检查的作用"。例如,@SuppressWarnings, @Deprecated 和 @Override 都具有编译检查作用。
- 注解可以帮助我们生成文档 @Documented
- 注解可配合反射使用,减少我们使用配置文件的数量,现在许多框架都开始使用注解来代替配置文件里相关配置,比如springboot里的@Bean和@Compoent,下面是一个反射配合注解的例子
import java.lang.annotation.Annotation;
import java.lang.annotation.Target;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Inherited;
import java.lang.reflect.Method;
/\*\*
\* Annotation在反射函数中的使用示例
\*/
@Retention(RetentionPolicy.RUNTIME)
@interface MyAnnotation {
String\[\] value() default "unknown";
}
/\*\*
\* Person类。它会使用MyAnnotation注解。
\*/
class Person {
/\*\*
\* empty()方法同时被 "@Deprecated" 和 "@MyAnnotation(value={"a","b"})"所标注
\* (01) @Deprecated,意味着empty()方法,不再被建议使用
\* (02) @MyAnnotation, 意味着empty() 方法对应的MyAnnotation的value值是默认值"unknown"
\*/
@MyAnnotation
@Deprecated
public void empty(){
System.out.println("\\nempty");
}
/\*\*
\* sombody() 被 @MyAnnotation(value={"girl","boy"}) 所标注,
\* @MyAnnotation(value={"girl","boy"}), 意味着MyAnnotation的value值是{"girl","boy"}
\*/
@MyAnnotation(value\={"girl","boy"})
public void somebody(String name, int age){
System.out.println("\\nsomebody: "+name+", "+age);
}
}
public class AnnotationTest {
public static void main(String\[\] args) throws Exception {
// 新建Person
Person person \= new Person();
// 获取Person的Class实例
Class<Person\> c \= Person.class;
// 获取 somebody() 方法的Method实例
Method mSomebody \= c.getMethod("somebody", new Class\[\]{String.class, int.class});
// 执行该方法
mSomebody.invoke(person, new Object\[\]{"lily", 18});
iteratorAnnotations(mSomebody);
// 获取 somebody() 方法的Method实例
Method mEmpty \= c.getMethod("empty", new Class\[\]{});
// 执行该方法
mEmpty.invoke(person, new Object\[\]{});
iteratorAnnotations(mEmpty);
}
public static void iteratorAnnotations(Method method) {
// 判断 somebody() 方法是否包含MyAnnotation注解
if(method.isAnnotationPresent(MyAnnotation.class)){
// 获取该方法的MyAnnotation注解实例
MyAnnotation myAnnotation \= method.getAnnotation(MyAnnotation.class);
// 获取 myAnnotation的值,并打印出来
String\[\] values \= myAnnotation.value();
for (String str:values)
System.out.printf(str+", ");
System.out.println();
}
// 获取方法上的所有注解,并打印出来
Annotation\[\] annotations \= method.getAnnotations();
for(Annotation annotation : annotations){
System.out.println(annotation);
}
}
}
输出的结果如下
somebody: lily, 18
girl, boy,
@com.skywang.annotation.MyAnnotation(value=[girl, boy])
empty
unknown,
@com.skywang.annotation.MyAnnotation(value=[unknown])
@java.lang.Deprecated()
以上就是Java注解基础的知识
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。