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

Java 为什么我的反射加载奇怪的类?,java,reflection,Java,Reflection,我正在尝试使用反射,看看我是否能够达到这样一个程度:我能够键入一个类名,我的应用程序将加载该类并创建它的实例。经过几次尝试后,我发现我不能只在class.forName()中粘贴一个没有包名的类名,因此我尝试获取一个已加载的所有可用包的列表,并尝试加载我键入的带有每个包名的类,直到它成功 到目前为止,我得到的是: BufferedReader console = new BufferedReader(new InputStreamReader(System.in)); String s

我正在尝试使用反射,看看我是否能够达到这样一个程度:我能够键入一个类名,我的应用程序将加载该类并创建它的实例。经过几次尝试后,我发现我不能只在
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的
包有什么特别之处导致了这种情况?我真的不在乎我的代码不能完全按照我想要的方式工作,我只想知道是什么导致了这种奇怪的行为

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) 

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

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

您的代码返回“怪异”类,因为它所做的工作在概念上是不正确的。任何规范都没有规定“rt.jar”文件中条目的物理顺序。他们只是碰巧在一个顺序,结果是你发现了一个“奇怪的”一个给定的方式,你正在做的迭代。在另一个Java版本中,您的代码可能会为您提供“非怪异的”
对象
类。不管是哪种方式,假设你将通过这种方式得到“正确”的类是。。。有缺陷


你说你这样做是因为:

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

如果你要实现一个解释器,你需要理解Java语言。 您需要了解的一点是,在Java中可以有许多具有相同简单名称的类。这意味着,扫描具有给定简单名称的任何类的类路径的想法是不实际的。您会发现,对于常用的类,存在太多的“冲突”(即具有相同简单名称的类)

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


简言之,抛开上面的代码,重新开始。

我只是想到了一件事:当我创建一个类时,我从来没有中断过我的循环。因此,这件事实际上可能是设法到达
java.lang.Object
,它将加载的类设置为true,但它在循环中继续,覆盖了加载的实际类,
sun.net.util
可能是我系统上加载的最后一个包。我所需要的只是一个中断声明,它应该能阻止这种行为。

我想。。。您认为忽略
sun.*
包和
com.sun.*
以避免这种行为安全吗?有没有更好的方法进行类/包查找?用于什么目的?只是为了实验?而且您不能完全忽略
com.sun
,因为这些类中的一些在正常操作中是经常可见的,通常在接口后面(例如,由
字符串
查找键选择的加密算法的实现)。SCTP库IIRC也在
com.sun
中直接使用。是的,非常多。我想尝试制作一个Java解释器:DTry分解BeanShell;你可能会发现一些有趣的复活节彩蛋。我不知道BeanShell是开源的。。。酷!我一直在等待这个答案:)就像我说的,这段代码只是为了实验,我对反射几乎没有经验,所以我只是想把脚弄湿。另外,我的问题是“为什么这段代码会加载奇怪的类”,而不是“如何修复它”。不过,谢谢你的提示,我可能会再次过来寻求有关进口计划的帮助:)我已经回答了你问题中的“为什么”部分。(我以前没有这样做,因为我认为这是多余的。但既然你坚持…)除非如果“怪异”类是第一个出现的,那么该方案将失败。或者如果这两个类都不是“怪异的”;e、 g.
java.util.Date
java.sql.Date
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)