ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

JavaSE:注解&反射

2021-12-21 01:00:07  阅读:137  来源: 互联网

标签:反射 Class 获取 实例 参数 注解 JavaSE class


Annotation-注解

概述

Annotation 是 JDK 5.0 引入的技术。

  1. 作用

    • 对程序做出解释(该作用类似 注释-comment);
    • 可以被程序读取(如 编译器)。
  2. 格式:@注解名 (参数)

    // 实例
    @Override
    @SuppressWarnings(value = "unchecked")
    
  3. 使用范围

    • 在package、class、method、field等的上方使用;
    • 可以通过反射机制来访问。

内置注解

  1. @Override:重写超类方法;
  2. @Deprecated:方法不建议使用;
  3. @SuppressWarnings:抑制编译时的警告信息。

元注解

元注解 (meta-annotation) 负责注解其它的注解

Java 定义了 4 个元注解:

  1. @Documented:生成 JavaDoc 文档
  2. @Retention:保留级别(在哪里有效)
    • SOURCE:源码
    • CLASS:类
    • RUNTIME:运行时
  3. @Target:使用范围(在哪里使用)
    • TYPE
    • FILED
    • METHOD
    • PARAMETER
    • CONSTRUCTOR
    • LOCAL_VARIABLE
    • ANNOTATION_TYPE
    • PACKAGE
    • 1.8 引入
      • TYPE_PARAMETER
      • TYPE_USE
  4. @Inherited:子类可以继承父类中的该注解

自定义注解

使用 @interface 自定义注解,自动实现接口java.lang.annotation.Annotaion

  1. 声明格式

    @元注解
    public @interface 注解名{
        参数类型 参数名();
    }
    
  2. 方法,实际上是声明一个参数;

    • 方法名即参数名;
    • 方法返回值类型即参数返回值类型,且只能是基本类型
    • 可以通过 default 来声明默认值,通常用空串和 0;
  3. 如果只有一个参数,参数名为 value。在使用注解的时候可以省略 value=""

实例1.1

  • @Documented:无
  • @Retention:源码范围;
  • @Target:METHOD (方法);
  • @Inherited:无
  • 参数个数:2
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface MyAnnotation {
    int id();
    String name();
}

测试

  1. 注解只能在方法上使用,在其它位置使用会报错

    • 在类上使用

      image-20211217210413695

    • 在本地变量使用

      image-20211217210604453

  2. 使用时必须给参数赋值,并且指明参数名(可以不按参数的声明顺序来赋值)

    • 不赋值 / 没有全部赋值

      image-20211217210854964

    • 没有指明参数名

      image-20211217211037400

实例1.2

  • 在实例1的基础上,设置参数默认值。
@Retention(RetentionPolicy.SOURCE)
@Target(ElementType.METHOD)
public @interface MyAnnotation {

    int id() default 0;
    String name() default "";
}

测试

  • 没有显式赋值的参数,为默认值

    image-20211217211453337

  • 给部分参数赋值

    image-20211217211508064

实例2

  • @Documented:有
  • @Retention:运行时范围;
  • @Target:TYPE (类型)、方法 (METHOD);(用数组把多个级别括起来)
  • @Inherited:有
  • 参数个数:1,以 value 作为属性名
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE, ElementType.METHOD})
public @interface MyAnnotation2 {

    String value();
}

测试

image-20211217212723530

  1. 在类、方法上方都可以使用;
  2. 使用时可以省略参数名:即无需指定 (value ="xxx") ,直接 ("xxx") 赋值。

Reflection-反射

概述

动态语言 & 静态语言

  • 动态语言:运行时可以改变结构,如 Object-C、C#、JS、PHP、Python;
  • 静态语言:相对于动态语言,运行时结构不可变,如 Java、C、C++。

反射

Java 可以称为准动态语言反射机制使 Java 具有动态性;

  • 使用 Reflection API 获取类的内部信息,操作对象的内部属性和方法;

    image-20211220220022180

  • 功能

    1. 在运行时判断任意一个对象所属的类
    2. 在运行时构造任意一个类的对象
    3. 在运行时判断 / 调用任意一个类所具有的成员变量和方法
    4. 在运行时获取泛型信息
    5. 在运行时处理注解
    6. 生成动态代理
    7. ...
  • 优缺点

    • 优点:动态创建对象和编译,体现出很大的灵活性;
    • 缺点:对性能有影响。反射是一种解释操作,即告诉 JVM 要做什么,这类操作慢于直接执行相同的操作。

主要API

  • java.lang.Class:类
  • java.lang.ref.ect.Method:方法
  • java.lang.reflect.Field:成员变量
  • java.lang.reflect.Constructor:构造器

Class类-反射对象

说明

一个类被加载之后,在堆内存的方法区中产生一个 Class实例

  1. 每个类的实例,都可以获取自己的 Class类;
    • Student类的实例可以通过 getClass()方法,获取 Class对象;
  2. 每个类只有一个 Class对象实例,且 Class 本身也是一个类;
    • 即使 Student类 有很多个实例:student1、student2等,其 Class对象 是唯一的;
  3. Class对象中包含了类的所有结构:类名、属性、方法、构造器、实现的接口等;
  4. Class类 是 Reflection 的根源,只有获取到 Class对象 才能动态加载和运行对应的类。

Class类的常用方法

  1. 获取Class对象:forName

  2. 获取父类Class对象:getSuperClass

  3. 获取实现的接口:getInterfaces

  4. 获取类加载器:getClassLoader

  5. 创建实例:newInstance

  6. 对象内部

    1. 获取构造器:getConstructors
    2. 获取方法:getMethod
    3. 获取属性:getDeclaredFields
    4. 获取类名:getName

获取Class实例的方式

  1. 已知类名:类名.class
  2. 已知类的实例:实例名.getClass()
  3. 已知全类名:Class.forName( 全类名 )
  4. 已知子类Class对象:子类.getSuperclass()
    • :子类也可以通过以上方式,获取Class对象
  5. ClassLoader获取(在之后讲解)

实例

  • 以 Person 类为例,Student 是 Person 的子类
Person p = new Person();

// 1、已知类名
Class<Person> class1 = Person.class;
// 2、已知对象
Class<? extends Person> class2 = p.getClass();
// 3、已知全类名
Class<?> class3 = Class.forName("indi.jaywee.Person");
// 4、已知子类Class:假设Student.class是已知的
Class<? super Student> class4 = Student.class.getSuperclass();

image-20211221000816670

不同类型的Class实例

  1. 类 (class):Class本身、外部类、内部类、局部内部类、匿名列不累
  2. 接口 (interface)
  3. 数组:一维、二维、...
  4. 枚举 (enum)
  5. 注解 (annotation)
  6. 基本数据类型 (primitive type)
  7. void

实例

// 类
Class<Class> class1 = Class.class;
Class<Person> class11 = Person.class;
// 接口
Class<Comparable> class2 = Comparable.class;
// 数组
Class<int[]> class3 = int[].class;
Class<int[][]> class33 = int[][].class;
// 枚举
Class<ElementType> class4 = ElementType.class;
// 注解
Class<Override> class5 = Override.class;
// 基本数据类型
Class<Double> class6 = Double.class;
// void
Class<Void> class7 = void.class;

image-20211221005232180

未完待续

标签:反射,Class,获取,实例,参数,注解,JavaSE,class
来源: https://www.cnblogs.com/secretmrj/p/15713589.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有