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注解基础的知识


lyh1091106900
1 声望0 粉丝