- 一. 反射机制
- 2.1 反射快速入门
- 2.2 反射机制
- 2.3 反射和传统的方法时间对比
- 2.3.1 时间复杂度对比
- 2.3.1 反射代码优化
- 二. class类
- 2.1 `Class`类的基本介绍
- 2.1.1 Class类图
- 2.1.1 Class类加载方法
- 2.1.3 对于某个类的`Class`类对象,在中只有一份,因此类只加载一次
- 2.1.4 每个类的实例都会记得自己是由哪个`Class`实例所生成
- 2.1.5 通过`Class`可以完整地得到一个类的完整结构,通过一系列`API`
- 2.1.6 Class对象是存放在堆中的
- 2.1.7 类的字节码二进制数据,放在方法区的,有的地方称为类的元数据
- 2.2 获取Class类对象
- 2.3 哪些类型有Class对象
- 三. 类加载
- 四. 反射获取类的结构信息
- 五. 反射相关类
- 六. class类常用方法
2.1 反射快速入门
- (1). 根据配置文件调用源代码的信息,在不更改源代码,只需要更改配置文件,就可以实现功能的实现。
- (2). 这样的需求在学习框架时特别多(开闭原则:不修改源代码,扩容功能)
各文件层次结构
re.properties配置文件:
classfullpath=com.hspedu.Cat method=hi
Cat类猫:
package com.hspedu;
public class Cat {
private String name = "招财猫";
private String cry = "喵喵喵";
public void hi(){
//常用方法
System.out.println("hi" + name);
}
public void cry(){
System.out.println("cry" + cry);
}
}
Java源代码:
package com.hspedu.reflection.question;
import com.hspedu.Cat;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Properties;
public class ReflectionQuetion {
public static void main(String[] args) throws IOException, ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchMethodException, InvocationTargetException {
//根据配置文件re.properties指定信息,创建Cat对象并调用方法hi
//1.使用传统方法 使用new创造对象
Cat cat = new Cat();
cat.hi();
@SuppressWarnings({"all"})
//2.使用配置文件读取配置信息
Properties properties = new Properties();
properties.load(new FileInputStream("src\re.properties"));
String classfullpathName = properties.get("classfullpath").toString();
String methodName = properties.get("method").toString();
System.out.println("classfullpath=" + classfullpathName);
System.out.println("method=" + methodName);
//这里的classfulpath 还有 method 读取的仅仅是配置文件的字符串信息,而非真正的类。
//目前的策略,没有合适的可以解决这样的问题。只能通过:配置信息 + 反射机制 解决这样的问题。
//3.利用反射机制创建对象
// (1).加载类,返回class类型的对象clc
Class clc = Class.forName(classfulpathName); //注意了,这里没有双引号,直接采用的名字
// (2).通过clc类创建类的对象实例
Object o = clc.newInstance();
System.out.println("o的运行类=" + o.getClass());
// (3).通过clc得到方法对象
Method method = clc.getMethod(methodName);
method.invoke(o);
}
}
仿真结果:
"C:Program FilesJavajdk1.8.0_152binjava.exe" "-javaagent:D:软件下载ideaideaIntelliJ IDEA 2021.1libidea_rt.jar=52611:D:软件下载ideaideaIntelliJ IDEA 2021.1bin" -Dfile.encoding=UTF-8 -classpath "C:Program FilesJavajdk1.8.0_152jrelibcharsets.jar;C:Program FilesJavajdk1.8.0_152jrelibdeploy.jar;C:Program FilesJavajdk1.8.0_152jrelibextaccess-bridge-64.jar;C:Program FilesJavajdk1.8.0_152jrelibextcldrdata.jar;C:Program FilesJavajdk1.8.0_152jrelibextdnsns.jar;C:Program FilesJavajdk1.8.0_152jrelibextjaccess.jar;C:Program FilesJavajdk1.8.0_152jrelibextjfxrt.jar;C:Program FilesJavajdk1.8.0_152jrelibextlocaledata.jar;C:Program FilesJavajdk1.8.0_152jrelibextnashorn.jar;C:Program FilesJavajdk1.8.0_152jrelibextsunec.jar;C:Program FilesJavajdk1.8.0_152jrelibextsunjce_provider.jar;C:Program FilesJavajdk1.8.0_152jrelibextsunmscapi.jar;C:Program FilesJavajdk1.8.0_152jrelibextsunpkcs11.jar;C:Program FilesJavajdk1.8.0_152jrelibextzipfs.jar;C:Program FilesJavajdk1.8.0_152jrelibjavaws.jar;C:Program FilesJavajdk1.8.0_152jrelibjce.jar;C:Program FilesJavajdk1.8.0_152jrelibjfr.jar;C:Program FilesJavajdk1.8.0_152jrelibjfxswt.jar;C:Program FilesJavajdk1.8.0_152jrelibjsse.jar;C:Program FilesJavajdk1.8.0_152jrelibmanagement-agent.jar;C:Program FilesJavajdk1.8.0_152jrelibplugin.jar;C:Program FilesJavajdk1.8.0_152jrelibresources.jar;C:Program FilesJavajdk1.8.0_152jrelibrt.jar;E:刘建成javaprojectProoutproductionPro" com.hspedu.reflection.question.ReflectionQuetion hi招财猫 classfullpath=com.hspedu.Cat method=hi o的运行类=class com.hspedu.Cat ===================== hi招财猫 Process finished with exit code 0
修改 re.properties 配置文件,而其他的不要动:
classfullpath=com.hspedu.Cat method=cry
修改 re.properties 配置文件后的仿真结果:
"C:Program FilesJavajdk1.8.0_152binjava.exe" "-javaagent:D:软件下载ideaideaIntelliJ IDEA 2021.1libidea_rt.jar=53025:D:软件下载ideaideaIntelliJ IDEA 2021.1bin" -Dfile.encoding=UTF-8 -classpath "C:Program FilesJavajdk1.8.0_152jrelibcharsets.jar;C:Program FilesJavajdk1.8.0_152jrelibdeploy.jar;C:Program FilesJavajdk1.8.0_152jrelibextaccess-bridge-64.jar;C:Program FilesJavajdk1.8.0_152jrelibextcldrdata.jar;C:Program FilesJavajdk1.8.0_152jrelibextdnsns.jar;C:Program FilesJavajdk1.8.0_152jrelibextjaccess.jar;C:Program FilesJavajdk1.8.0_152jrelibextjfxrt.jar;C:Program FilesJavajdk1.8.0_152jrelibextlocaledata.jar;C:Program FilesJavajdk1.8.0_152jrelibextnashorn.jar;C:Program FilesJavajdk1.8.0_152jrelibextsunec.jar;C:Program FilesJavajdk1.8.0_152jrelibextsunjce_provider.jar;C:Program FilesJavajdk1.8.0_152jrelibextsunmscapi.jar;C:Program FilesJavajdk1.8.0_152jrelibextsunpkcs11.jar;C:Program FilesJavajdk1.8.0_152jrelibextzipfs.jar;C:Program FilesJavajdk1.8.0_152jrelibjavaws.jar;C:Program FilesJavajdk1.8.0_152jrelibjce.jar;C:Program FilesJavajdk1.8.0_152jrelibjfr.jar;C:Program FilesJavajdk1.8.0_152jrelibjfxswt.jar;C:Program FilesJavajdk1.8.0_152jrelibjsse.jar;C:Program FilesJavajdk1.8.0_152jrelibmanagement-agent.jar;C:Program FilesJavajdk1.8.0_152jrelibplugin.jar;C:Program FilesJavajdk1.8.0_152jrelibresources.jar;C:Program FilesJavajdk1.8.0_152jrelibrt.jar;E:刘建成javaprojectProoutproductionPro" com.hspedu.reflection.question.ReflectionQuetion hi招财猫 classfullpath=com.hspedu.Cat method=cry o的运行类=class com.hspedu.Cat ===================== cry喵喵喵 Process finished with exit code 0
2.2 反射机制
-
- 反射机制允许程序在执行期间借助于Reflection API取得任何类的内部信息(比如:成员变量,构造器,成员方法等等),并能操作对象的属性及方法。反射再设计模式和框架底层都会用到。
-
- 加载完类之后,在堆之中就会产生一个Class类型的对象,这个对象包含了类的完整的结构信息。通过这个镜子得到类的结构,所以,形象的称之为:反射。
-
- 优点:可以动态的创建和使用对象。没有反射技术,框架技术就失去了底层支撑。
-
- 缺点:使用反射基本是解释执行,对执行速度有影响。
- 缺点:使用反射基本是解释执行,对执行速度有影响。
- java.lang.Class: 代表一个类,Class对象表示某个类加载后再堆中的对象
- java.lang.reflect.Method: 代表类的方法,Method对象表示某个类的方法
- java.lang.reflect.Field: 代表类的成员变量,Field对象表示某个类的成员变量
- java.lang.reflect.Constructor: 代表类的构造方法,Constructor对象表示构造器
这些类在java.lang.reflec
java.lang.reflect.Field的使用:
System.out.println("========= getField ================");
//得到name字段:
Field nameField = clc.getField("age"); //getFiled不能得到私有的属性
System.out.println(nameField.get(o)); //传统写法 对象.成员变量
java.lang.reflect.Constructor的使用:
// Cat 修改版本
package com.hspedu;
public class Cat {
private String name = "招财猫";
private String cry = "喵喵喵";
public int age = 10;
//增加 Cat 的构造器函数
public Cat(String name){
this.name = name;
}
//Cat没有了默认的无参构造函数,得重新建立一个无参数的构造函数
public Cat(){
}
public void hi(){
//常用方法
System.out.println("hi" + name);
}
public void cry(){
System.out.println("cry" + cry);
}
}
//具体代码:
System.out.println("========= java.lang.reflect.Constructor ================");
//java.lang.reflect.Constructor: 代表类的构造方法,Constructor对象表示构造器
Constructor constructor = clc.getConstructor(); //()中可以指定构造器的参数类型,返回无参构造器
System.out.println(constructor);
Constructor constructor1 = clc.getConstructor(String.class); //这里传入的String.class就是String类的class对象
System.out.println(constructor1); //输出带形式参数String的构造器
//仿真结果: ========= java.lang.reflect.Constructor ================ public com.hspedu.Cat() public com.hspedu.Cat(java.lang.String)
2.3 反射和传统的方法时间对比
2.3.1 时间复杂度对比
时间对比源代码:
package com.hspedu.reflection0;
import com.hspedu.Cat;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
public class Reflection02 {
public static void main(String[] args) throws ClassNotFoundException, InvocationTargetException, InstantiationException, IllegalAccessException, NoSuchMethodException {
m1();
m2();
}
//传统方法来调用hi
public static void m1(){
Cat cat = new Cat();
long start = System.currentTimeMillis();
for(int i=0; i<90000000; i++){
cat.hi();
}
long end = System.currentTimeMillis();
System.out.println("传统 m1 方法来调用 hi 耗时=" + (end - start));
}
//反射机制调用方法
public static void m2() throws ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchMethodException, InvocationTargetException {
Class> clc = Class.forName("com.hspedu.Cat");
Object o = clc.newInstance();
Method hi = clc.getMethod("hi");
long start = System.currentTimeMillis();
for(int i=0; i<90000000; i++){
hi.invoke(o);
}
long end = System.currentTimeMillis();
System.out.println("反射机制的 m2 方法来调用 hi 耗时=" + (end - start));
}
}
仿真结果:
"C:Program FilesJavajdk1.8.0_152binjava.exe" "-javaagent:D:软件下载ideaideaIntelliJ IDEA 2021.1libidea_rt.jar=53251:D:软件下载ideaideaIntelliJ IDEA 2021.1bin" -Dfile.encoding=UTF-8 -classpath "C:Program FilesJavajdk1.8.0_152jrelibcharsets.jar;C:Program FilesJavajdk1.8.0_152jrelibdeploy.jar;C:Program FilesJavajdk1.8.0_152jrelibextaccess-bridge-64.jar;C:Program FilesJavajdk1.8.0_152jrelibextcldrdata.jar;C:Program FilesJavajdk1.8.0_152jrelibextdnsns.jar;C:Program FilesJavajdk1.8.0_152jrelibextjaccess.jar;C:Program FilesJavajdk1.8.0_152jrelibextjfxrt.jar;C:Program FilesJavajdk1.8.0_152jrelibextlocaledata.jar;C:Program FilesJavajdk1.8.0_152jrelibextnashorn.jar;C:Program FilesJavajdk1.8.0_152jrelibextsunec.jar;C:Program FilesJavajdk1.8.0_152jrelibextsunjce_provider.jar;C:Program FilesJavajdk1.8.0_152jrelibextsunmscapi.jar;C:Program FilesJavajdk1.8.0_152jrelibextsunpkcs11.jar;C:Program FilesJavajdk1.8.0_152jrelibextzipfs.jar;C:Program FilesJavajdk1.8.0_152jrelibjavaws.jar;C:Program FilesJavajdk1.8.0_152jrelibjce.jar;C:Program FilesJavajdk1.8.0_152jrelibjfr.jar;C:Program FilesJavajdk1.8.0_152jrelibjfxswt.jar;C:Program FilesJavajdk1.8.0_152jrelibjsse.jar;C:Program FilesJavajdk1.8.0_152jrelibmanagement-agent.jar;C:Program FilesJavajdk1.8.0_152jrelibplugin.jar;C:Program FilesJavajdk1.8.0_152jrelibresources.jar;C:Program FilesJavajdk1.8.0_152jrelibrt.jar;E:刘建成javaprojectProoutproductionPro" com.hspedu.reflection0.Reflection02 传统 m1 方法来调用 hi 耗时=10 反射机制的 m2 方法来调用 hi 耗时=537 Process finished with exit code 0
2.3.1 反射代码优化
反射部分的代码调用优化:
- Method和Field、Constructor对象都有setAccessible()方法
- setAccessible()作用是启动和禁用访问安全检查的开关
- 参数值为true表示反射的对象在使用时取消访问检查,提高反射效率。参数值为false表示反射的对象在使用时开启访问检查
package com.hspedu.reflection0;
import com.hspedu.Cat;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
public class Reflection02 {
public static void main(String[] args) throws ClassNotFoundException, InvocationTargetException, InstantiationException, IllegalAccessException, NoSuchMethodException {
m1();
m2();
m3();
}
//传统方法来调用hi
public static void m1(){
Cat cat = new Cat();
long start = System.currentTimeMillis();
for(int i=0; i<90000000; i++){
cat.hi();
}
long end = System.currentTimeMillis();
System.out.println("传统 m1 方法来调用 hi 耗时=" + (end - start));
}
//反射机制调用方法
public static void m2() throws ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchMethodException, InvocationTargetException {
Class> clc = Class.forName("com.hspedu.Cat");
Object o = clc.newInstance();
Method hi = clc.getMethod("hi");
long start = System.currentTimeMillis();
for(int i=0; i<90000000; i++){
hi.invoke(o);
}
long end = System.currentTimeMillis();
System.out.println("反射机制的 m2 方法来调用 hi 耗时=" + (end - start));
}
//反射机制调用方法 + 性能优化
public static void m3() throws ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchMethodException, InvocationTargetException {
Class> clc = Class.forName("com.hspedu.Cat");
Object o = clc.newInstance();
Method hi = clc.getMethod("hi");
hi.setAccessible(true); //在反射方法调用时,取消访问检查
long start = System.currentTimeMillis();
for(int i=0; i<90000000; i++){
hi.invoke(o);
}
long end = System.currentTimeMillis();
System.out.println("反射机制的 m3 方法来调用 hi 耗时=" + (end - start));
}
}
"C:Program FilesJavajdk1.8.0_152binjava.exe" "-javaagent:D:软件下载ideaideaIntelliJ IDEA 2021.1libidea_rt.jar=53289:D:软件下载ideaideaIntelliJ IDEA 2021.1bin" -Dfile.encoding=UTF-8 -classpath "C:Program FilesJavajdk1.8.0_152jrelibcharsets.jar;C:Program FilesJavajdk1.8.0_152jrelibdeploy.jar;C:Program FilesJavajdk1.8.0_152jrelibextaccess-bridge-64.jar;C:Program FilesJavajdk1.8.0_152jrelibextcldrdata.jar;C:Program FilesJavajdk1.8.0_152jrelibextdnsns.jar;C:Program FilesJavajdk1.8.0_152jrelibextjaccess.jar;C:Program FilesJavajdk1.8.0_152jrelibextjfxrt.jar;C:Program FilesJavajdk1.8.0_152jrelibextlocaledata.jar;C:Program FilesJavajdk1.8.0_152jrelibextnashorn.jar;C:Program FilesJavajdk1.8.0_152jrelibextsunec.jar;C:Program FilesJavajdk1.8.0_152jrelibextsunjce_provider.jar;C:Program FilesJavajdk1.8.0_152jrelibextsunmscapi.jar;C:Program FilesJavajdk1.8.0_152jrelibextsunpkcs11.jar;C:Program FilesJavajdk1.8.0_152jrelibextzipfs.jar;C:Program FilesJavajdk1.8.0_152jrelibjavaws.jar;C:Program FilesJavajdk1.8.0_152jrelibjce.jar;C:Program FilesJavajdk1.8.0_152jrelibjfr.jar;C:Program FilesJavajdk1.8.0_152jrelibjfxswt.jar;C:Program FilesJavajdk1.8.0_152jrelibjsse.jar;C:Program FilesJavajdk1.8.0_152jrelibmanagement-agent.jar;C:Program FilesJavajdk1.8.0_152jrelibplugin.jar;C:Program FilesJavajdk1.8.0_152jrelibresources.jar;C:Program FilesJavajdk1.8.0_152jrelibrt.jar;E:刘建成javaprojectProoutproductionPro" com.hspedu.reflection0.Reflection02 传统 m1 方法来调用 hi 耗时=10 反射机制的 m2 方法来调用 hi 耗时=648 反射机制的 m3 方法来调用 hi 耗时=329 Process finished with exit code 0
二. class类
2.1 Class类的基本介绍
- 1.Class也是类,因此也继承了Object类
- 2.Class类对象不是new出来的,而是系统创建出来的
- 3.对于某个类的Class类对象,在呢村中只有一份,因此类只加载一次
- 4.每个类的实例都会记得自己是由哪个Class实例所生成
- 5.通过Class可以完整地得到一个类的完整结构,通过一系列API
- 6.Class对象是存放在堆的
- 7.类的字节码二进制数据,是放在方法区的,有的地方称之为类的元数据
2.1.1 Class类图
2.1.1 Class类加载方法
- 通过ClassLoader 里面的loadClass()生成的Class对象
传统的方法:
反射的方法:
同一个类通过Class类产生对象
package com.hspedu.reflection0.class_;
import com.hspedu.Cat;
public class Class01 {
public static void main(String[] args) throws ClassNotFoundException {
//2. Class类对象不是new出来的,而是系统创建出来的
//(1).传统的new对象
//(2).反射方式
Class clc1 = Class.forName("com.hspedu.Cat");
Class clc2 = Class.forName("com.hspedu.Cat");
System.out.println(clc1.hashCode());
System.out.println(clc2.hashCode());
}
}
"C:Program FilesJavajdk1.8.0_152binjava.exe" "-javaagent:D:软件下载ideaideaIntelliJ IDEA 2021.1libidea_rt.jar=53688:D:软件下载ideaideaIntelliJ IDEA 2021.1bin" -Dfile.encoding=UTF-8 -classpath "C:Program FilesJavajdk1.8.0_152jrelibcharsets.jar;C:Program FilesJavajdk1.8.0_152jrelibdeploy.jar;C:Program FilesJavajdk1.8.0_152jrelibextaccess-bridge-64.jar;C:Program FilesJavajdk1.8.0_152jrelibextcldrdata.jar;C:Program FilesJavajdk1.8.0_152jrelibextdnsns.jar;C:Program FilesJavajdk1.8.0_152jrelibextjaccess.jar;C:Program FilesJavajdk1.8.0_152jrelibextjfxrt.jar;C:Program FilesJavajdk1.8.0_152jrelibextlocaledata.jar;C:Program FilesJavajdk1.8.0_152jrelibextnashorn.jar;C:Program FilesJavajdk1.8.0_152jrelibextsunec.jar;C:Program FilesJavajdk1.8.0_152jrelibextsunjce_provider.jar;C:Program FilesJavajdk1.8.0_152jrelibextsunmscapi.jar;C:Program FilesJavajdk1.8.0_152jrelibextsunpkcs11.jar;C:Program FilesJavajdk1.8.0_152jrelibextzipfs.jar;C:Program FilesJavajdk1.8.0_152jrelibjavaws.jar;C:Program FilesJavajdk1.8.0_152jrelibjce.jar;C:Program FilesJavajdk1.8.0_152jrelibjfr.jar;C:Program FilesJavajdk1.8.0_152jrelibjfxswt.jar;C:Program FilesJavajdk1.8.0_152jrelibjsse.jar;C:Program FilesJavajdk1.8.0_152jrelibmanagement-agent.jar;C:Program FilesJavajdk1.8.0_152jrelibplugin.jar;C:Program FilesJavajdk1.8.0_152jrelibresources.jar;C:Program FilesJavajdk1.8.0_152jrelibrt.jar;E:刘建成javaprojectProoutproductionPro" com.hspedu.reflection0.class_.Class01 356573597 356573597 //这里表明,产生的是同一个对象 Process finished with exit code 0
不同的类通过Class类产生对象
package com.hspedu.reflection0.class_;
import com.hspedu.Cat;
public class Class01 {
public static void main(String[] args) throws ClassNotFoundException {
//2. Class类对象不是new出来的,而是系统创建出来的
//(1).传统的new对象
//(2).反射方式
Class clc1 = Class.forName("com.hspedu.Cat");
Class clc2 = Class.forName("com.hspedu.Cat");
System.out.println(clc1.hashCode());
System.out.println(clc2.hashCode());
Class clc3 = Class.forName("com.hspedu.Dog");
System.out.println(clc3.hashCode());
}
}
"C:Program FilesJavajdk1.8.0_152binjava.exe" "-javaagent:D:软件下载ideaideaIntelliJ IDEA 2021.1libidea_rt.jar=53697:D:软件下载ideaideaIntelliJ IDEA 2021.1bin" -Dfile.encoding=UTF-8 -classpath "C:Program FilesJavajdk1.8.0_152jrelibcharsets.jar;C:Program FilesJavajdk1.8.0_152jrelibdeploy.jar;C:Program FilesJavajdk1.8.0_152jrelibextaccess-bridge-64.jar;C:Program FilesJavajdk1.8.0_152jrelibextcldrdata.jar;C:Program FilesJavajdk1.8.0_152jrelibextdnsns.jar;C:Program FilesJavajdk1.8.0_152jrelibextjaccess.jar;C:Program FilesJavajdk1.8.0_152jrelibextjfxrt.jar;C:Program FilesJavajdk1.8.0_152jrelibextlocaledata.jar;C:Program FilesJavajdk1.8.0_152jrelibextnashorn.jar;C:Program FilesJavajdk1.8.0_152jrelibextsunec.jar;C:Program FilesJavajdk1.8.0_152jrelibextsunjce_provider.jar;C:Program FilesJavajdk1.8.0_152jrelibextsunmscapi.jar;C:Program FilesJavajdk1.8.0_152jrelibextsunpkcs11.jar;C:Program FilesJavajdk1.8.0_152jrelibextzipfs.jar;C:Program FilesJavajdk1.8.0_152jrelibjavaws.jar;C:Program FilesJavajdk1.8.0_152jrelibjce.jar;C:Program FilesJavajdk1.8.0_152jrelibjfr.jar;C:Program FilesJavajdk1.8.0_152jrelibjfxswt.jar;C:Program FilesJavajdk1.8.0_152jrelibjsse.jar;C:Program FilesJavajdk1.8.0_152jrelibmanagement-agent.jar;C:Program FilesJavajdk1.8.0_152jrelibplugin.jar;C:Program FilesJavajdk1.8.0_152jrelibresources.jar;C:Program FilesJavajdk1.8.0_152jrelibrt.jar;E:刘建成javaprojectProoutproductionPro" com.hspedu.reflection0.class_.Class01 356573597 356573597 1735600054 //这里表明了,产生了不同的对象 Process finished with exit code 0
Class方法和传统方法一起做对比,可看出采用Class的方法的特点
package com.hspedu.reflection0.class_;
import com.hspedu.Cat;
public class Class01 {
public static void main(String[] args) throws ClassNotFoundException {
//2. Class类对象不是new出来的,而是系统创建出来的
//(1).传统的new对象
//(2).反射方式
Class clc1 = Class.forName("com.hspedu.Cat");
Class clc2 = Class.forName("com.hspedu.Cat");
System.out.println("Class方法产生的Cat对象clc1:" + clc1.hashCode());
System.out.println("Class方法产生的Cat对象clc2:" + clc2.hashCode());
Class clc3 = Class.forName("com.hspedu.Dog");
System.out.println("Class方法产生的Dog对象clc3:" + clc3.hashCode());
Cat cat1 = new Cat();
Cat cat2 = new Cat();
System.out.println("传统方法对象cat1:" + cat1.hashCode());
System.out.println("传统方法对象cat2:" + cat2.hashCode());
}
}
"C:Program FilesJavajdk1.8.0_152binjava.exe" "-javaagent:D:软件下载ideaideaIntelliJ IDEA 2021.1libidea_rt.jar=53728:D:软件下载ideaideaIntelliJ IDEA 2021.1bin" -Dfile.encoding=UTF-8 -classpath "C:Program FilesJavajdk1.8.0_152jrelibcharsets.jar;C:Program FilesJavajdk1.8.0_152jrelibdeploy.jar;C:Program FilesJavajdk1.8.0_152jrelibextaccess-bridge-64.jar;C:Program FilesJavajdk1.8.0_152jrelibextcldrdata.jar;C:Program FilesJavajdk1.8.0_152jrelibextdnsns.jar;C:Program FilesJavajdk1.8.0_152jrelibextjaccess.jar;C:Program FilesJavajdk1.8.0_152jrelibextjfxrt.jar;C:Program FilesJavajdk1.8.0_152jrelibextlocaledata.jar;C:Program FilesJavajdk1.8.0_152jrelibextnashorn.jar;C:Program FilesJavajdk1.8.0_152jrelibextsunec.jar;C:Program FilesJavajdk1.8.0_152jrelibextsunjce_provider.jar;C:Program FilesJavajdk1.8.0_152jrelibextsunmscapi.jar;C:Program FilesJavajdk1.8.0_152jrelibextsunpkcs11.jar;C:Program FilesJavajdk1.8.0_152jrelibextzipfs.jar;C:Program FilesJavajdk1.8.0_152jrelibjavaws.jar;C:Program FilesJavajdk1.8.0_152jrelibjce.jar;C:Program FilesJavajdk1.8.0_152jrelibjfr.jar;C:Program FilesJavajdk1.8.0_152jrelibjfxswt.jar;C:Program FilesJavajdk1.8.0_152jrelibjsse.jar;C:Program FilesJavajdk1.8.0_152jrelibmanagement-agent.jar;C:Program FilesJavajdk1.8.0_152jrelibplugin.jar;C:Program FilesJavajdk1.8.0_152jrelibresources.jar;C:Program FilesJavajdk1.8.0_152jrelibrt.jar;E:刘建成javaprojectProoutproductionPro" com.hspedu.reflection0.class_.Class01 Class方法产生的Cat对象clc1:356573597 Class方法产生的Cat对象clc2:356573597 Class方法产生的Dog对象clc3:1735600054 传统方法对象cat1:21685669 传统方法对象cat2:2133927002 Process finished with exit code 0
2.1.4 每个类的实例都会记得自己是由哪个Class实例所生成
2.1.5 通过Class可以完整地得到一个类的完整结构,通过一系列API
2.1.6 Class对象是存放在堆中的
2.1.7 类的字节码二进制数据,放在方法区的,有的地方称为类的元数据
Class类应用实例:
实例1 —> 输出clc:
package com.hspedu.reflection0.class_;
public class Class02{
public static void main(String[] args) throws ClassNotFoundException {
String classAllPAth = "com.hspedu.Car";
//获取读到的CAr类,对应的Class对象
//>表示不确定的Java类型
Class> clc = Class.forName(classAllPAth);
//输出clc
System.out.println(clc); //如果输出clc对象,是哪个类的Class对象,com.hspedu.Car
System.out.println(clc.getClass()); //输出clc运行时类型:java.lang.Class
}
}
"C:Program FilesJavajdk1.8.0_152binjava.exe" "-javaagent:D:软件下载ideaideaIntelliJ IDEA 2021.1libidea_rt.jar=53840:D:软件下载ideaideaIntelliJ IDEA 2021.1bin" -Dfile.encoding=UTF-8 -classpath "C:Program FilesJavajdk1.8.0_152jrelibcharsets.jar;C:Program FilesJavajdk1.8.0_152jrelibdeploy.jar;C:Program FilesJavajdk1.8.0_152jrelibextaccess-bridge-64.jar;C:Program FilesJavajdk1.8.0_152jrelibextcldrdata.jar;C:Program FilesJavajdk1.8.0_152jrelibextdnsns.jar;C:Program FilesJavajdk1.8.0_152jrelibextjaccess.jar;C:Program FilesJavajdk1.8.0_152jrelibextjfxrt.jar;C:Program FilesJavajdk1.8.0_152jrelibextlocaledata.jar;C:Program FilesJavajdk1.8.0_152jrelibextnashorn.jar;C:Program FilesJavajdk1.8.0_152jrelibextsunec.jar;C:Program FilesJavajdk1.8.0_152jrelibextsunjce_provider.jar;C:Program FilesJavajdk1.8.0_152jrelibextsunmscapi.jar;C:Program FilesJavajdk1.8.0_152jrelibextsunpkcs11.jar;C:Program FilesJavajdk1.8.0_152jrelibextzipfs.jar;C:Program FilesJavajdk1.8.0_152jrelibjavaws.jar;C:Program FilesJavajdk1.8.0_152jrelibjce.jar;C:Program FilesJavajdk1.8.0_152jrelibjfr.jar;C:Program FilesJavajdk1.8.0_152jrelibjfxswt.jar;C:Program FilesJavajdk1.8.0_152jrelibjsse.jar;C:Program FilesJavajdk1.8.0_152jrelibmanagement-agent.jar;C:Program FilesJavajdk1.8.0_152jrelibplugin.jar;C:Program FilesJavajdk1.8.0_152jrelibresources.jar;C:Program FilesJavajdk1.8.0_152jrelibrt.jar;E:刘建成javaprojectProoutproductionPro" com.hspedu.reflection0.class_.Class02 class com.hspedu.Car class java.lang.Class Process finished with exit code 0
实例2 —> 得到包名:
package com.hspedu.reflection0.class_;
public class Class02{
public static void main(String[] args) throws ClassNotFoundException {
String classAllPAth = "com.hspedu.Car";
//获取读到的CAr类,对应的Class对象
//>表示不确定的Java类型
Class> clc = Class.forName(classAllPAth);
//得到包名
System.out.println(clc.getPackage().getName());
}
}
"C:Program FilesJavajdk1.8.0_152binjava.exe" "-javaagent:D:软件下载ideaideaIntelliJ IDEA 2021.1libidea_rt.jar=53855:D:软件下载ideaideaIntelliJ IDEA 2021.1bin" -Dfile.encoding=UTF-8 -classpath "C:Program FilesJavajdk1.8.0_152jrelibcharsets.jar;C:Program FilesJavajdk1.8.0_152jrelibdeploy.jar;C:Program FilesJavajdk1.8.0_152jrelibextaccess-bridge-64.jar;C:Program FilesJavajdk1.8.0_152jrelibextcldrdata.jar;C:Program FilesJavajdk1.8.0_152jrelibextdnsns.jar;C:Program FilesJavajdk1.8.0_152jrelibextjaccess.jar;C:Program FilesJavajdk1.8.0_152jrelibextjfxrt.jar;C:Program FilesJavajdk1.8.0_152jrelibextlocaledata.jar;C:Program FilesJavajdk1.8.0_152jrelibextnashorn.jar;C:Program FilesJavajdk1.8.0_152jrelibextsunec.jar;C:Program FilesJavajdk1.8.0_152jrelibextsunjce_provider.jar;C:Program FilesJavajdk1.8.0_152jrelibextsunmscapi.jar;C:Program FilesJavajdk1.8.0_152jrelibextsunpkcs11.jar;C:Program FilesJavajdk1.8.0_152jrelibextzipfs.jar;C:Program FilesJavajdk1.8.0_152jrelibjavaws.jar;C:Program FilesJavajdk1.8.0_152jrelibjce.jar;C:Program FilesJavajdk1.8.0_152jrelibjfr.jar;C:Program FilesJavajdk1.8.0_152jrelibjfxswt.jar;C:Program FilesJavajdk1.8.0_152jrelibjsse.jar;C:Program FilesJavajdk1.8.0_152jrelibmanagement-agent.jar;C:Program FilesJavajdk1.8.0_152jrelibplugin.jar;C:Program FilesJavajdk1.8.0_152jrelibresources.jar;C:Program FilesJavajdk1.8.0_152jrelibrt.jar;E:刘建成javaprojectProoutproductionPro" com.hspedu.reflection0.class_.Class02 com.hspedu Process finished with exit code 0
实例3 —> 其他方法:
//为了显示更加方便,将Car类进行一定的更改
package com.hspedu;
public class Car {
public String brand = "宝马"; //这里如果是私有属性,利用反射机制来获取对象属性会报错的,后面再看私有属性的获取
public int price = 500000;
public String color = "白色";
@Override
public String toString() {
return "Car{" +
"brand='" + brand + ''' +
", price=" + price +
", color='" + color + ''' +
'}';
}
}
package com.hspedu.reflection0.class_;
import com.hspedu.Car;
import java.lang.reflect.Field;
public class Class02{
public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchFieldException {
String classAllPAth = "com.hspedu.Car";
//获取读到的CAr类,对应的Class对象
//>表示不确定的Java类型
Class> clc = Class.forName(classAllPAth);
//1. 得到包名
System.out.println("得到包名" + clc.getPackage().getName());
//2. 得到全类名
System.out.println("得到全类名" + clc.getName());
//3. 通过clc创建对象实例
Car car = (Car) clc.newInstance();
System.out.println(car);
//4. 通过反射获取对象属性 brand
Field brand = clc.getField("brand");
System.out.println(brand.get(car)); //宝马
//5. 通过反射给属性赋值
brand.set(car,"奔驰"); //方法.对象。和传统的Java是反着的。
System.out.println(brand.get(car)); //奔驰
//6. 获取所有属性
System.out.println("==========");
Field[] fields = clc.getFields();
for(Field f:fields){
System.out.println(f.get(car));
}
}
}
"C:Program FilesJavajdk1.8.0_152binjava.exe" "-javaagent:D:软件下载ideaideaIntelliJ IDEA 2021.1libidea_rt.jar=53886:D:软件下载ideaideaIntelliJ IDEA 2021.1bin" -Dfile.encoding=UTF-8 -classpath "C:Program FilesJavajdk1.8.0_152jrelibcharsets.jar;C:Program FilesJavajdk1.8.0_152jrelibdeploy.jar;C:Program FilesJavajdk1.8.0_152jrelibextaccess-bridge-64.jar;C:Program FilesJavajdk1.8.0_152jrelibextcldrdata.jar;C:Program FilesJavajdk1.8.0_152jrelibextdnsns.jar;C:Program FilesJavajdk1.8.0_152jrelibextjaccess.jar;C:Program FilesJavajdk1.8.0_152jrelibextjfxrt.jar;C:Program FilesJavajdk1.8.0_152jrelibextlocaledata.jar;C:Program FilesJavajdk1.8.0_152jrelibextnashorn.jar;C:Program FilesJavajdk1.8.0_152jrelibextsunec.jar;C:Program FilesJavajdk1.8.0_152jrelibextsunjce_provider.jar;C:Program FilesJavajdk1.8.0_152jrelibextsunmscapi.jar;C:Program FilesJavajdk1.8.0_152jrelibextsunpkcs11.jar;C:Program FilesJavajdk1.8.0_152jrelibextzipfs.jar;C:Program FilesJavajdk1.8.0_152jrelibjavaws.jar;C:Program FilesJavajdk1.8.0_152jrelibjce.jar;C:Program FilesJavajdk1.8.0_152jrelibjfr.jar;C:Program FilesJavajdk1.8.0_152jrelibjfxswt.jar;C:Program FilesJavajdk1.8.0_152jrelibjsse.jar;C:Program FilesJavajdk1.8.0_152jrelibmanagement-agent.jar;C:Program FilesJavajdk1.8.0_152jrelibplugin.jar;C:Program FilesJavajdk1.8.0_152jrelibresources.jar;C:Program FilesJavajdk1.8.0_152jrelibrt.jar;E:刘建成javaprojectProoutproductionPro" com.hspedu.reflection0.class_.Class02
得到包名com.hspedu
得到全类名com.hspedu.Car
Car{brand='宝马', price=500000, color='白色'}
宝马
奔驰
==========
奔驰
500000
白色
Process finished with exit code 0
2.2 获取Class类对象
- 编译阶段:Class.forName()
- 类加载阶段:类.class
- 运行阶段:对象.getClass()
package com.hspedu.reflection0.class_;
import com.hspedu.Car;
public class GetClass_ {
public static void main(String[] args) throws ClassNotFoundException {
//1. Class.forName
String classALLPath = "com.hspedu.Car"; //通过读取配置文件获取到的
Class> clc = Class.forName(classALLPath);
System.out.println(clc);
//2. 类.class。应用场景:参数传递
Class clc1 = Car.class;
System.out.println(clc1);
//3. 通过: 对象.getClass(),应用场景,有对象实例
Car car = new Car();
Class clc2 = car.getClass();
System.out.println(clc2);
//4. 通过类加载器得到Class对象,一共有4种类加载器
//(1).先得到类加载器car
ClassLoader classLoader = car.getClass().getClassLoader();
//(2).通过类加载器得到Class对象
Class> clc3 = classLoader.loadClass(classALLPath);
System.out.println(clc3);
//clc clc1 clc2 clc3其实是同一个对象
System.out.println("======clc clc1 clc2 clc3的hashcode()======");
System.out.println(clc.hashCode());
System.out.println(clc1.hashCode());
System.out.println(clc2.hashCode());
System.out.println(clc3.hashCode());
//基本数据类型
System.out.println("======基本数据类型:======");
Class integerClass = int.class;
Class characterClass = char.class;
Class booleanClass = boolean.class;
System.out.println(integerClass); //int
System.out.println(characterClass);
//基本数据类型对应的包装类
System.out.println("======基本数据类型对应的包装类:======");
Class type1 = Integer.TYPE;
Class type2 = Character.TYPE;
System.out.println(type1);
System.out.println(type2);
System.out.println("type1的hashcode:" + type1.hashCode());
System.out.println("包装类hashcode:" + integerClass.hashCode());
}
}
"C:Program FilesJavajdk1.8.0_152binjava.exe" "-javaagent:D:软件下载ideaideaIntelliJ IDEA 2021.1libidea_rt.jar=53967:D:软件下载ideaideaIntelliJ IDEA 2021.1bin" -Dfile.encoding=UTF-8 -classpath "C:Program FilesJavajdk1.8.0_152jrelibcharsets.jar;C:Program FilesJavajdk1.8.0_152jrelibdeploy.jar;C:Program FilesJavajdk1.8.0_152jrelibextaccess-bridge-64.jar;C:Program FilesJavajdk1.8.0_152jrelibextcldrdata.jar;C:Program FilesJavajdk1.8.0_152jrelibextdnsns.jar;C:Program FilesJavajdk1.8.0_152jrelibextjaccess.jar;C:Program FilesJavajdk1.8.0_152jrelibextjfxrt.jar;C:Program FilesJavajdk1.8.0_152jrelibextlocaledata.jar;C:Program FilesJavajdk1.8.0_152jrelibextnashorn.jar;C:Program FilesJavajdk1.8.0_152jrelibextsunec.jar;C:Program FilesJavajdk1.8.0_152jrelibextsunjce_provider.jar;C:Program FilesJavajdk1.8.0_152jrelibextsunmscapi.jar;C:Program FilesJavajdk1.8.0_152jrelibextsunpkcs11.jar;C:Program FilesJavajdk1.8.0_152jrelibextzipfs.jar;C:Program FilesJavajdk1.8.0_152jrelibjavaws.jar;C:Program FilesJavajdk1.8.0_152jrelibjce.jar;C:Program FilesJavajdk1.8.0_152jrelibjfr.jar;C:Program FilesJavajdk1.8.0_152jrelibjfxswt.jar;C:Program FilesJavajdk1.8.0_152jrelibjsse.jar;C:Program FilesJavajdk1.8.0_152jrelibmanagement-agent.jar;C:Program FilesJavajdk1.8.0_152jrelibplugin.jar;C:Program FilesJavajdk1.8.0_152jrelibresources.jar;C:Program FilesJavajdk1.8.0_152jrelibrt.jar;E:刘建成javaprojectProoutproductionPro" com.hspedu.reflection0.class_.GetClass_ class com.hspedu.Car class com.hspedu.Car class com.hspedu.Car class com.hspedu.Car ======clc clc1 clc2 clc3的hashcode()====== 356573597 356573597 356573597 356573597 ======基本数据类型:====== int char ======基本数据类型对应的包装类:====== int char type1的hashcode:1735600054 包装类hashcode:1735600054 Process finished with exit code 0
2.3 哪些类型有Class对象
-
- 外部类,成员内部类,静态内部类,局部内部类,匿名内部类
-
- interface接口
-
- 数组
-
- enum:枚举
-
- annotation:注解
-
- 基本数据类型
-
- void
package com.hspedu.reflection0.class_;
import java.io.Serializable;
public class ALLTypeClas {
public static void main(String[] args) {
//外部类
Class cls1 = String.class;
//接口
Class cls2 = Serializable.class;
//数组
Class cls3 = Integer[].class;
//二维数组
Class cls4 = float[][].class;
//注解
Class cls5 = Deprecated.class;
//枚举
Class cls6 = Thread.State.class;
//long基本数据类型
Class cls7 = long.class;
//void
Class cls8 = void.class;
//Class
Class cls9 = Class.class;
System.out.println(cls1);
System.out.println(cls2);
System.out.println(cls3);
System.out.println(cls4);
System.out.println(cls5);
System.out.println(cls6);
System.out.println(cls7);
System.out.println(cls8);
System.out.println(cls9);
}
}
"C:Program FilesJavajdk1.8.0_152binjava.exe" "-javaagent:D:软件下载ideaideaIntelliJ IDEA 2021.1libidea_rt.jar=54011:D:软件下载ideaideaIntelliJ IDEA 2021.1bin" -Dfile.encoding=UTF-8 -classpath "C:Program FilesJavajdk1.8.0_152jrelibcharsets.jar;C:Program FilesJavajdk1.8.0_152jrelibdeploy.jar;C:Program FilesJavajdk1.8.0_152jrelibextaccess-bridge-64.jar;C:Program FilesJavajdk1.8.0_152jrelibextcldrdata.jar;C:Program FilesJavajdk1.8.0_152jrelibextdnsns.jar;C:Program FilesJavajdk1.8.0_152jrelibextjaccess.jar;C:Program FilesJavajdk1.8.0_152jrelibextjfxrt.jar;C:Program FilesJavajdk1.8.0_152jrelibextlocaledata.jar;C:Program FilesJavajdk1.8.0_152jrelibextnashorn.jar;C:Program FilesJavajdk1.8.0_152jrelibextsunec.jar;C:Program FilesJavajdk1.8.0_152jrelibextsunjce_provider.jar;C:Program FilesJavajdk1.8.0_152jrelibextsunmscapi.jar;C:Program FilesJavajdk1.8.0_152jrelibextsunpkcs11.jar;C:Program FilesJavajdk1.8.0_152jrelibextzipfs.jar;C:Program FilesJavajdk1.8.0_152jrelibjavaws.jar;C:Program FilesJavajdk1.8.0_152jrelibjce.jar;C:Program FilesJavajdk1.8.0_152jrelibjfr.jar;C:Program FilesJavajdk1.8.0_152jrelibjfxswt.jar;C:Program FilesJavajdk1.8.0_152jrelibjsse.jar;C:Program FilesJavajdk1.8.0_152jrelibmanagement-agent.jar;C:Program FilesJavajdk1.8.0_152jrelibplugin.jar;C:Program FilesJavajdk1.8.0_152jrelibresources.jar;C:Program FilesJavajdk1.8.0_152jrelibrt.jar;E:刘建成javaprojectProoutproductionPro" com.hspedu.reflection0.class_.ALLTypeClas class java.lang.String interface java.io.Serializable class [Ljava.lang.Integer; class [[F interface java.lang.Deprecated class java.lang.Thread$State long void class java.lang.Class Process finished with exit code 0
三. 类加载
-
反射机制是java实现动态语言的关键,也就是通过反射实现类动态加载。
-
静态加载:编译时加载相关的类,如果没有则报错,依赖性太强
-
动态加载:运行时加载需要的类,如果运行时不用该类,即使不存在该类,则不报错,降低了依赖性
-
静态加载和动态加载对比的代码:
package com.hspedu.reflection0.class_;
import com.hspedu.Dog;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Scanner;
public class ClassLoad_ {
public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchMethodException, InvocationTargetException {
Scanner scanner = new Scanner(System.in);
System.out.println("请输入key");
String key = scanner.next();
switch(key){
case "1":
Dog dog = new Dog();
dog.cry();
dog.laugh(); //Dog里面没有这个类。编译时,如果有问题,则会报错,
break;
case "2": //文件夹中没有Person这个类,编译时没有报错。在运行时,如果用到Person类,发现没有才会报错。
Class cls = Class.forName("Person"); //运行时,就算没有Person,只要不用他,是不会报错的。
Object o = cls.newInstance();
Method m = cls.getMethod("hi");
m.invoke(o);
System.out.println("ok~");
break;
default:
System.out.println("do nothing~");
}
}
}
类加载流程图:
- 类加载的各个阶段
- JVM在该阶段的主要目的是将字节码从不同的数据源(可能是class文件、也可能是jar包,甚至网络)转换为二进制字节流加载到内存中,并生成一个代表该类的java.lang.Class对象
- 连接阶段
- 验证:
- 1.目的是为了确保Class文件的字节流中包含的信息符合当前虚拟机的要求,姑且不会危害虚拟机自身的安全。
- 2.包括:文件格式验证(是否以魔数oxcafebabe开头)、元数据验证,字节码验证和符号引用验证
- 3.可以考虑使用 -Xverify:none 参数来关闭大部分的类验证措施,缩短虚拟机类加载的时间。
- 准备:
- 解析
- 验证:
四. 反射获取类的结构信息
参考链接
五. 反射相关类
参考链接
六. class类常用方法
参考链接



