资源(在类路径上)

一个资源是一个路径,如姓名,它驻留在 classpath 文件数据等。资源的最常见用途是绑定应用程序图像,声音和只读数据(例如默认配置)。

可以使用 ClassLoader.getResourceClassLoader.getResourceAsStream 方法访问资源。最常见的用例是将资源放在与读取它们的类相同的包中; 在 Class.getResourceClass.getResourceAsStream 方法服务于这个常见的情况。

getResource 方法和 getResourceAsStream 方法之间的唯一区别是前者返回一个 URL,而后者打开该 URL 并返回一个 InputStream。

ClassLoader 的方法接受类似路径的资源名称作为参数,并在 ClassLoader 的类路径中搜索与该名称匹配的条目的每个位置。

  • 如果类路径位置是 .jar 文件,则具有指定名称的 jar 条目将被视为匹配项。
  • 如果类路径位置是目录,则具有指定名称的该目录下的相对文件将被视为匹配项。

资源名称类似于相对 URL 的路径部分。在*所有平台上,*它使用正斜杠(/)作为目录分隔符。它不能以斜线开头。

类的相应方法是相似的,除了:

  • 资源名称可以以斜杠开头,在这种情况下,删除初始斜杠,并将名称的其余部分传递给 ClassLoader 的相应方法。
  • 如果资源名称不以斜杠开头,则将其视为相对于正在调用其 getResource 或 getResourceAsStream 方法的类。实际的资源名称变为 package / name ,其中 package 是类所属的包的名称,每个句点都用斜杠替换, name 是给该方法的原始参数。

例如:

package com.example;

public class ExampleApplication {
    public void readImage()
    throws IOException {

        URL imageURL = ExampleApplication.class.getResource("icon.png");

        // The above statement is identical to:
        // ClassLoader loader = ExampleApplication.class.getClassLoader();
        // URL imageURL = loader.getResource("com/example/icon.png");

        Image image = ImageIO.read(imageURL);
    }
}

资源应放在命名包中,而不是放在 .jar 文件的根目录中,原因与类放在包中的原因相同:防止多个供应商之间发生冲突。例如,如果多个 .jar 文件位于类路径中,并且其中多个文件的根目录中包含 config.properties 条目,则对 getResource 或 getResourceAsStream 方法的调用将从类路径中首先列出的 .jar 返回 config.properties。。在类路径顺序不受应用程序直接控制的环境(例如 Java EE)中,这不是可预测的行为。

如果指定的资源不存在,则所有 getResource 和 getResourceAsStream 方法都返回 null。由于必须在构建时将资源添加到应用程序,因此在编写代码时应该知道它们的位置; 在运行时找不到资源的失败通常是程序员错误的结果。

资源是只读的。无法写入资源。新手开发人员经常犯错误,因为在 IDE(如 Eclipse)中进行开发时,资源是一个单独的物理文件,因此在一般情况下将其视为单独的物理文件是安全的。但是,这是不正确的; 应用程序几乎总是作为 .jar 或 .war 文件等档案进行分发,在这种情况下,资源不会是单独的文件而且不可写。 (URL 类的 getFile 方法不是解决方法;尽管它的名称,它只返回 URL 的路径部分,这绝不保证是有效的文件名。)

没有安全的方法在运行时列出资源。同样,由于开发人员负责在构建时向应用程序添加资源文件,因此开发人员应该已经知道他们的路径。虽然有解决方法,但它们并不可靠,最终会失败。