Java注解和反射的学习笔记

目录

注解Annotation

什么是注解?

注解的作用

注解元素的数据类型

注解元素的分类

内置注解

元注解——修饰注解的注解

@Documented:执行 javadoc 的时候,标记这些注解是否包含在生成的用户文档中。

自定义注解

 代码示例

静态VS动态语言

动态语言

静态语言

Java 反射 Reflection

 Java 反射的作用

Java 反射的实现方法

利用反射动态创建对象实例

实现反射的类

实现反射的优缺点

 解决方案

Java反射API

反射使用步骤(获取 Class 对象、调用对象方法)

注解和反射的关系

Java的内存分析

类的加载过程


 

注解Annotation

什么是注解?

注解就是代码中的特殊标记,这些标记可以在编译、类加载、运行时被读取,从而做相对应的处理。

注:注释时给人看的,注解是给程序看的,可以被编译器读取。

注解的作用

注解大多时候与反射或者 AOP 切面结合使用,它的作用有很多,比如标记和检查,最重要的一点就是简化代码,降低耦合性,提高执行效率

  1. 提供元数据:注解可以在代码中添加元数据,用于描述、标记和配置代码的特性、属性或行为。通过注解,开发者可以在代码中附加额外的信息,以便在编译时、运行时或其他工具处理过程中进行解析和利用。

  2. 代码生成和处理:许多框架和工具可以读取注解信息,并根据注解执行相应的代码生成和处理操作。例如,基于注解的框架可以根据注解生成数据库模式、生成文档、生成测试代码、实现依赖注入等。

  3. 编译时检查和验证:编译器可以利用注解来进行静态检查和验证。通过定义自定义的注解,并使用注解处理器,可以在编译时对代码进行额外的检查和验证,以确保代码符合特定的约束、规范或安全要求。

  4. 运行时行为和逻辑:注解可以用于在运行时实现特定的行为和逻辑。通过使用反射机制,可以在运行时读取注解信息,并根据注解配置对象的行为、调用特定的方法或触发相应的事件

  5. 文档生成和文档化:注解可以用于生成文档和文档化代码。通过使用特定的注解标记和描述代码的元素,可以生成详细的文档,例如API文档、接口规范、使用说明等。

  6. 框架和扩展机制:注解是许多框架和扩展机制的基础。通过使用注解,开发者可以在框架中进行配置、声明和扩展,以实现特定的行为、逻辑或定制化需求。

注解元素的数据类型

所有基本类型(int,float,boolean,byte,double,char,long,short)

String

Class

enum

Annotation

上述类型的数组

注:声明注解元素时可以使用基本类型但不允许使用任何包装类型,同时注解也可以作为元素的类型,也就是嵌套注解

注解元素的分类

内置注解

  • @Override - 检查该方法是否是重写方法。如果发现其父类,或者是引用的接口中并没有该方法时,会报编译错误。
  • @Deprecated - 标记过时方法。如果使用该方法,会报编译警告。
  • @SuppressWarnings - 用于有选择的关闭编译器对类、方法、成员变量、变量初始化的警告。

JDK7 之后又加了 3 个,@SafeVarargs - Java 7开始支持,忽略任何使用参数为泛型变量的方法或构造函数调用产生的警告。@FunctionalInterface - Java 8 开始支持,标识一个匿名函数或函数式接口。@Repeatable - Java 8 开始支持,标识某注解可以在同一个声明上使用多次。

元注解——修饰注解的注解

  • @Target:用来指定注解的作用域(如方法、类或字段),其中 ElementType 是枚举类型,其定义如下,也代表可能的取值范围 。注,如果 @Target 无指定作用域,则默认可以作用于任何元素上。
  • @Retention:用来指定注解的生命周期,它有三个值,对应 RetentionPolicy 中的三个枚举值,分别是:源码级别(source),类文件级别(class)或者运行时级别(runtime)
  • @Documented:执行 javadoc 的时候,标记这些注解是否包含在生成的用户文档中。
  • @Inherited标记这个注解具有继承性,比如 A 类被注解 @Table 标记,而 @Table 注解被 @Inherited 声明(具备继承性);继承于 A 的子类,也继承 @Table 注解。

自定义注解

所有基本类型(int,float,boolean,byte,double,char,long,short)

String

Class

enum

Annotation

上述类型的数组

注:声明注解元素时可以使用基本类型但不允许使用任何包装类型,同时注解也可以作为元素的类型,也就是嵌套注解

 代码示例

//自定义注解
public class Demo03_CustomAnnotation {
    //注解可以显示赋值,如果没有默认值,就必须给注解赋值
    @MyAnnotation2(name = "王五")
    public void test() {
    }
}

@Target(value = {ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@interface MyAnnotation2 {
    //注解的参数:参数类型+参数名()
    //String name();
    String name() default "";
    int age() default 0;
    int id() default -1;//-1代表不存在
    String[] schools() default {"西部开源","清华大学"};

其中, @interface与interface的区别以及@interface的用法

interface:声明一个Java接口。在接口中只能有常量和抽象方法;接口不可以实例化,接口中的方法没有方法体,继承接口的类必须实现接口中定义的方法。

@interface:一个继承了java.lang.annotation.Annotation接口的自定义注解,定义注释类型。

  • @Interface用来声明一个注解,格式:public @Interface 注解名{定义内容}
  • 其中的每一个方法实际上是声明了一个配置参数
  • 方法的名称就是参数的名称
  • 返回值类型就是参数的类型(返回值只能时基本类型,Class String,enum)
  • 可以通过default来声明参数的默认值
  • 如果只有一个参数成员,一般参数名为value,如果元素的名字为value,使用这个注释的时候,元素的名字和等号可以省略。eg:  public @interface Copyright { String value(); }
  • 没有元素/方法的注释被成为标记(marker)注释类型。标记注释在使用的时候,其后面的括号可以省略
  • 注解元素必须要有值,我们定义注解元素时经常使用空字符串,0作为默认值

静态VS动态语言

动态语言

  • 是一类在运行时可以改变其结构的语言:例如新的函数、对象、甚至代码可以被引进,已有的函数可以被删除或是其他结构上的变化。通俗点说就是在运行时代码可以根据某些条件改变自身结构。
  • 主要动态语言:0bject-C、C#、JavaScript、PHP、Python等。

静态语言

  • 与动态语言相对应的,运行时结构不可变的语言就是静态语言。如Java、C、C++、Java不是动态语言,但Java可以称之为“准动态语言”。即Java有一定的动态性
  • 我们可以利用反射机制获得类似动态语言的特性。Java的动态性让编程的时候更加灵活!

Java 反射 Reflection

1、Java的反射(reflection)机制是指在程序的运行状态中,可以构造任意一个类的对象,可以了解任意一个对象所属的类,可以了解任意一个类的成员变量和方法,可以调用任意一个对象的属性和方法。 这种动态获取程序信息以及动态调用对象的功能称为Java语言的反射机制。

2、加载完类之后,在堆内存的方法区中就产生了一个Class类型的对象(一个对象只有
一个Class类对象
),这个对象就包含了完整的类的结构信息。可以通过这个对象看
类的结构,这个对象就像一面镜子,透过这个镜子看到类的结构,所以,形象的称之
为:反射。

  • 正常方式:引入包名-->通过new实例化-->取得实例化对象
  • 反射方式:实例化对象-->getClass()方法-->得到完整的"包类“名称

 Java 反射的作用

 反射通过Java的java.lang.reflect包提供了一组API,可以在运行时读取和操作类的结构、成员和注解等信息。

反射可以实现动态创建对象、调用方法、访问属性、获取注解信息等功能,使得代码更加灵活和动态。

==这种动态获取的信息以及动态调用对象的方法的功能称为Java语言的反射机制==

  • 在运行时判定任意一个对象所属的类
  • 在运行时构造任意一个类的对象
  • 在运行时判定任意一个类所具有的成员变量和方法
  • 在运行时调用任意一个对象的成员变量和 方法
  • 在运行调用任意一个对象的方法
  • 生成动态代码

Java 反射的实现方法

  1. Class.forName(“类的路径”)
  2. 类名.class
  3. 对象名.getClass()
  4. 基本类型的包装类,可以调用包装类的Type属性来获得该包装类的Class对象

利用反射动态创建对象实例

  1. Class 对象的 newInstance()

    使用 Class 对象的 newInstance()方法来创建该 Class 对象对应类的实例,但是这种方法要求该 Class 对象对应的类有默认的空构造器。

  2. 调用 Constructor 对象的 newInstance()

    先使用 Class 对象获取指定的 Constructor 对象,再调用 Constructor 对象的 newInstance()方法来创建 Class 对象对应类的实例,通过这种方法可以选定构造方法创建实例。

//获取 Person 类的 Class 对象
Class clazz=Class.forName("reflection.Person");
//使用.newInstane 方法创建对象
Person p=(Person) clazz.newInstance();
//获取构造方法并创建对象
Constructor c=clazz.getDeclaredConstructor(String.class,String.class,int.class);
//创建对象并设置属性13/04/2018
Person p1=(Person) c.newInstance("李四","男",20);

实现反射的类

  1. Class:表示正在运行的Java应用程序中的类和接口。
    注意: 所有获取对象的信息都需要Class类来实现。
  2. Field:提供有关类和接口的属性信息,以及对它的动态访问权限。
  3. Constructor:提供关于类的单个构造方法的信息以及它的访问权限。
  4. Method:提供类或接口中某个方法的信息。

实现反射的优缺点

优点:可以实现动态创建对象和编译,体现出很大的灵活性;
缺点: 使用反射性能较低,需要解析字节码,将内存中的对象进行解析。

 解决方案

  1. 通过setAccessible(true)关闭JDK的安全检查来提升反射速度;
  2. 多次创建一个类的实例时,有缓存会快很多
  3. ReflflectASM工具类,通过字节码生成的方式加快反射速度
  4. 相对不安全,破坏了封装性(因为通过反射可以获得私有方法和属性)

Java反射API

反射 API 用来生成 JVM 中的类、接口或则对象的信息

  1. Class 类:反射的核心类,可以获取类的属性,方法等信息。
  2. Field 类:Java.lang.reflec 包中的类,表示类的成员变量,可以用来获取和设置类之中的属性
    值。
  3. Method 类: Java.lang.reflec 包中的类,表示类的方法,它可以用来获取类中的方法信息或
    者执行方法。
  4. Constructor 类: Java.lang.reflec 包中的类,表示类的构造方法。

反射使用步骤(获取 Class 对象、调用对象方法)

  1. 获取想要操作的类的 Class 对象,他是反射的核心,通过 Class 对象我们可以任意调用类的方法。
  2. 调用 Class 类中的方法,既就是反射的使用阶段。
  3. 使用反射 API 来操作这些信息。

注解和反射的关系

  1. 注解和反射可以结合使用,通过反射机制可以读取和处理注解信息,从而实现一些动态行为和逻辑。
  2. 反射可以读取类、方法、字段上的注解信息,并根据注解的值来实现相应的操作
  3. 注解可以提供元数据,帮助反射读取和解释代码的特性和行为,从而实现更灵活、可配置和可扩展的代码逻辑。

Java的内存分析

类的加载过程

类的加载与ClassLoader的理解

  • 19
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值