Java 中的内置的类加载器
-
Bootstrap class loader
:它是虚拟机的内置类加载器,通常表示为null ,并且没有父null -
Platform class loader
:平台类加载器可以看到所有平台类 ,平台类包括由平台类加载器或其祖先定义的Java SE平台API,其实现类和JDK特定的运行时类 -
System class loader
:它也被称为应用程序类加载器 ,与平台类加载器不同。 系统类加载器通常用于定义应用程序类路径,模块路径和JDK特定工具上的类 -
类加载器的继承关系:System的父加载器为Platform,而Platform的父加载器为Bootstrap
-
java.lang.ClassLoader
方法名 | 说明 |
---|---|
static ClassLoader getSystemClassLoader() | 返回用于委派的系统类加载器 |
ClassLoader getParent() | 返回父类加载器进行委派 |
ClassLoader systemClassLoader = ClassLoader.getSystemClassLoader();
System.out.println(systemClassLoader);
// sun.misc.Launcher$AppClassLoader@18b4aac2
ClassLoader parentLoader = systemClassLoader.getParent();
System.out.println(parentLoader);
// sun.misc.Launcher$ExtClassLoader@1540e19d
ClassLoader rootLoad = parentLoader.getParent();
System.out.println(rootLoad);
// null
反射
三种方式获得Class对象
-
类名.class属性
Class c1 = Foo.class
-
对象名.getClass()
Class c2 = foo.getClass()
-
Class.forName(全类名)
, 动态加载类Class c3 = Class.forName("test.reflect.Foo")
-
三者是相等的
System.out.println(c1 == c2&&c2 == c3)
-
通过Class类的对象获得某个类的信息
getName()
返回类类型的名称getSimpleName()
返回类类型的名称的简写
java.lang.String // getName() String // getSimpleName()
Class c1 = int.class;
Class c2 = String.class;
Class c3 = void.class;
Class c4 = double.class;
Class c5 = Double.class;
System.out.println(c1.getName());
System.out.println(c2.getName());
System.out.println(c3.getName());
System.out.println(c4.getName());
System.out.println(c5.getName());
# int
# java.lang.String
# void
# double
# java.lang.Double
获取构造函数
方法名 | 说明 |
---|---|
Constructor<?>[] getConstructors() | 返回所有public构造方法对象的数组 |
Constructor<?>[] getDeclaredConstructors() | 返回所有构造方法对象的数组 |
Constructor getConstructor(Class<?>… parameterTypes) | 返回单个公共构造方法对象 |
Constructor getDeclaredConstructor(Class<?>… parameterTypes) | 返回单个构造方法对象 |
-
T newInstance(Object...initargs)
根据指定的构造方法创建对象 -
调用共有的构造方法创建对象
public static void main(String[] args) { try { Class<?> studentClass = Class.forName("main.language.StudentReflect"); Constructor<?> constructor = studentClass.getDeclaredConstructor(String.class, int.class, String.class); Object obj = constructor.newInstance("张三", 20, "合肥"); System.out.println(obj); } catch (ClassNotFoundException e) { e.printStackTrace(); } catch (NoSuchMethodException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } catch (InstantiationException e) { e.printStackTrace(); } catch (InvocationTargetException e) { e.printStackTrace(); } }
-
使用私有构造函数创建对象。需要先设置访问权限
setAccessible
// 获得一个私有的构造方法 Constructor<?> privateCons = studentClass.getDeclaredConstructor(String.class); privateCons.setAccessible(true); // 调用私有方法需要先修改访问权限 Object obj2 = privateCons.newInstance("李四"); System.out.println(obj2);
获得成员变量
方法名 | 说明 |
---|---|
Field[] getFields() | 返回所有公共成员变量对象的数组 |
Field[] getDeclaredFields() | 返回所有成员变量对象的数组 |
Field getField(String name) | 返回单个公共成员变量对象 |
Field getDeclaredField(String name) | 返回单个成员变量对象 |
void set(Object obj, Object value) | 给obj对象的成员变量赋值为value |
getType() | 获得 变量的类型。返回Class |
Field nameField = studentClass.getDeclaredField("name");
nameField.setAccessible(true);
nameField.set(obj2, "李斯");
System.out.println(obj2);
获得成员方法
方法也是对象,一个成员方法就是一个Method对象实例
方法名 | 说明 |
---|---|
Method[] getMethods() | 返回所有public成员方法对象的数组,包括继承的 |
Method[] getDeclaredMethods() | 返回所有(public, protected, default)成员方法对象的数组,不包括继承的 |
Method getMethod(String name, Class<?>…parameterTypes) | 返回单个public成员方法对象,包括继承 |
Method getDeclaredMethod(String name, Class<?>…parameterTypes) | 返回单个(public,protected,private)成员方法对象 ,不包括继承的 |
Object invoke(Object obj, Object… args) | 调用obj对象的成员方法,参数是args,返回值是Object类型 |
getReturnType() | 获得返回值,返回的是 Class |
Method method1 = studentClass.getMethod("method1");
Method method3 = studentClass.getMethod("method3", String.class, int.class);
Method function = studentClass.getDeclaredMethod("function");
function.setAccessible(true);
method1.invoke(obj2);
method3.invoke(obj2, "方法三", 100);
function.invoke(obj2);
- 绕过泛型类型检查
// 绕过泛型检查
ArrayList<Integer> list = new ArrayList<>();
Class<? extends ArrayList> listClass = list.getClass();
Method addMethod = listClass.getMethod("add", Object.class);
addMethod.invoke(list, "aaaaa");
addMethod.invoke(list, "bbbbb");
addMethod.invoke(list, "ccccc");
// String res1 = list.get(0); // 编译错误
// Integer res2 = list.get(0); // 类型转换错误
System.out.println(list.get(0)); // 正常