栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

JavaSE——反射

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

JavaSE——反射

1、反射概述

动态语言

    动态语言:是一类在运行时可以改变其结构的语言:例如新的函数、对象、甚至代码都可以被引进,已有的函数可以被删除,或是其他结构上的变化。通俗来讲就是在运行时代码可以根据某些条件改变自身结构

    主要的动态语言有:C#、Javascript,PHP、Python

静态语言

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

Reflection(反射)是Java被视为动态语言的关键,反射机制允许程序在执行期借助于Reflection API 取得任何类的内部信息,并能直接操作任意对象的内部属性及方法。

1.2、反射的优点与缺点

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

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

1.3、反射相关的主要API

java.lang.Class:代表一个类

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

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

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

1.4、Class类 1.4.2、Class类概述

在Object中定义了以下的方法,由于所有类都继承了Object类,那么此方法将被所有的类继承

public final native Class getClass();

该方法返回值的类型是一个Class类,Class类是Java反射的源头,

Class类是描述类的类

Class本身也是一个类Class对象只能由系统建立对象一个加载的类在JVM中只会有一个Class实例一个Class对象对应的是一个加载到JVM中的一个.class文件每个类的实例都会记得自己由那个Class实例所生成Class类是Reflection的根源,针对任何你想动态加载、运行的类、唯有先获得相应的Class对象 1.4.2、Class类的常用方法

1.4.3、获取Class类的实例

    若已知具体的类,通过类的class属性获取,该方法最为可靠,程序性能最高。

    //1.通过类名.class获取该类的Class对象
    Class userClass = User.class;
    System.out.println(userClass.getName());
    

    一直某个类的实例,调用该实例的getClass()方法获取Class对象

    //2.已知某个类的实例,通过该实例的getClass()方法(注:该方法继承自Object类)获取到Class对象
    User user = new User();
    Class userClass1 = user.getClass();
    System.out.println(userClass1.getName());
    

    已知一个类的全类名,且该类在类路径下,可以通过Class类的静态方法forName()获取,但可能抛出ClassNotFoundException

    //3.使用类的全限定名,通过使用Class类中的静态方法forName()获取
    Class aClass = Class.forName("com.haha.demo.User");
    System.out.println(aClass.getName());
    

    内置基本数据类型可以直接用封装的类名.Type

    //4.内置基本数据类型的封装类可以用类名.Type
    Class aClass1 = Integer.TYPE;
    System.out.println(aClass1.getName());
    

    可以用ClassLoader

2、反射的底层分析 2.1、底层分析的背景

Java内存分析

在Java的内存中,分为堆、栈、方法区三块

堆:

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

栈:

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

方法区(特殊的堆):

可以被所有的线程共享包含了所有的class和static变量 2.2、类的加载

当程序主动使用某个类时,如果该类还未被加载到内存这种,则会通过以下三步对该类进行初始化。

    加载

    首先所有的 .java程序经过Java complier的编译生成 .class文件,当我们需要使用某些类时,Java会将.class文件字节码内容加载到内存中,并将这些静态数据转换成方法区的运行时数据结构,然后生成一个代表这个类的java.lang.Class对象(Class类在加载阶段就已经生成,且加载的每个类都有一个单独的Class对象)!

    链接:是将Java类的二进制代码合并到JVM的运行状态之中的过程

    验证:确保加载的类信息符合JVM的规范,没有安全方面的问题准备:正式为类变量(static)分配内存并设置类变量默认初始值的阶段,这些内存都将在方法区中进行分配。解析:虚拟机常量池内的符号引用(常量名)替换为直接引用(地址)的过程

    初始化:

    执行类构造器()方法的过程,类构造器()方法是由编译器自动收集类中所有类变量的赋值动作和静态代码块中的语句合并产生的。(类构造器是构造类信息的,不是构造该类对象的构造器)。当初始化一个类的时候,如果发现其父类还没有进行初始化,则需要先触发其父类的初始化虚拟机会保证一个类的()方法在多线程环境中正确的加锁和同步。

2.3、什么时候发生类初始化

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

当虚拟机启动时,先初始化main方法所在的类new一个类的对象调用类的静态成员(除final常量)和静态方法使用java.lang.reflect包的方法对类进行反射调用当初始化一个类,如果其父类没有被初始化,则会先初始化其父类 类的被动引用(不会发生类的初始化)

当我们访问一个静态域时,只有真正声明这个域的类才会被初始化。如:当通过子类引用父类的静态变量,不会导致子类初始化。通过数组定义类的引用,不会出发此类的初始化引用常量(final)不会出发此类的初始化(常量在链接阶段就存入调用类的常量池中了) 2.4、类加载器的作用

类加载的作用:将class文件字节码内容加载到内存中,并将这些静态数据转换成方法区的运行时数据结构,然后在堆中生成一个代表这个类的java.lang.Class对象,作为方法区中类数据的访问入口。

类缓存:标准的JavaSE类加载器可以按照要求查找类,但一旦某个类被加载到类加载器中,它将维持加载一段时间。不过JVM垃圾回收机制可以回收这些Class对象。

JVM定义了如下类型的类的加载器

    引导类加载器:用C++进行编写的,是JVM自带的类加载器,负责Java平台核心库,用来装载核心类库,该加载器无法直接获取。扩展类加载器:负责jre/lib/ext目录下的jar包装入工作库
    中,它将维持加载一段时间。不过JVM垃圾回收机制可以回收这些Class对象。

JVM定义了如下类型的类的加载器

    引导类加载器:用C++进行编写的,是JVM自带的类加载器,负责Java平台核心库,用来装载核心类库,该加载器无法直接获取。扩展类加载器:负责jre/lib/ext目录下的jar包装入工作库系统类加载器:负责java-classpath所指目录下的类与jar包装入工作,是最常用的加载器。
转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/770098.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号