“new”关键字在 Java 中的实际作用是什么,我应该避免创建新对象吗?

新手上路,请多包涵

几分钟前我注册了,尽管自从我开始学习计算机编程以来,我一直在充分利用这个网站,我一直在自学,并认为这是我的一个小爱好。

我确实查找了类似的问题,但实际上我找不到我要寻找的答案。现在,请注意,在 Java(这是我被建议开始使用的语言)中,根据需要声明和实例化变量被认为是良好的编程习惯,请考虑以下几行:

 class MyClass {
    void myMethod() {
        AnotherClass myObject = new AnotherClass();
        myObject.doStuff();
    }
}

现在,假设我在运行我的程序时调用 myMethod() 10 次,它是如何工作的?每次都创建一个新对象吗? myObject 变量是否每次都重新分配?编译器是否会跳过类似的代码,因为它看到对象已经创建并且变量 myObject 已经分配给该对象?简而言之:只有当我打算只调用该方法一次时,我才应该编写这样的代码吗?我知道…问这样一个愚蠢的问题让我感到羞耻,但请给我一个机会!提前致谢!

--------------------------编辑-------------------- ——

那么现在我应该在得到新答案后编辑这篇文章吗?顺便说一句…天哪,太快了,非常感谢!哇,这让我很困惑,很多,我想这是因为我一直在自学……无论如何,创建一个 new AnotherClass 对象不是没有用的 myObject 每次都是变量?我的意思是,如果我想在整个程序中使用 myObject 变量,难道我不应该一劳永逸地声明它吗?也许在另一种方法中,我将只调用一次?因为据我所知,每次我调用 myMethod() 都会创建一个新对象,从而覆盖 myObject 自己的属性 aka 变量,或者我只是在胡说八道?

--------------------------编辑-------------------- ——

从我现在不记得的某个网站上阅读这段代码后,我产生了疑问:

     public class DataBase {

    private static String buf, retString = "\n";
    private static File file = new File("test.txt");

    public static void readText(JTextArea area) {
        try {
            FileReader fr = new FileReader (file);
            BufferedReader br = new BufferedReader(fr);
            while ((buf = br.readLine()) != null) {
                area.append(buf);
                area.append(retString);
            }
            br.close();
            fr.close();
        }
        catch (IOException e) {
            System.out.println("Exception: " + e);
        }
    }

    public static void writeText(JTextArea area) {
        try {
            FileWriter fw = new FileWriter (file);
            BufferedWriter bw = new BufferedWriter(fw);
            bw.write(area.getText());
            bw.close();
            fw.close();
        }
        catch (IOException e) {
            System.out.println("Exception: " + e);
        }
    }
}

我的意思是,为什么不像其他变量那样在类的顶部声明 FileWriter、FileReader、BufferedReader 和 BufferedWriter?为什么不在构造函数中也初始化它们呢?为什么每次调用方法时都这样做而不是使用可能相同的实例变量?

原文由 zeme 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 734
1 个回答

是的,如果您调用 myMethod() 10 次,它将创建 10 个唯一且独立的对象。

new 关键字完全按照锡罐上所说的那样,它创建一个全新的对象,无论是否已经存在。它创建一个新对象并将对该对象的引用填充到它已被赋予的变量中,覆盖变量持有的任何先前值(对象)。

myObject 变量是否每次都重新分配?

同样,是的,每次调用该方法时,它都会重新分配一个新对象。关于这一点的一个有趣的注意事项是,当您在方法主体本身内定义变量时,变量不会“真正”被重新分配,因此每次方法结束时,它都会删除在其范围内定义的变量.所以它实际上做的是创建 10 个单独的变量并分配 10 个单独的对象,尽管正如我所说的,其他的应该已经自动删除,所以它不会使用任何额外的内存。

简而言之:只有当我打算只调用该方法一次时,我才应该编写这样的代码吗?

正如我所说,在上面的示例中,每个对象都将在方法执行结束时被销毁(假设您没有将对象引用分配给方法范围之外的变量)所以在您的示例中您可以愉快地调用该方法想打多少次就打多少次,但每次都不会连接到之前的电话。

我知道我的写作方式可能会令人困惑,所以如果你想让我澄清任何事情,尽管问。

更新答案以反映已编辑的问题

“为什么不像其他变量那样在类的顶部声明 FileWriter、FileReader、BufferedReader 和 BufferedWriter?”

Okay, I assume you understand that the variables are not actually called FileWriter , FileReader , BufferedReader , and BufferedWriter , but rather this is变量类型。他们的名字是 fwfrbrbw 如果你不明白我的意思,就问吧。从现在开始,我将按照您所做的名称来引用变量,以便于阅读,毕竟 fw 代表 FileWriter 无论如何,所以不应该有太多的混淆。

这个问题的关键隐藏在变量本身的名称中。请注意它们是如何以 ReaderWriter 结尾的,这可以为我们提供有关它们用途的微妙线索。显然 FileWriterBufferedWriter 以某种方式与输出有关。通过查看代码,我们发现我们的怀疑是正确的,除了在 writeText(JTextArea area) 方法之外,这些变量没有出现。因此,如果该变量未在代码中的其他任何地方使用,那么在使用它们的方法中定义和初始化它们在逻辑上是有意义的,这不仅使代码更易于阅读,因为我们随后“知道”了那些变量仅与该方法相关,但也有在方法执行结束时删除这些变量的好处,因此不会留下仅被非常短暂使用的变量。根据这些规则,我们可以说 FileReaderBufferedReader 也是如此。

观察这个关于变量范围的例子。 (看我在代码中添加的注释)

 public class DataBase {

private static String buf, retString = "\n"; // buf & retString - created
private static File file = new File("test.txt"); // file - created

public static void readText(JTextArea area) {
    try {
        FileReader fr = new FileReader (file); // fr (FileReader) - created
        BufferedReader br = new BufferedReader(fr); // br (BufferedReader) - created
        while ((buf = br.readLine()) != null) {
            area.append(buf);
            area.append(retString);
        }
        br.close();
        fr.close();
    } // fr (FileReader & br (BufferedReader) - destroyed
    catch (IOException e) {
        System.out.println("Exception: " + e);
    }
}

public static void writeText(JTextArea area) {
    try {
        FileWriter fw = new FileWriter (file); // fw (FileWriter) - created
        BufferedWriter bw = new BufferedWriter(fw); // bw (BufferedWriter) - created
        bw.write(area.getText());
        bw.close();
        fw.close();
    } // fw & bw - destroyed
    catch (IOException e) {
        System.out.println("Exception: " + e);
    }
}
} // buf, retString and file - Still exist as long as the object exists

从这个例子中可以更加清楚为什么变量在方法中定义而不是作为实例变量并在构造函数中初始化。它允许更简洁的代码以及更具可读性。

为什么每次调用方法时都这样做而不是使用可能相同的实例变量?

那么这个问题与变量类型有关。我们不能为所有信息重用一个变量,因为类型需要不同。

如果我们从代码中获取所有变量

private static String buf, retString = "\n"; // valid
private static File file = new File("test.txt"); // valid

FileReader fr = new FileReader (file); // valid
BufferedReader br = new BufferedReader(fr); // valid
FileWriter fw = new FileWriter (file); // valid
BufferedWriter bw = new BufferedWriter(fw); // valid

现在我们知道我们不能将与变量类型不同的值放入该变量中,所以像

FileReader fr = new BufferedReader(fr); // Is not valid!

因为类型根本不匹配。

说得通?

原文由 linuscash 发布,翻译遵循 CC BY-SA 3.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题