是否可以将对象强制转换为在所有 Java 版本中与其抽象父级(而不是其父级)具有完全相同结构的对象?

我有一个名为 java 库testlib.jar,它有一个抽象类,如下所示:


com.test;

public abstract class AbstractClass {

    public abstract void foo();

}

和一个命名MyClass如下的类:


com.test;

public class MyClass extends AbstractClass{

    @Override

    public void foo() {

        System.out.println("foo is called in MyClass");

    }

}

就是这样。在我的应用程序中,我有一个抽象类,如下所示:


com.test;

public abstract class AbstractClass {

    public abstract void foo();

}

所以它和testlib.jar. 在这里,我加载了testlib.jar文件并实例化了一个对象MyClass并将其强制转换为我的应用程序已知的抽象类(第二个):


URLClassLoader urlClassLoader = new URLClassLoader(

            new URL[]{new URL("file:\\path\\to\\testlib.jar")});

Class<AbstractClass> MyClass = (Class<AbstractClass>)urlClassLoader.loadClass("com.test.MyClass");

Constructor<AbstractClass> c = MyClass.getConstructor();

AbstractClass myObject = c.newInstance();

myObject.foo();

输出:


foo is called in MyClass

请注意,我正在投射MyClass到一个实际上不是它的父类的类。


知道这里我有两个问题:


1- 这种方法是否适用于所有 JVM?


2- JVM 如何在内部处理这个转换操作?


千万里不及你
浏览 161回答 2
2回答

莫回无

我认为您正在尝试做的是违反直觉且容易出错的。您不必使用这种方法。相反,提取您想要在库中共享的 API 并在双方共享:提供者和客户端。此外,您的示例存在缺陷,因为您使用了URLClassLoader依赖于父类加载器的构造函数:URLClassLoader urlClassLoader = new URLClassLoader(&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; new URL[]{new URL("file:\\path\\to\\testlib.jar")});正如文档所述:使用默认委托父类加载器为指定的 URL 构造一个新的 URLClassLoader。在父类加载器中首次搜索后,将按照为类和资源指定的顺序搜索 URL。所以这意味着:Class<AbstractClass> MyClass = (Class<AbstractClass>)urlClassLoader.loadClass("com.test.MyClass");您加载在当前类路径中定义的类,而不是在 JAR 中。所以这个赋值只能在AbstractClass声明的类型也指当前类路径中的哪个类型时起作用,而不是在 JAR 中:AbstractClass myObject = c.newInstance();不要使用默认的父类加载器,你可能会看到抛出 java.lang.ClassCastException:URLClassLoader urlClassLoader = new URLClassLoader(&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; new URL[]{new URL("file:\\path\\to\\testlib.jar")}, null);

12345678_0001

刚刚使用在 Android 7.1.1 上测试了这种方法DexClassLoader并且它有效,但是在 Android 4.2.2 上测试时失败了。
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Java