6

我正在尝试使用反射来查看是否可以输入类名,并且我的应用程序将加载该类并创建它的实例。经过几次尝试后,我发现我不能只在Class.forName()没有包名的情况下粘贴一个类名,所以我最终尝试获取已加载的所有可用包的列表,并尝试加载我在每个包中键入的类名字直到它受到打击。

这是我到目前为止所得到的:

BufferedReader console = new BufferedReader(new InputStreamReader(System.in));
    String s = "";
    do
    {
        ClassLoader clsldr = ClassLoader.getSystemClassLoader();
        Package[] pkgs = Package.getPackages();
        s = console.readLine();
        if(s.equals(":exit"))
        {
            System.exit(0);
        }
        boolean classFound = false;
        Object loadedClass = null;
        String classname = "";
        for (int i = 0; i < pkgs.length; i++) {
            Package package1 = pkgs[i];
            try
            {
                classname = package1.getName().replace('/', '.') + "." + s;
                clsldr.loadClass(classname);
                loadedClass = Class.forName(classname);
                classFound = true;
            }
            catch(Exception e)
            {

            }

        }
        System.out.println("LOADED A CLASS!!!!");
        System.out.println(classname);
        System.out.println(loadedClass);
    }
    while(s.length() == 0);

它以一种非常奇怪的方式工作。例如,当我在提示符处输入“对象”时,它以某种方式设法加载sun.net.util.Object,但是当我打印出它打印的实际对象时class java.lang.ObjectString我输入的 a以及其他几件事也得到了同样的结果。我尝试过的一个有趣的方法是int- 它已加载sun.net.util.int,当我打印对象时它只返回 null。当我尝试时发生了另一个Java

Java
LOADED A CLASS!!!!
sun.net.util.Java
null

有谁知道这里发生了什么?sun.net.util造成这种情况的包裹有什么特别之处吗?我真的不在乎我的代码不能完全按照我的意愿工作,我只是想知道是什么导致了这种奇怪的行为。

爪哇版:

java version "1.7.0_25"                                         
Java(TM) SE Runtime Environment (build 1.7.0_25-b17)            
Java HotSpot(TM) 64-Bit Server VM (build 23.25-b01, mixed mode) 

如果这有什么不同,我使用的是 Windows 8 64 位。

4

3 回答 3

3

您的代码正在返回“奇怪”的类,因为它正在做的事情在概念上被破坏了。任何规范中都没有说明“rt.jar”文件中条目的物理顺序应该是什么。考虑到您进行迭代的方式,它们恰好处于导致您找到“奇怪”的顺序的顺序。在另一个 Java 版本中,您的代码可能会为您提供“非怪异”Object类。无论哪种方式,以这种方式获得“正确”课程的假设是......有缺陷的。


你说你这样做是因为:

“我想尝试制作 Java 解释器”

好吧,如果您要实现解释器,则需要了解 Java 语言。您需要了解的一件事是,Java 中可以有许多具有相同简单名称的类。这意味着您扫描类路径以查找具有给定简单名称的任何类的想法根本不切实际。你会发现常用的类有太多的“冲突”(即简单名称相同的类)。

在传统的 Java 中,这种冲突问题是通过通过完全限定名称引用类或通过导入它们来解决的。为了使您的解释器可用,您需要实现一个反映传统 Java 导入机制的导入方案。

简而言之,放弃上面的代码并重新开始。

于 2013-08-09T01:13:41.317 回答
0

sun以和开头的com.sun类是 JVM 内部使用的内部和大多数未记录的“管家”类。它们不是 Java API 的一部分,不同的 JVM 会有不同的。您看到所有这些不同的内部结构的事实是您必须为反射 API 指定完全限定名称的原因。;-)

于 2013-08-08T22:11:50.053 回答
0

我只是想到了一些事情:当我找到一门课时,我从来没有打破我的循环。因此,这件事实际上可能正在设法获取java.lang.Object加载为 true 的集合类,但它会继续循环,覆盖加载的实际类,并且sun.net.util可能是我系统上加载的最后一个包。我需要的只是一个 break 语句,它应该停止这种行为。

于 2013-08-09T06:35:19.720 回答