Java反射、类加载、初始化

简介: Class.getResource(String path) 与 Class.getClassLoader.getResource (String path) 区别:

Java反射、类加载、初始化

一、 先了解一下基本知识:

1.      字节码和机器码是什么,有什么联系

二、反射、类加载器、初始化

2.      反射:

2.1,反射理解:

2.2Class类常用方法:

2.3获取某个类的class 实例四种方法:

2.4反射优点、缺点:

2.5,反射在实际开发中的使用场景:

 

3,类加载ClassLoader:

3.1,类加载器的一个主要方法:getResourceAsStream(String str): 获取类路径下的指定文件的输入流

3.2 类加载器和inputStream 加载配置文件的区别:

3.3 配置文件的路径问题:

3.4  Class.getResource(String path) 与 Class.getClassLoader.getResource (String path) 区别:

 

4,类的加载机制

4.1 类的加载:

4.2类加载的时机

4.3 类加载器分类:

4.4 类加载的双亲委派模型

 


一、 先了解一下基本知识:


1.      字节码和机器码是什么,有什么联系

机器码:顾名思义,机器可以读懂的码;就是0、1啦;原生码(Native Code),是电脑的CPU可直接解读的数据

字节码:字节码(Bytecode)是一种包含执行程序、由一序列 op 代码/数据对 组成的二进制文件字节码是一种中间码,它比机器码更抽象,需要直译器转译后才能成为机器码的中间代码。(ps:OP (操作码operation code))

举例:java bytecode; 首先通过java语言编译器编写代码,生成.java 文件,然后编译器实行javac 指令,生成.class 文件(字节码文件),然后jvm 跨平台,在直译器的翻译下生成机器码,让CPU 解读。(ps:编译器的作用:编译器里我们通过高级java 高级语言,编写代码,理由编译器自带的javac 命令,生成字节码.class 文件,然后再通过编译器的java 命令,运行代码,查看结果。)

联系:字节码是一种中间状态(中间码)的二进制代码(文件)。需要直译器转译后才能成为机器码。

 

二、反射、类加载器、初始化


2.      反射:

2.1,反射理解:照镜子

对象通过反射可以得到的信息:某个类的属性、方法和构造器、某个类到底实现了哪些接口。对于每个类而言,JRE 都为其保留一个不变的 Class 类型的对象。一个 Class 对象包含了特定某个结构(class/interface/enum/annotation/primitive type/void/[])的有关信息。

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

 

在Object类中定义了public final Class getClass()方法,方法返回值的类型是一个Class类。

Class类是Reflection的根源,针对任何你想动态加载、运行的类,唯有先获得相应的Class对象。

2.2Class类常用方法:


0.png


2.3获取某个类的class 实例四种方法:


法1:  // 已知具体的类,调用运行时类的属性:.class;它主要应用于原始数据类型,并且仅在我们知道类的名称时才使用。要创建的Class对象的类名在编译时确定。         Class<?> clazz = String.class;  
法2: //已知某个类的实例,调用该实例的getClass()方法获取Class对象
    String str = new String("string");
    Class c3 = str.getClass();
法3:调用Class的静态方法:forName(String classPath)
    Class<?> clazz = Class.forName(“某个类的类名(路径)”);
法4:方式四:使用类的加载器:ClassLoader
   ClassLoader classLoader = ReflectionTest.class.getClassLoader();
   Class<?> clazz4 = classLoader.loadClass("reflection_mechanism.Person");


2.4反射优点、缺点:

优点:提高了程序的灵活性和扩展性,降低模块的耦合性;例如通过反射机制可以让程序创建和控制任何类的对象,无需提前硬编码目标类;反射是框架的灵魂,使用反射可以避免将代码写死在框架中。

缺点:性能问题:反射相当于一系列解释操作,通知jvm要做的事情,性能比直接的java代码要慢很多。把本来应该在项目启动阶段做的事情,延迟到了项目运行阶段来做。这样就增加了项目运行阶段的系统开销。安全限制:使用反射技术要求程序必须在一个没有安全限制的环境中运行。因为有内部的暴露。

2.5,反射在实际开发中的使用场景:

♢反射使用不好,对性能影响比较,一般项目中很少直接使用,主要用在底层框架中。使用反射机制,①模块开发,通过反射调用对应字节码;②动态代理模式;③spring框架、Hibernate框架等;

反射是框架设计的灵魂。

举例:

  • ① 用 IoC 来注入和组装 bean;
  • ②工厂模式:Factory类中用反射的话,添加了一个新的类之后,就不需要再修改工厂类Factory
  • ③数据库JDBC中通过Class.forName(Driver).来获得数据库连接驱动;
  • ④动态代理、面向切面、bean 对象中的方法替换与增强,也使用了反射;
  • ⑤定义的注解,也是通过反射查找

ps:什么是IoC?--- “控制反转”, 获的对象的过程被反转了,依赖注入。 控制权的转移,应用程序本身不负责依赖对象的创建和维护,而是有外部容器的创建和维护。例如将对象的依赖交给配置文件来配置

 

3,类加载ClassLoader:

3.1,类加载器的一个主要方法:getResourceAsStream(String str): 获取类路径下的指定文件的输入流

3.2 类加载器和inputStream 加载配置文件的区别:

类加载器作用:

加载“.classpath”的资源文件,例如xml、properities文件。注意:该方式只能读取类路径(.classpath)的配置文件

InputStream 读取配置文件:

注:该方式的优点在于可以读取任意路径下的配置文件

3.3 配置文件的路径问题:

类加载器作用:加载“.classpath”的资源文件,例如xml、properities文件

注意:该方式只能读取类路径(.classpath)的配置文件

ps:查看eclipse中的.classpath 文件:Window-》show View-》Navigator(Deprecated)


1.png


  配置文件的路径是个疑惑!!!,从使用相对路径时频繁报错!!!,其实Class.getClassLoader.getResource (String path) 默认是从.classpath根下获取。


2.png3.png


//PolymorphicFunction这一行的完整代码 pro.load(HeroFactories.class.getClassLoader().getResourceAsStream("PolymorphicFunction/Pro.properties"));


3.4  Class.getResource(String path) 与 Class.getClassLoader.getResource (String path) 区别:

Class.getResource(String path)

path不以'/'开头时,默认是从此类所在的包下取资源;

path'/'开头时,则是从项目的ClassPath根下获取资源

class.getResource("/") == class.getClassLoader().getResource("")

Class.getClassLoader.getResource (String path)

♢默认是从ClassPath根下获取,path不能以’/'开头,根是src(bin),classPath文件到配置文件xml或者properties文件;

path不能以'/'开头path是指类加载器的加载范围,在资源加载的过程中,使用的逐级向上委托的形式加载的,'/'表示Boot ClassLoader,类加载器中的加载范围,因为这个类加载器是C++实现的,所以加载范围为null。

4,类的加载机制

4.1 类的加载:

  类的加载:指的是将类的.class字节码文件中的二进制数据读入到jvm内存中,将其放在运行时数据区的方法区内,然后在堆区创建一个 java.lang.Class对象,用来封装类在方法区内的数据结构。


4.png


4.2类加载的时机:

类从被加载到虚拟机内存中开始,到卸载出内存为止,整个生命周期包括以下7个阶段:加载、验证、准备、解析、初始化、使用、卸载。

 其中验证、准备、解析3个部分统称为连接。 因此生命周期可以简记为:加载、连接(验、准、解)、初始化、使用、卸载(加连初使卸)


5.png

4.3 类加载器分类:

加载器主要有四种:

①   jvm启动类加载器bootstrap loader,用c++实现为jvm的一部分(仅指sun的hotspot),负责 JAVA_HOME/lib下面的类库中的类的加载,这个加载器,java程序无法引用到。

②   扩展类加载器Extension Loader,由sun.misc.Launcher$ExtClassLoader类实现,可在java中使用,负责JAVA_HOME/lib/ext 目录和java.ext.dir目录中类库的类的加载。

③   应用系统类加载器Application System Loader,由sun.misc.Louncher$AppClassLoader实现,负责加载用户类路径中类库中的类,如果没有使用自定义的加载器,这个就是默认的 加载器!

④   用户自定义加载器 自己定义从哪里加载类的二进制流。

4.4 类加载的双亲委派模型:

各个加载器都是先委托自己的父加载器加载类,若确实没加载到再自己来加载,于是java默认的类查找加载顺序是自顶向下的,树状结构。


6.png




目录
相关文章
|
2月前
|
Java 编译器
java“变量 x 可能未被初始化”解决
在Java中,如果编译器检测到变量可能在使用前未被初始化,会报“变量 x 可能未被初始化”的错误。解决方法包括:1. 在声明变量时直接初始化;2. 确保所有可能的执行路径都能对变量进行初始化。
274 2
|
29天前
|
监控 Java
Java基础——反射
本文介绍了Java反射机制的基本概念和使用方法,包括`Class`类的使用、动态加载类、获取方法和成员变量信息、方法反射操作、以及通过反射了解集合泛型的本质。同时,文章还探讨了动态代理的概念及其应用,通过实例展示了如何利用动态代理实现面向切面编程(AOP),例如为方法执行添加性能监控。
|
1月前
|
Java
Java的反射
Java的反射。
29 2
|
1月前
|
Java
Java 静态变量的初始化顺序
【10月更文挑战第15天】了解 Java 静态变量的初始化顺序对于正确编写和维护代码至关重要。通过深入理解初始化顺序的原理和细节,我们可以更好地避免潜在的问题,并提高代码的质量和可靠性。
|
2月前
|
存储 Java
[Java]反射
本文详细介绍了Java反射机制的基本概念、使用方法及其注意事项。首先解释了反射的定义和类加载过程,接着通过具体示例展示了如何使用反射获取和操作类的构造方法、方法和变量。文章还讨论了反射在类加载、内部类、父类成员访问等方面的特殊行为,并提供了通过反射跳过泛型检查的示例。最后,简要介绍了字面量和符号引用的概念。全文旨在帮助读者深入理解反射机制及其应用场景。
37 0
[Java]反射
|
3月前
|
安全 Java 索引
Java——反射&枚举
本文介绍了Java反射机制及其应用,包括获取Class对象、构造方法、成员变量和成员方法。反射允许在运行时动态操作类和对象,例如创建对象、调用方法和访问字段。文章详细解释了不同方法的使用方式及其注意事项,并展示了如何通过反射获取类的各种信息。此外,还介绍了枚举类型的特点和使用方法,包括枚举的构造方法及其在反射中的特殊处理。
76 9
Java——反射&枚举
|
2月前
|
安全 Java 测试技术
🌟Java零基础-反射:从入门到精通
【10月更文挑战第4天】本文收录于「滚雪球学Java」专栏,专业攻坚指数级提升,希望能够助你一臂之力,帮你早日登顶实现财富自由🚀;同时,欢迎大家关注&&收藏&&订阅!持续更新中,up!up!up!!
31 2
|
2月前
|
Java 编译器
【一步一步了解Java系列】:子类继承以及代码块的初始化
【一步一步了解Java系列】:子类继承以及代码块的初始化
143 3
|
2月前
|
Java
java构造方法时对象初始化,实例化,参数赋值
java构造方法时对象初始化,实例化,参数赋值
81 1
|
3月前
|
安全 Java API
【Java面试题汇总】Java基础篇——String+集合+泛型+IO+异常+反射(2023版)
String常量池、String、StringBuffer、Stringbuilder有什么区别、List与Set的区别、ArrayList和LinkedList的区别、HashMap底层原理、ConcurrentHashMap、HashMap和Hashtable的区别、泛型擦除、ABA问题、IO多路复用、BIO、NIO、O、异常处理机制、反射