Java - 注解与反射(小结)

Java - 注解与反射(学习笔记)

注解


Java内置的注解

  • Java 定义了一套注解,共有 7 个,3 个在 java.lang 中,剩下 4 个在 java.lang.annotation 中。

作用在代码上的注解是

  • @Override - 检查该方法是否是重写方法。如果发现其父类,或者是引用的接口中并没有该方法时,会报编译错误。

  • @Deprecated - 标记过时方法。如果使用该方法,会报编译警告。

  • @SuppressWarnings - 指示编译器去忽略注解中声明的警告。

作用在其他注解上的注解(或者说 元注解)是:

  • @Retention - 标识这个注解怎么保存,是只在代码中,还是编入class文件中,或者是在运行时可以通过反射访问。

  • @Documented - 标记这些注解是否包含在用户文档中。

  • @Target - 标记这个注解应该是哪种 Java 成员。

  • @Inherited - 标记这个注解是继承于哪个注解类(默认 注解并没有继承于任何子类)

从 Java 7 开始,额外添加了 3 个注解:

  • @SafeVarargs - Java 7 开始支持,忽略任何使用参数为泛型变量的方法或构造函数调用产生的警告。

  • @FunctionalInterface - Java 8 开始支持,标识一个匿名函数或函数式接口。

  • @Repeatable - Java 8 开始支持,标识某注解可以在同一个声明上使用多次。


如何自定义注解

  • 使用 @interface自定义注解时 , 自动继承了java.lang.annotation.Annotation接口

  • 分析 :

  • @ interface用来声明一个注解 , 格式 : public @ interface 注解名 { 定义内容 }

  • 其中的每一个方法实际上是声明了一个配置参数.

  • 方法的名称就是参数的名称.

  • 返回值类型就是参数的类型 ( 返回值只能是基本类型,Class , String , enum ).

  • 可以通过default来声明参数的默认值 如果只有一个参数成员 ,

  • 一般参数名为value 。(如果value只有一个值时还可以把value去掉)

  • 注解元素必须要有值 , 我们定义注解元素时 , 经常使用空字符串,0作为默认值 .


反射


什么是反射

  话题引入:java的class类在编译执行时,(在内存中)会自动产生一个对应的.Class文件(即Class对象),且一个类在内存中只有对应的一个Class对象。这个Class对象我们无法手动创建,且包含了对应类的整个结构信息,就如同一面镜子,把class类的信息显示在镜子上。我们只能通过这个Class的方法去获取对应class的全部信息方法或操作,而不是直接通过new这个class的对象来调用他的方法。

  我们通过Class拿到对应class的信息过程,就如同对着镜子去操作,通过class映射到Class对象上的信息去操作class,这个通过映射信息操作本体的过程就是反射。

      若把class类比作人,Class是镜子,编译执行比作出门,那么你每次出门都会照一次镜子,镜子上会映射你的影像,你可以通过镜子获得你身上的信息:比如穿的是什么衣服,名牌上的名字等等。这个通过镜子而获得的信息的过程,就称为反射。或是你照着镜子吹头发的时候,你是通过镜子反射的信息去看着头发吹,而不是直接看着头发吹。

会自动产生Class对象的类型有

  • class、interface、[]、[] []、枚举、注解、 primitive type、 void等数据类型在加载时会自动生成一个对应的Class对象

  • 一个数据类型只有一个Class对象,且是加载时自动创建,我们只能获取不能手动创建,获得Class实例的方法:获取Class类的实例


反射的用途

引入概念:java的动态性

引入概念:
动态语言:指在运行时代码可以根据某些条件改变自身结构。如:Object-C、C#、JavaScript、PHP、Python等。
静态语言:与动态语言相对应的,运行时结构不可变的语言就是静态语言。如Java、C、C++。

Java不是动态语言,但Java可以称之为“准动态语言”。我们可以利用 java的反射机制获得类似动态语言的特性。Reflection(反射)是Java被视为动态语言的关键,反射机制允许程序在执行期借助于Reflection API取得任何类的内部信息,并能直接操作任意对象的内部属性及方法。

  • 反射相关的主要API >通过这些类内部的方法实现反射 (重点是Class)

  • java.lang.Class : 代表一个类

  • java.lang.reflect.Method : 代表类的方法

  • java.lang.reflect.Field : 代表类的成员变量

  • java.lang.reflect.Constructor : 代表类的构造器

  • .......

使用反射的主要思想:

  • 我们可以通过反射,即Class对象,来获取对应类的全部信息,并通过获取的信息来操作。

  • 获取方式:通过Class类对象的方法(可查文档)返回的Method、Filed、Constructior对象来获取、调用或操作对应的类的信息、属性或方法。进而还可以获得类、字段等的注解信息。

通过反射(即有了Class对象),能做什么?

以User类为例
大前提:要有User类的Class对象。如:
//获得一个Class对象
//获取通过Class类 获得User类的Class对象
Classc1=Class.forName("test04_reflection.User");//"User类的包路径"
  • 通过Class对象创建一个User类的对象(两种方式):

  • 第一种,无参构造。

通过 User的Class类对象(c1_User) 的newInstance()方法 构建一个 User对象user。
⚠️注意:1、类必须有一个无参数的构造器。2、类的构造器的访问权限要足够。
  • 第二种,有参构造。

通过Class获取User的声明的有参构造器,并通过该构造器构造一个新user
  • 通过Class对象获取方法,并方法对象反向对User类对象进行操作。

  • 通过Class对象获取属性,并通过属性对象反向对User类对象进行操作。

⚠️补充:setAccessible()

  • Method和Field、Constructor对象都有setAccessible()方法。

  • setAccessible作用是启动和禁用访问安全检查的开关。

  • 参数值为true则指示反射的对象在使用时应该取消Java语言访问检查。

  • 提高反射的效率。如果代码中必须用反射,而该句代码需要频繁的被调用,那么请设置为true。

  • 使得原本无法访问的私有成员也可以访问

  • 参数值为false则指示反射的对象应该实施Java语言访问检查

建议:去熟悉下jdk1.8文档关于 Class类、Method类、Field类中封装的方法

反射的优缺点

  • 优点:可以实现动态创建对象和编译,体现出很大的灵活性 !

  • 缺点:通过性能分析,可以得出反射对性能有影响。使用反射基本上是一种解释操作,我们可以告诉JVM,我们希望做什么并且它满 足我们的要求。这类操作总是慢于 直接执行相同的操作。

猜你喜欢

转载自blog.csdn.net/weixin_41606115/article/details/129030915