Java编译时注解和运行时注解有啥区别

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Java编译时注解和运行时注解有啥区别相关的知识,希望对你有一定的参考价值。

区别如下:
1)编译时注解,注解内容只存在源文件,在编译期间将被丢弃,不能通过JVM获取注解信息;
2)运行时注解,编译时被存储在.class字节码文件,可以通过JVM运行时获取注解信息(且只限于被RUNTIME注解的注解)。

参考技术A 重写,重载,泛型,分别是在运行时还是编译时执行的

1. 方法重载是在编译时执行的,因为,在编译的时候,如果调用了一个重载的方法,那么编译时必须确定他调用的方法是哪个。如:

当调用evaluate("hello")时候,我们在编译时就可以确定他调用的method #1.

2.
方法的重写是在运行时进行的。这个也常被称为运行时多态的体现。编译器是没有办法知道它调用的到底是那个方法,相反的,只有在jvm执行过程中,才知晓到底是父子类中的哪个方法被调用了当有如下一个接口的时候,我们是无法确定到底是调用父类还是子类的方法

3.
泛型(类型检测),这个发生在编译时。编译器会在编译时对泛型类型进行检测,并吧他重写成实际的对象类型(非泛型代码),这样就可以被JVM执行了。这个过程被称为"类型擦除"。

类型擦除的关键在于从泛型类型中清除类型参数的相关信息,并且再必要的时候添加类型检查和类型转换的方法。

类型擦除可以简单的理解为将泛型java代码转换为普通java代码,只不过编译器更直接点,将泛型java代码直接转换成普通java字节码。类型擦除的主要过程如下:

1). 将所有的泛型参数用其最左边界(最顶级的父类型)类型替换。

2). 移除所有的类型参数。

在编译后变成:

4. 注解。注解即有可能是运行时也有可能是编译时。

如java中的@Override注解就是典型的编译时注解,他会在编译时会检查一些简单的如拼写的错误(与父类方法不相同)等

同样的@Test注解是junit框架的注解,他是一个运行时注解,他可以在运行时动态的配置相关信息如timeout等。

5. 异常。异常即有可能是运行时异常,也有可能是编译时异常。

RuntimeException是一个用于指示编译器不需要检查的异常。RuntimeException
是在jvm运行过程中抛出异常的父类。对于运行时异常是不需要再方法中显示的捕获或者处理的。

已检查的异常是被编译器在编译时候已经检查过的异常,这些异常需要在try/catch块中处理的异常。

6. AOP. Aspects能够在编译时,预编译时以及运行时使用。

1).
编译时:当你拥有源码的时候,AOP编译器(AspectJ编译器)能够编译源码并生成编织后的class。这些编织进入的额外功能是在编译时放进去的。

2). 预编译时:织入过程有时候也叫二进制织入,它是用来织入到哪些已经存在的class文件或者jar中的。

3). 运行时:当被织入的对象已经被加载如jvm中后,可以动态的织入到这些类中一些信息。

7. 继承:继承是编译时执行的,它是静态的。这个过程编译后就已经确定

8. 代理(delegate):也称动态代理,是在运行时执行。
参考技术B /**
1.SOURCE:在源文件中有效(即源文件保留)
2.CLASS:在class文件中有效(即class保留)
3.RUNTIME:在运行时有效(即运行时保留)
*/
@Retention(RetentionPolicy.RUNTIME)
@Retention(RetentionPolicy.SOURCE)
@Retention(RetentionPolicy.CLASS)
@Retention定义了该Annotation被保留的时间长短:某些Annotation仅出现在源代码中,而被编译器丢弃;而另一些却被编译在class文件中;编译在class文件中的Annotation可能会被虚拟机忽略,而另一些在class被装载时将被读取(请注意并不影响class的执行,因为Annotation与class在使用上是被分离的)。本回答被提问者采纳
参考技术C ALU内含电路系统,易于输出端完成简单的普通运算和逻辑运算(比如加法和位元运算)。如果加法运算产生一个对该CPU处理而言过大的结果,在标志暂存器里可能会设置运算溢出(Arithmetic Overflow)标志。

Java注解

一、注解的分类:

1、按照运行机制分:

1)、源码注解:只在源码中存在,.java文件中

2)、编译时注解:在源码和.class文件中都存在 如:@Override @Deprecated @Suppvisewarnings

3)、运行时注解:在运行阶段起作用,会影响运行逻辑的注解 如:@Autowired

 

2、按照来源分:

1)、来自JDK的注解

2)、来自第三方的注解

3)、我们自己定义的注解

 

3、元注解:

注解的注解

 

二、自定义注解

1、使用@interface关键字定义注解

2、成员以无参数无异常方式声明

3、可以用default为成员指定一个默认值

4、成员的类型只能是基本类型、String、Class、Annotation、Enumeration

5、如果注解只有一个成员,则成员名必须取名为value(),在使用时可以忽略成员名和赋值号(=)

6、注解类可以没有成员,没有成员的注解成为标示注解

 

@Target({ElementType.METHOD,ElementType.TYPE})

@Retention(RetentionPolicy.RUNTIME)

@Inherited

@Documented

public @interface Description{

  String desc();

  String author();

  int age() default 18;

}

 

三、元注解

1)、@Target: 注解的作用域

构造方法声明 CONSTRUCTOR、

字段声明FIELD、

局部变量声明LOCAL_VARIABLE、

方法声明METHOD、

包声明PACKAGE、

注解类型声明ANNOTATION_TYPE、

参数声明PARAMETER、

类接口声明TYPE

2)、@Retention:生命周期

SOURCE只在源码显示,编译时会丢弃

CLASS编译时会记录到class中,运行时忽略

RUNTIME运行时存在,可以通过反射读取

3)、@Inherited:允许子类继承

4)、@Documented:生成javadoc时会包含注解信息

 

四、使用自定义注解

1、使用注解的语法:

@<注解名>(<成员名1>=<成员名值1>,<成员名2>=<成员名值2>,...)

@Description(desc="i am eyeColor", author="Mooc Boy", age=19)

public String eyeColor(){

  return "red";

}

 

五、解析注解

概念:通过反射获取类、函数或成员上的运行时注解信息,从而实现动态控制程序运行的逻辑

 

以上是关于Java编译时注解和运行时注解有啥区别的主要内容,如果未能解决你的问题,请参考以下文章

java--自定义注解(注解在编译时生效)

java注释的java注解

java中注解简介

java 编译时注解框架 lombok-ex

Java注解-注解处理器(编译期|RetentionPolicy.SOURCE)

Java注解-注解处理器(编译期|RetentionPolicy.SOURCE)