当我可以用后者创建文件时,为什么我应该创建 File 对象然后在 FileWriter 或 PrintWriter 中使用它?

Why should I create File object and then use it in FileWriter or PrintWriter when I can create file with latter ones?

为什么:

File file = new File("somefile.txt");
PrintWriter printWriter = new PrintWriter(file);

当我们可以直接:

PrintWriter printWriter = new PrintWriter("somefile.txt");

我理解这个概念并理解 File() 构造函数创建文件的抽象,但是把这归结为实际问题,为什么要创建 File 对象然后将其传递给 FileWriter? (或任何其他编写器构造函数)

目的是什么?

方法只是重载。它的主要目的是为用户提供一种更舒适的方式来使用 PrintWriter.

如果您当前的文件是 File 对象,您可以直接传递它。 如果你有它作为 OutputStream,你可以使用它。 如果你有一个 String 表示路径,就用它等等。

在内部,它们都分解为打开 OutputStream 资源的相同方法。

假设您不是自己创建资源,而是通过另一种方法将其作为对象获取。如果方法 returns 一个 File 对象和 PrintWriter 没有这个额外的构造函数,您将需要从文件对象中提取 path。那是额外的一行代码,计算机科学家很懒惰...

此外,主要构造函数将是使用 OutputStream 的构造函数,因为这是最灵活的对象,它还允许打​​印到非文件的内容,如 Web 资源或其他流。 如果您现在只想将一些行写入文件,那么额外的构造函数非常方便,可以节省一些代码行。

如果您只想在文件系统的给定位置创建一个新文件,请确定为什么不使用 new PrintWriter(String path)。对于这种情况似乎很方便。但是,您可能不想将路径表示为 String。可能目标位置是复杂且相对的,那么 File 会更方便。就像 new File("testFile", directory) 一样,它将文件创建到具有相对路径的 File 目录中。

只使用看起来最适合您当前情况的构造函数。

这很方便。检查构造函数的源代码。 (开启JDK实现)

public PrintWriter(String fileName) throws FileNotFoundException {
    this(new BufferedWriter(new OutputStreamWriter(new FileOutputStream(fileName))), false);
}

public FileOutputStream(String name) throws FileNotFoundException {
    this(name != null ? new File(name) : null, false);
}

在您的示例中,两个版本执行相同的操作。唯一真正的区别是代码的可读性。 (由您决定您认为哪个版本更具可读性。)

另一方面,如果您需要对文件路径名进行操作,最好使用 FilePath 来做,而不是尝试使用字符串做同样的事情抨击。示例包括获取父目录路径、形成子目录路径、添加或删除文件名后缀。通过使用 FilePath,您通常可以避免复杂情况,例如路径名语法中的平台特定差异。

此外,FilePath(以及相关的 类)允许您对文件/目录本身执行其他操作。例如,重命名/移动、删除或测试和更改权限。

简而言之,在 其他 情况下,可能有充分的理由更喜欢使用 File,等等。但在您的示例中,它没有真正的区别。

主要原因是基于名为 separation of concerns 的架构范例。

如果您只是处理这个特定的案例,那么只需进行第二次调用并将两个操作封装在一行中会更简单。但是从软件架构的角度来看,您正在用一个 operation.The 解决两个不同的问题,第一个问题是定义和初始化输出。第二个是写入选择的输出。

这意味着如果将来您想要更改您的应用程序以使用不同的输出,如网络连接、控制台或其他,您将需要更改整个操作,因为网络连接不能描述为字符串,如文件。但是,如果您将 Writer 作为通用操作使用,它将始终接收初始化的输出流,以后您将不需要进行更改。

你的例子是一个简单的案例,所有这些关于软件架构的讨论可能被视为有点复杂。但是,一旦您开始使用这种关注点分离的思想工作,您的代码就会更加一致,可能会更冗长,但会更健壮。