java反射

反射

反射可以对成员变量,成员方法和构造方法的信息进行编程访问,

功能

在运行时判断任意一个对象所属的类,在运行时构造任意一个类的对象,在运行时判断任意一个类所具有的成员变量和方法,在运行时获取泛型信息,在运行时调用任意一个对象的成员变量和方法,在运行时处理注解,生成动态代理

动态语言:是一类在运行时可以改变其结构的语言,运行时代码可以根据某些条件改变自身结构

静态语言:与动态语言相对应,运行时结构不可变的语言就是静态语言

一个类被加载后,整个类的结构都会被封装到class对象中

Class类

  1. Class本身也是一个类

  2. Class对象只能由系统建立对象

  3. 一个加载的类在JVM中指挥有一个Class实例

  4. 一个Class对象对应的是一个加载到JVM中的一个.class文件

  5. 每个类的实例都会记得自己是由哪一个Class实例所生成的

  6. 通过Class可以完整地得到一个类中的所有被加载的结构

  7. Class类是Reflection的根源,针对任何想动态加载,运行的类,只有先获得对应的Class对象

ClassforName() 返回指定类名的Class对象

newInstance() 调用缺省构造函数,返回Class对象的实例

getName 返回此Class对象所表示的实体(类,接口,数组类或者void)的名称

getSuperClass() 返回当前Class对象的父类的class对象

getinterfaces() 获取当前Class对象的接口

getClassLoader() 返回该类的加载器

getConstructors() 返回一个包含某些Constructor对象的数组

getMethod() 返回一个Method对象,此对象的形参类型为paraType

getDeclaredFields 返回Field对象的一个数组

Java内存

堆:存放new的对象和数组,可以被所有线程共享,不会存放别的对象引用

栈:存放基本变量类型(包含这个基本类型的具体数值),引用对象的变量(会存放这个引用在堆里面的具体地址)

方法区:可以被所有线程共享,包含了所有的class和static变量

类的加载过程

类的加载(Load):将类的class文件读入内存,并为之创建一个Class对象,此过程由类加载器完成

类的链接(Link):将类的二进制数据合并到JRE中

验证:确保加载的类信息符合JVM规范,没有安全方面的问题

准备:正式为类变量(static)分配内存并设置类变量默认初始值的阶段,这些内存都将在方法区中进行分配

解析:虚拟接常量池内的符号引用(常量名)替换为直接引用(地址)的过程

类的初始化(Initialize)JVM负责对类进行初始化

  1. 执行类构造器<clinit>()方法的过程,类构造器<clinit>()方法是由编译期自动手机类中所有类变量的复制动作和静态代码块中的语句合并产生,(类构造器是构造类信息的,不是构造该类对象的构造器)

  2. 当初始化一个类的时候,如果发现其父类还没有进行初始化,则需要先触发其父类的初始化

  3. 虚拟机会保证一个类<clinit>()方法在多线程环境中被正确加锁和同步

####

什么时候会发生类的初始化?

类的主动引用:一定会发生类的初始化

  1. 当虚拟机启动,先初始化main方法所在的类

  2. new一个类的对象

  3. 调用类的静态成员(除了final常量)和静态方法

  4. 使用reflect对类进行反射调用

  5. 当初始化一个类,如果其父类没有被初始化,则会优先初始化他的父类

类的被动引用(不会发生类的初始化)

  1. 当访问一个静态域时,只有真正声明这个域的类才会被初始化,如:当通过子类引用父类的静态变量,不会导致子类初始化

  2. 通过数组定义类引用,不会触发此类的初始化

  3. 引用常量不会触发此类的初始化(常量在链接阶段就存入调用类的常量池中了)

双亲委派机制

逐级向上查找,优先使用最上层中有的包

获取class对象的三种方式

1.Class.forName("全类名") 源代码阶段

2.类名.class 加载阶段

3.对象.getClass 运行阶段

    // 1. 通过forName的方式获取
        Class<?> clazz1 = Class.forName("MyReflect.Student");
        // 2. 通过类名.class的方式获取
        Class clazz2 = Student.class;
        // 3. 通过对象.getClass的方式
        Student s = new Student();
        Class clazz3 = s.getClass();
        System.out.println(clazz1 == clazz2);
        System.out.println(clazz2 == clazz3);

获取构造方法

getConstructors() 返回所有公共构造方法对象的数组

getDeclaredConstructors() 返回所有构造方法对象的数组(包括私有的)

getConstructor() 返回单个公共构造方法对象

getDeclaredConstructor() 返回单个构造方法对象

Constructor类中用于创建对象的方法

getmodifiers() 获取对应的修饰符,返回值是整数型的

T newInstance() 根据指定的构造方法创建对象

setAccessible() 设置为true 表示取消权限的校验 访问检查

  // 1. 获取目标文件的字节码文件
        Class<?> clazz1 = Class.forName("MyReflect.Student");
        // 2. 获取内部的所有的公共构造方法的对象
        Constructor[] constructors = clazz1.getConstructors();
        for (Constructor constructor : constructors) {
            System.out.println(constructor);
        }
        // 获取所有的构造方法
        Constructor[] declaredConstructors = clazz1.getDeclaredConstructors();
        for (Constructor<?> declaredConstructor : declaredConstructors) {
            System.out.println(declaredConstructor);
        }

获取成员变量

getFields() 返回所有公共成员变量对象的数组

getDeclaredFields() 返回所有成员变量对象的数组

getField(String name) 返回单个公共成员变量对象

getDwclaredField(String name) 返回单个成员变量对象

getType 获取成员变量的数据类型

set 赋值

要修改的属性.set(要修改的对象,要修改的值)

如果是私有的则需要提前setAccessible()

get 获取值 要获取的属性值.get(要去获取对应值的对象)

获取成员方法

getMethods() 获取所有公共成员方法对象的数组,包括继承的

getDeclareMethods 获取所有成员方法对象的数组,不包括继承的

getMethod 返回单个公共成员方法对象

getDeclareMethod 返回单个成员方法对象

invoke(用obj对象调用该方法,调用方法传递的参数,没有就不写) 运行方法,返回值没有就不写

通过反射获取泛型

getGenericParameterTypes() 获取泛型参数类型

getActualTypeArguments()获取真实的参数类型

Method s1 = Student.class.getMethod("s1", String.class, Integer.class);
        Type[] genericParameterTypes = s1.getGenericParameterTypes(); // 获取泛型参数类型
        for (Type genericParameterType : genericParameterTypes) {
            if(genericParameterType instanceof ParameterizedType){
                // 获取真实的参数类型
                Type[] actualTypeArguments = (ParameterizedType) genericParameterTypes.getActualTypeArguments(); 
​

getGenericReturnType() // 获取返回值的类型

通过反射获取直接

ORM --->对象关系映射

getAnnotations() 获取注解

获取注解内部的参数

先获取方法(属性),通过getAnnotation方法获取指定注解,然后.getValue获取内部的参数

通过getAnnotation(指定注解.class).value() 即可获取注解内部的值

注解

作用

注解本身有检查和约束的作用

不是程序本身,可以对程序做出解释

可以被其他程序读取

@注释名 可添加一些参数值

内置注解

@Override:定次注解只适用于修饰方法,表示一个方法声明打算重写超类中的另一个方法声明

@Deprecated:次注解可以用于修饰方法,属性,类表示不鼓励程序员使用这样的元素,但是可以使用,通常因为他很危险或者存在更好的选择

@SupperssWarnings:用来抵制编译时的警告信息

元注解

用来解释其他注解的注解

@Target:用于描述注解的适用范围,表示可以在哪些地方使用

作用域:可以指定多个,是一个数组

TYPE类,FIELD字段,METHOD方法,PARAMETED参数,CONSTRUCTOR构造器,LOCAL_VARIABLE本地变量,ANNOTATION_TYPE注解,PACKAGE包,TYPE_PARAMETED类型参数,TYPE_USE用户类型

@Retention:表示需要在什么级别保存该注解信息,用于描述注解的生命周期(SOURCE(源代码级别) < CLASS(class级别) <RUNTIME(运行的时候注解依然有用))表示在什么地方有效

@Documented:说明该注解江北包含在javadoc中

@Inherited:说明子类可以继承父类中的该注解

自定义注解

使用@interface

@Target({ElementType.TYPE , ElementType.METHOD}) // 表示自定义的注解可以在类上和方法上使用
@Retention(RetentionPolicy.RUNTIME) // 表示此自定义注解可以有效至运行期
@interface MyAnnotation{
    // 在自定义注解中定义传递的参数的格式 类型+属性名+()
    String name(); // 表示使用此注解的时候需要传递一个参数,并不是一个抽象方法
    String age() default "1"; // 表示这个要传递的参数,如果有参数就是传递的参数,如果没有就是默认为1
    String value(); // 如果字段名为value,那么在使用此注解的时候,需要传参的时候,可以把value省略,直接写值即可
}

<mirror> <id>alimaven</id> <mirrorOf>central</mirrorOf> <name>aliyun maven</name> <url>http://maven.aliyun.com/nexus/content/repositories/central/</url> </mirror>

<mirror> <id>maven-default-http-blocker</id> <mirrorOf>external:http:*</mirrorOf> <name>Pseudo repository to mirror external repositories initially using HTTP.</name> <url>http://0.0.0.0/</url> <blocked>true</blocked> </mirror> ———————————————— 版权声明:本文为CSDN博主「有意悠悠」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。 原文链接:Maven安装及配置,添加maven到IDEA中_idea添加maven_有意悠悠的博客-CSDN博客

<profile> <id>jdk-1.8</id> <activation> <activeByDefault>true</activeByDefault> <jdk>1.8</jdk> </activation> <properties> <maven.compiler.source>1.8</maven.compiler.source> <maven.compiler.target>1.8</maven.compiler.target> <maven.compiler.compilerVersion>1.8</maven.compiler.compilerVersion> </properties> </profile> ———————————————— 版权声明:本文为CSDN博主「有意悠悠」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。 原文链接:Maven安装及配置,添加maven到IDEA中_idea添加maven_有意悠悠的博客-CSDN博客

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值