代码之家  ›  专栏  ›  技术社区  ›  mpobrien

有没有一种方法可以强制类加载器加载包,即使没有加载任何类?

  •  15
  • mpobrien  · 技术社区  · 15 年前

    假设Java代码库有一个名为“COM.Supe”的包。

    在运行时,我们可以通过调用

    Package p = Package.getPackage( "com.example" ); //(returns null)
    

    甚至可以通过调用

    Packages[] ps = Package.getPackages();
    

    问题是-如果类加载器还没有从包中加载任何类,那么它将不可用于这些函数调用。我们可以通过强制首先加载包中的一个类来强制它加载包,如下所示:

    this.getClass().getClassLoader().loadClass( "com.example.SomeClass" );
    Package p = Package.getPackage( "com.example" ); //(returns non-null)
    

    然而,这是一种黑客行为,需要提前知道属于包的某个类的名称。

    所以问题是——有没有任何方法可以按名称获取包的实例,不管类加载器是否做过什么?我对类加载/包在这种情况下如何工作的假设是否准确?

    3 回复  |  直到 8 年前
        1
  •  11
  •   Adriaan Koster    15 年前

    或者,您可以使用类根目录作为起点,并遍历所有*.class文件和子目录。只有当您事先知道所有.class文件将驻留在哪里时,这才有效。

    这一切的原因是Java具有动态的类加载,因此类可以在运行时从编译时或甚至在启动时未知的位置加载。因此,包的概念只是已加载类的名称空间,而不是可以用来查找它们的目录。

        2
  •  5
  •   bmargulies    15 年前

    恐怕你的假设是无效的。类装入器在装入类时进行包簿记。

    可以将通配符传递给 ClassLoader.getResources 然后强制它在一个包中挑选类,这将依次完成工作。

    您可以创建自己的类加载器来调用 definePackage 但这对你使用的普通香草类装载机没有帮助。

        3
  •  5
  •   mgaert    8 年前

    我认为你需要这个,因为你需要检查它的注释。否则,您将不会有兴趣拥有一个包引用,该包引用只有围绕访问注释的操作。这导致了这样的假设,即您也在其中定义了一个package-info.java,其中包含一些注释。

    如果你检查 java.lang.Package 你会看到 getPackageInfo 只是将包信息类作为普通类加载。

    我也遇到了同样的问题,并提出了这个解决方案。

    public static Package getPackage(String packageName) throws ClassNotFoundException {
        Class.forName(packageName+".package-info"); // makes sure package info exist and that the class loader already knows about the package
        return Package.getPackage(packageName);
    }