自定义了类加载器为啥只能通过反射创建对象,想new就没有办法了吗
指定外部的class文件,只能通过反射创建对象;在破坏双亲委派原则的情况下,虽使用自定义的类加载器,但是你要使用类加载load然后创建对象。所以要使用自定义的类加载器就不能通过new的方式创建对象。
参照代码如下:
package com.demo1;
import java.io.IOException;
import java.io.InputStream;
/**
* @Author blackoon88
* @Date 2022/5/14
*/
public class MyClassLoader2 extends ClassLoader{
public static void main(String[] args) throws Exception {
/**
* 重写loadClass,违背了双亲委派原则。
* 因为双亲委派的逻辑是在loadClass中通过递归实现
* 正确操作为重写findClass
*/
ClassLoader load = new ClassLoader() {
@Override
public Class<?> loadClass(String name) throws ClassNotFoundException {
try {
String fileName = name.substring(name.lastIndexOf(".") + 1) + ".class";
InputStream resourceAsStream = getClass().getResourceAsStream(fileName);
if (resourceAsStream == null) {
return super.loadClass(name);
}
byte[] b = new byte[resourceAsStream.available()];
resourceAsStream.read(b);
return defineClass(name, b, 0, b.length);
} catch (IOException e) {
throw new ClassNotFoundException();
}
}
};
ClassLoader find = new ClassLoader() {
@Override
protected Class<?> findClass(String name) throws ClassNotFoundException {
String fileName = name.substring(name.lastIndexOf(".") + 1) + ".class";
InputStream resourceAsStream = getClass().getResourceAsStream(fileName);
if (resourceAsStream == null) {
return super.findClass(name);
} else {
byte[] b = new byte[0];
try {
b = new byte[resourceAsStream.available()];
resourceAsStream.read(b);
} catch (IOException e) {
e.printStackTrace();
}
return defineClass(name, b, 0, b.length);
}
}
};
// 重写loadClass,破坏双亲委派原则,但会使用自定义的类加载器
Object loadObject = load.loadClass("com.demo1.MyClassLoader2").newInstance();
System.out.println("load:"+ loadObject.getClass().getClassLoader());
System.out.println(loadObject instanceof MyClassLoader2);
System.out.println("------------------------------------------------------");
// 重写findClass,运行时由于要加载的类在classpath下已经编译好,则会用AppClassLoader来加载,
// 如果要使用自定义累加器的加载,则应该使用类路径classpath外的一个class文件,并且类路径下不能包含此class
// 才能使用到自定义的类加载器
Object findObject = find.loadClass("com.demo1.MyClassLoader2").newInstance();
System.out.println("find:"+ findObject.getClass().getClassLoader());
System.out.println(findObject instanceof MyClassLoader2);
}
}
若有帮助,谢谢采纳~