为什么我的反射会加载奇怪的类?

时间:2013-08-08 22:03:03

标签: java reflection

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

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

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.Object。我用String以及我输入的其他几个东西得到同样的东西。我尝试的一个有趣的是int - 它加载了sun.net.util.int,当我打印对象时它只返回null。另一件事发生在我尝试Java时:

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

有没有人知道这里发生了什么? sun.net.util包引起了什么特别的问题?我真的不在乎我的代码不能完全像我想要的那样工作,我只是想知道是什么导致了这种奇怪的行为。

Java版:

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位。

3 个答案:

答案 0 :(得分:3)

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


你说你这样做是因为:

  

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

如果您要实现解释器,那么您需要了解Java语言。 您需要了解的一件事是,在Java中可以有许多类具有相同的简单名称。这意味着您使用给定的简单名称扫描任何类的类路径的想法是不切实际的。您会发现常用类的“碰撞”(即具有相同简单名称的类)太多了。

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

简而言之,抛弃上面的代码然后重新开始。

答案 1 :(得分:0)

suncom.sun开头的类是JVM内部使用的内部和大多数未记录的“内务处理”类。它们不是Java API的一部分,不同的JVM将有不同的JVM。您正在查看所有这些不同内部的事实是您必须为Reflection API指定完全限定名称的原因。 ; - )

答案 2 :(得分:0)

我只是想到了一些事情:当我整理一堂课时,我从未打破过我的循环。所以这件事可能实际上是设法到达java.lang.Object,它将类加载为true,但它会在循环中继续覆盖加载的实际类,sun.net.util可能是我加载的最后一个包系统。我需要的只是一个break语句,它应该可以阻止这种行为。