任何类都需要有一个类加载器,因此我们必须在这里给出一个。
重要的部分是这样的(在getProxyClass()的文档中
):
所有接口类型都必须通过指定的类装入器按名称可见。换句话说,对于类装入器 cl 和每个接口 i,以下表达式必须为 true:
Class.forName(i.getName(), false, cl) == i
因此,您可以使用任何类装入器,其中一个(或多个)父类装入器定义了给定的接口。
如果适用于您的情况,我想您的接口还具有类装入器(引导装入器) - 那么您使用哪个类装入器并不重要。如果你必须从你不知道的接口创建一个代理,只需采用给出的第一个接口的类加载器,并希望你的调用方没有做一些奇怪的事情。null
null
为什么需要它?
你可以想象它是这样的:
- 该方法为一个新类创建(如果它尚不存在)一些字节码,该类实现所有接口的所有方法(每个方法都只是将调用转发到您的)。
getProxyClass()
InvocationHandler
- 然后,它将此字节码传递给您指定的类装入器的方法。
defineClass
- 在此字节码中,所有接口都按名称引用,VM 现在使用引用的调用来解析这些接口。
forName
我们可以在没有任何VM魔力的纯Java中以这种方式实现它,但是我们需要为它创建一个新的类加载器(以指定的类加载器作为父级),而不是能够重用现有的类加载器。getProxyClass
实际上,这个合成类可能没有实际的字节码,因为VM能够在这里使用它的内部魔力:-)