2022/08/10 吉软 Java基础(23)注解和反射

学习目录

Java注解

一、Java注解概述

二、注解的作用分类

三、注解中的方法

四、三个非常重要的主干类

五、作用在代码上的注解:

六、元注解:

Java反射     

一、反射的概述

二、什么是反射?

三、 java中反射的用法非常非常多,常见的有以下这几个:

获取class对象的三种方法

 二、构造类的实例化对象

反射的应用场景:


Java注解

一、Java注解概述

       注解(Annotation),也叫元数据。一种代码级别的说明。它是JDK1.5及以后版本引入的一个特性,与类、接口、枚举是在同一个层次。它可以声明在包、类、字段、方法、局部变量、方法参数等的前面,用来对这些元素进行说明,注释。

二、注解的作用分类

  • 编写文档: 通过代码里标识的元数据生成文档【生成文档doc文档】
  • 代码分析: 通过代码里标识的元数据对代码进行分析【使用反射】
  • 编译检查: 通过代码里标识的元数据让编译器能够实现基本的编译检查【Override等】

三、注解中的方法

        1、定义方法的格式:String name();

        2、可以有默认值,也可以没有。

             如果没有默认值在使用的时候必须填写对应的值。

             如果需要有默认值,使用default指定默认值。

        3、如果想在使用的时候不指定具体的名字,可以将方法名写为value,如果有多个参数,则                 需要写名字

import java.lang.annotation.*;

/**
 * 这是我们自己创建的注解
 */
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
@Inherited
public @interface MyAnnotation {

    String name() default "tom";
    int age();
    int value();
}

四、三个非常重要的主干类

1. Annotation 接口,定义一些常用的方法

2. ElementType 枚举

  • 用来指定注解的类型。(我的注解要用在哪里?)

3. RetentionPolicy 枚举

  • 它用来指定注解的策略。不同类型的策略指定的注解的作用域不同。

        (1)SOURCE,注解仅存在于编译器处理期间,编译期处理完之后,这个注解就没用了

        (2)CLASS,注解在.class文件中依然有效。

        (3)RUNTIME,编译期是不起作用的,只有在运行期才由JVM读取。

Java自带的注解共10个:

        4个注解在java.lang.annotation,6个注解在java.lang

五、作用在代码上的注解:

1、@Override:检查该方法是否是重写方法。如果返现其父类,或者是引用的接口中没有该方法,会报错

2、@Deprecated:标记的方法,过时的方法。

3、@SuppressWarnings:编辑器忽略警告

4、@SafeVarargs:JDK7支持忽略任何使用参数为泛型变量的方法或构造器产生的警告

5、@FunctionalInterface:JDK8开始支持,表示一个接口为函数式接口

6、@Repeatable:JDK8开始支持,标识某个注解可以在同一个声明上使用多次

  • all:忽略所有警告
  • boxing:忽略装箱、拆箱警告
  • rawtypes:使用生成时没有指定数据类型
  • unchecked:忽略没有进行类型检查操作的警告
  • unused:忽略没有使用的警告

六、元注解:

        元注解就是用来描述注解的注解。一般使用元注解来限制自定义注解的使用范围、生命周期等等。

jdk的中java.lang.annotation包中定义了四个元注解,如下:

  • @Retention:标识这个注解作用域
  • @Documented:标记这个注解是否包含在用户文档中
  • @Target:这个注解可以修饰哪些信息
  • @Inherited:如果一个类用上了@Inherited注解,那么其子类也会继承这个注解

更多有关“注解”的内容访问:  http://t.csdn.cn/jfvcQ


Java反射     

        反射是框架设计的灵魂(使用的前提条件:必须先得到代表的字节码的Class,Class类用于表示.class文件(字节码))

一、反射的概述

        JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。要想解剖一个类,必须先要获取到该类的字节码文件对象。而解剖使用的就是Class类中的方法.所以先要获取到每一个字节码文件对应的Class类型的对象.

二、什么是反射?

        反射就是把java类中的各种成分映射成一个个的Java对象例如:一个类有:成员变量、方法、构造方法、包等等信息,利用反射技术可以对一个类进行解剖,把个个组成部分映射成一个个对象。(其实:一个类中这些成员方法、构造方法、在加入类中都有一个类来描述)


直接举例:

public Map<String, String> getMap(String className) {
    Class clazz = Class.forName(className);
    Constructor constructor = clazz.getConstructor();
    return (Map<String, String>) constructor.newInstance();
}

        这时不管你需要什么Map,只要实现了Map接口,你都能通过getMap获得,只需要传入对应Map的全限定名,例如java.util.HashMap / java.util.LinkedHashMap

三、 java中反射的用法非常非常多,常见的有以下这几个:

  • 在运行时获取一个类的 Class 对象
  • 在运行时构造一个类的实例化对象
  • 在运行时获取一个类的所有信息:变量、方法、构造器、注解

获取class对象的三种方法

1、类名.class:这种获取方式只有在编译前已经声明了该类的类型才能获取到 Class 对象

Class<HashMap> hashMap= HashMap.class;

2、实例.getClass():通过实例化对象获取该实例的 Class 对象

Map<String, String> hashMap = new HashMap<>();
Class<? extends Map> hashMapClass = hashMap.getClass();

3、Class.forName(“类的全限定名”):通过类的全限定名获取该类的 Class 对象

Class<?> hashMap= Class.forName("java.util.HashMap");

 二、构造类的实例化对象

        通过反射构造一个类的实例方式有2种:

1、Class 对象调用newInstance()方法

Class<?> hashMapClass = Class.forName("java.util.HashMap");
HashMap hashMapInstance = (HashMap) hashMapClass.newInstance();

        注意:即使 HashMap已经显式定义了构造方法,通过 newInstance() 创建的实例中,所有属性值都是对应类型的初始值,因为 newInstance() 构造实例会调用默认无参构造器。

2、Constructor 构造器调用newInstance()方法

Class<?> hashMapClass = Class.forName("java.util.HashMap");
Constructor<?> constructor = hashMapClass.getConstructor();
constructor.setAccessible(true);
HashMap newInstance = (HashMap) constructor.newInstance();

        通过 getConstructor(Object… paramTypes) 方法指定获取指定参数类型的 Constructor, Constructor 调用 newInstance(Object… paramValues) 时传入构造方法参数的值,同样可以构造一个实例,且内部属性已经被赋值。

        通过Class对象调用 newInstance() 会走默认无参构造方法,如果想通过显式构造方法构造实例,需要提前从Class中调用getConstructor()方法获取对应的构造器,通过构造器去实例化对象。

 三、获取类的所有信息

1、获取类中的变量(Field)

Field[] getFields():获取类中所有被public修饰的所有变量 Field getField(String
name):根据变量名获取类中的一个变量,该变量必须被public修饰 Field[]
getDeclaredFields():获取类中所有的变量,但无法获取继承下来的变量 Field
getDeclaredField(String name):根据姓名获取类中的某个变量,无法获取继承下来的变量

2、获取类中的方法(Method)

Method[] getMethods():获取类中被public修饰的所有方法
Method getMethod(String name, Class…<?>
paramTypes):根据名字和参数类型获取对应方法,该方法必须被public修饰
Method[] getDeclaredMethods():获取所有方法,但无法获取继承下来的方法
Method getDeclaredMethod(String name, Class…<?>
paramTypes):根据名字和参数类型获取对应方法,无法获取继承下来的方法

3、获取类的构造器(Constructor)

Constuctor[] getConstructors():获取类中所有被public修饰的构造器 Constructor
getConstructor(Class…<?> paramTypes):根据参数类型获取类中某个构造器,该构造器必须被public修饰
Constructor[] getDeclaredConstructors():获取类中所有构造器 Constructor
getDeclaredCnstoructor(class…<?> paramTypes):根据参数类型获取对应的构造器

反射的应用场景:

1、Spring 实例化对象:当程序启动时,Spring 会读取配置文件applicationContext.xml并解析出里

面所有的标签实例化到IOC容器中。

2、反射 + 工厂模式:通过反射消除工厂中的多个分支,如果需要生产新的类,无需关注工厂类,

工厂类可以应对各种新增的类,反射可以使得程序更加健壮。

3、JDBC连接数据库:使用JDBC连接数据库时,指定连接数据库的驱动类时用到反射加载驱动类

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值