1、类加载器(ClassLoader)负责将类的.class文件加载到Java虚拟机(JVM)中。 Java 三种内置的类加载器:
内置类加载器
Bootstrap Class Loader(引导类加载器):
JVM自带的类加载器,不是Java语言实现的,而是用本地代码(如C/C++)实现的。
负责加载Java的核心库,如java.lang.*等。对于Java程序员来说,它是不可见的,无法直接引用它。尝试获取它的实例通常返回null,且没有直接的父加载器。
Extension Class Loader(扩展类加载器):
负责加载Java的扩展库,这些库位于$JAVA_HOME/jre/lib/ext或者由系统属性java.ext.dirs指定的目录中。它是Bootstrap Class Loader的子加载器。
System Class Loader(系统类加载器):
应用程序类加载器(Application Class Loader)。
负责加载用户类路径(classpath)所指定的类库,开发者可以直接使用该类加载器来加载类。
它是Extension Class Loader的子加载器。
类加载器的继承关系
System Class Loader 的父加载器是 Extension Class Loader。
Extension Class Loader 的父加载器是 Bootstrap Class Loader。
ClassLoader 中的两个方法
static ClassLoader getSystemClassLoader():
此方法返回用于委派的系统类加载器(即应用程序类加载器)。
ClassLoader getParent():
此方法返回此类加载器的父类加载器。
Bootstrap Class Loader,此方法通常返回null,因为它没有父加载器(在Java代码中)。
对于其他类型的类加载器(如Extension Class Loader和System Class Loader),此方法将返回其父加载器的实例。
测试代码:
package test.reflect;
public class ClassLoaderDemo {
public static void main(String[] args) {
// 获取系统类加载器(也称为应用程序类加载器)
ClassLoader systemClassLoader = ClassLoader.getSystemClassLoader();
System.out.println("系统类加载器(System ClassLoader):" + systemClassLoader.getClass().getName());
// 尝试获取系统类加载器的父加载器
ClassLoader parentClassLoader = systemClassLoader.getParent();
if (parentClassLoader != null) {
System.out.println("系统类加载器的父加载器:" + parentClassLoader.getClass().getName());
} else {
System.out.println("系统类加载器的父加载器无法直接访问(可能是Bootstrap ClassLoader)");
}
// 获取Bootstrap ClassLoader的父加载器)将总是返回null
// Bootstrap ClassLoader在Java代码中没有直接的父加载器
ClassLoader grandparentClassLoader = parentClassLoader != null ? parentClassLoader.getParent() : null;
System.out.println("父加载器的父加载器(Bootstrap ClassLoader的父加载器):" + (grandparentClassLoader != null ? grandparentClassLoader.getClass().getName() : "null"));
}
}
运行结果如下:
........................................................................................................................................................
2、反射机制:
Java反射(Reflection)机制,允许程序在运行时(runtime)检查或修改类的行为。主要依赖于java.lang.reflect包中的类和接口。通过反射,可以动态地创建类的实例、访问类的私有成员(包括字段、方法)、调用任何方法,甚至是在编译时并不知道的类的方法。
测试代码1:
package test.reflect;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
//使用反射机制调用一个类的私有方法。
public class ReflectionDemo {
private void privateMethod() {
System.out.println("Private method called.");
}
public static void main(String[] args) {
try {
// 获取Class对象
Class<?> clazz = Class.forName("test.reflect.ReflectionDemo");
// 创建实例
Object instance = clazz.getDeclaredConstructor().newInstance();
// 获取私有方法
Method method = clazz.getDeclaredMethod("privateMethod");
// 设置为可访问
method.setAccessible(true);
// 调用私有方法
method.invoke(instance);
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException |
NoSuchMethodException | InvocationTargetException e) {
e.printStackTrace();
}
}
}
运行结果如下:
........................................................................................................................................................
测试代码2:
创建一个Flower类:
package test.reflect;
public class Flower {
// 私有成员变量
private String species;
// 默认(包级私有)成员变量
String color;
// 公共成员变量
public String fragrance;
// 无参构造方法
public Flower() {
}
// 默认构造方法
Flower(String color) {
this.color = color;
}
// 公共构造方法1
public Flower(String species, String color) {
this.species = species;
this.color = color;
}
// 公共构造方法2
public Flower(String species, String color, String fragrance) {
this.species = species;
this.color = color;
this.fragrance = fragrance;
}
public String getSpecies() {
return species;
}
public void setSpecies(String species) {
this.species = species;
}
public String getColor() {
return color;
}
public void setColor(String color) {
this.color = color;
}
public String getFragrance() {
return fragrance;
}
public void setFragrance(String fragrance) {
this.fragrance = fragrance;
}
// 私有成员方法
@SuppressWarnings("unused")
private void privateMethod() {
System.out.println("Private method called.");
}
// 公共成员方法1
public void publicMethod1() {
System.out.println("Public method 1 called. Flower details: species=" + species + ", color=" + color + ", fragrance=" + fragrance);
}
// 公共成员方法2
public void publicMethod2(String newColor) {
this.color = newColor;
System.out.println("Color changed to: " + newColor);
}
// 重写toString方法
@Override
public String toString() {
return "Flower{" +
"species='" + species + '\'' +
", color='" + color + '\'' +
", fragrance='" + fragrance + '\'' +
'}';
}
}
使用反射获取构造方法:
package test.reflect;
import java.lang.reflect.Constructor;
public class ReflectionDemoTest {
public static void main(String[] args) {
try {
// 获取Flower类的Class对象
Class<?> flowerClass = Flower.class;
// 使用无参构造方法创建Flower实例
Constructor<?> noArgConstructor = flowerClass.getConstructor();
noArgConstructor.setAccessible(true);
Flower flower1 = (Flower) noArgConstructor.newInstance();
System.out.println(flower1);
// 使用带有两个参数的构造方法创建Flower实例
Constructor<?> twoArgConstructor = flowerClass.getConstructor(String.class, String.class);
Flower flower2 = (Flower) twoArgConstructor.newInstance("Rose", "Red");
System.out.println(flower2);
// 使用带有三个参数的构造方法创建Flower实例
Constructor<?> threeArgConstructor = flowerClass.getConstructor(String.class, String.class, String.class);
Flower flower3 = (Flower) threeArgConstructor.newInstance("Lily", "White", "Sweet");
System.out.println(flower3);
// 私有构造方法不能直接通过getConstructor获取,通常不推荐反射地访问私有构造方法
// 如果确实需要,使用getDeclaredConstructor并调用setAccessible(true)
} catch (Exception e) {
e.printStackTrace();
}
}
}
运行结果如下:
使用反射获取成员变量:
package test.reflect;
import java.lang.reflect.Field;
public class TestReflection {
public static void main(String[] args) {
try {
// 创建Flower对象
Flower flower = new Flower();
// 获取Flower类的Class对象
Class<?> flowerClass = flower.getClass();
// 获取private成员变量species并设置为可访问
Field speciesField = flowerClass.getDeclaredField("species");
speciesField.setAccessible(true);
speciesField.set(flower, "Rose"); // 修改对象属性
// 获取private成员变量color并设置为可访问
Field colorField = flowerClass.getDeclaredField("color");
colorField.setAccessible(true);
colorField.set(flower, "Red"); // 修改对象属性
// 获取private成员变量fragrance并设置为可访问
Field fragranceField = flowerClass.getDeclaredField("fragrance");
// 如果成员变量是public的,则不需要setAccessible(true)
fragranceField.setAccessible(true);
fragranceField.set(flower, "Sweet"); // 修改对象属性
// 打印修改后的对象信息
System.out.println(flower);
} catch (NoSuchFieldException | IllegalAccessException e) {
e.printStackTrace();
}
}
}
运行结果如下:
使用反射获取成员方法:
package test.reflect;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
public class ReflectionTest {
public static void main(String[] args) {
try {
// 创建Flower对象
Flower flower = new Flower("Rose", "Red");
// 获取Flower类的Class对象
Class<?> flowerClass = flower.getClass();
// 获取成员方法publicMethod1
Method publicMethod1 = flowerClass.getMethod("publicMethod1");
// 调用publicMethod1
publicMethod1.invoke(flower);
// 如果方法需要参数
Method setColorMethod = flowerClass.getMethod("setColor", String.class);
setColorMethod.invoke(flower, "Pink"); // 调用setColor方法,将color设置为Pink
System.out.println(flower);
} catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {
e.printStackTrace();
}
}
}
运行结果如下:
使用反射同时获取构造方法、成员变量和成员方法:
package test.reflect;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
public class ReflectionExample {
public static void main(String[] args) {
// 获取Flower类的Class对象
Class<Flower> flowerClass = Flower.class;
// 通过反射创建Flower类的实例
try {
// 使用带参数的构造方法
Constructor<Flower> constructor = flowerClass.getDeclaredConstructor(String.class, String.class, String.class);
Flower flowerInstance = constructor.newInstance("Rose", "Red", "Fragrant");
System.out.println(flowerInstance);
} catch (InstantiationException | IllegalAccessException | NoSuchMethodException | InvocationTargetException e) {
e.printStackTrace();
}
// 访问Flower类的私有成员
try {
// 访问私有字段
Field speciesField = flowerClass.getDeclaredField("species");
speciesField.setAccessible(true); // 设置为可访问
Flower anotherFlower = new Flower("Tulip", "Purple", "Sweet");
Object speciesValue = speciesField.get(anotherFlower);
System.out.println(speciesValue);
// 调用私有方法
Method privateMethod = flowerClass.getDeclaredMethod("privateMethod");
privateMethod.setAccessible(true); // 设置为可访问
privateMethod.invoke(anotherFlower);
} catch (NoSuchFieldException | NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {
e.printStackTrace();
}
}
}
运行结果如下: