“new”关键字在Java中实际起什么作用?我应该避免创建新对象吗? 我在几分钟前注册了,虽然自从我开始从事计算机编程以来,我一直在利用这个网站,我一直在自学,考虑我的一点爱好。

“new”关键字在Java中实际起什么作用?我应该避免创建新对象吗? 我在几分钟前注册了,虽然自从我开始从事计算机编程以来,我一直在利用这个网站,我一直在自学,考虑我的一点爱好。,java,object,constructor,new-operator,Java,Object,Constructor,New Operator,我确实找过类似的问题,但事实上我找不到我想要的答案。 现在,意识到,在java中我建议开始的语言,认为在需要时声明和实例化变量是一个好的编程实践,请考虑以下几行: class MyClass { void myMethod() { AnotherClass myObject = new AnotherClass(); myObject.doStuff(); } } 现在,假设我在运行我的程序时调用myMethod,比方说,10次,这是如何工作的?

我确实找过类似的问题,但事实上我找不到我想要的答案。 现在,意识到,在java中我建议开始的语言,认为在需要时声明和实例化变量是一个好的编程实践,请考虑以下几行:

class MyClass {
    void myMethod() {
        AnotherClass myObject = new AnotherClass();
        myObject.doStuff();
    }
}
现在,假设我在运行我的程序时调用myMethod,比方说,10次,这是如何工作的?是否每次都创建一个新对象?myObject变量是否每次都重新分配?编译器是否会跳过类似的代码,因为它看到对象已经创建,并且变量myObject已经分配给这样的对象?简而言之:如果我只打算调用该方法一次,我是否应该编写这样的代码? 我知道。。。我问了这么愚蠢的问题真丢脸,但请给我一个机会! 提前谢谢

--------------编辑---------------


那么现在我应该在得到新答案后编辑这篇文章吗? 顺便提一下天哪,太快了,非常感谢!哇,这让我很困惑,我想这是因为我一直在自学。。。 无论如何,每次为myObject变量创建一个新的其他类对象不是没有用吗?我的意思是,如果我想在整个程序中使用myObject变量,我不应该一次性声明它吗?也许在另一个方法中,我只调用一次?因为据我所知,每次调用myMethod时,都会创建一个新的对象,从而覆盖myObject自身的属性,也就是变量,还是我在胡说八道

--------------编辑---------------

在阅读了一些我现在记不起来的网站上的代码后,我产生了怀疑:

    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 和其他变量一样在班上名列前茅? 为什么不在构造函数中初始化它们呢? 为什么每次调用方法时都这样做,而不是使用同一个实例变量

现在,假设我在运行 程序,如何工作?是否每次都创建一个新对象

对!


重用或不重用实例化对象取决于设计和情况。在某些情况下,最好重用对象,在这种情况下,您可以创建一个类字段来保留引用,并且在某些情况下,最好每次创建一个新对象,例如,查看不可变性。

是的,每次都创建一个新对象。在堆栈中分配对每个myObject的引用

简而言之:我应该只在计划调用时编写这样的代码吗 那种方法只有一次

如果希望myObject在方法执行完成后消失,则选择“是”。如果出于某种原因,需要保留对它的引用,则可以将其声明为类成员

class MyClass {
    AnotherClass myObject;
    void myMethod() {
        myObject = new AnotherClass();
        myObject.doStuff();
    }
}
这样,每次调用myMethod时仍然会创建它,但在myMethod完成后它仍然存在。这可能很方便,也可能不方便,这取决于具体情况

编译器看到对象时是否跳过类似的代码 已创建,并且变量myObject已被删除 分配给这样的对象

这在使用新工具时不会发生。可以保证它将创建一个新实例。它可以使用编译器来实现,而不是跳过代码行,而是阻止创建新对象。例如,实现了这一点:如果您尝试获取一个介于-128和127之间的整数,它将始终返回相同的实例,并且在使用其工厂方法时不会创建新对象

当然,使用new不会返回相同的实例,但总是返回一个新实例

 Integer five = new Integer("5");//Will create a new object each time.
 Integer otherFive = new Integer("5");

 assert(five==otherFive);//false
问题更新后 关于您添加的代码,真的没有什么好说的。 然而,如果你看一看,你会注意到两种方法。根据它的名字,一个似乎是写的,另一个似乎是读的。这种行为特定于每个方法,因此writeFile的方法不关心用于读取的对象。readFile方法不关心用于写入的对象。因此,使文件读取器可用于writeFile方法是没有意义的,等等

回到您最初的问题,是的,每次调用该方法时都会实例化一个新对象。这并不重要。最好不要问自己为什么readFile方法可以访问FileWriter实例?

每次调用myMethod方法时,代码都从顶部执行,没有关于它在以前执行中所做操作的内存,当然,除非您更改了MyClass对象的某些字段。这意味着每次运行该方法时,都将创建一个新的其他类对象 并将其存储在myObject中。更一般地说,方法的每次执行都将从顶部运行代码,并且不会避免重新计算值,即使这些值可能已从以前的迭代中缓存,除非将值显式存储在某个位置


如果这不是您想要的,而是您想要存储您分配的对象,以便在以后的迭代中可以再次引用它,您可以将其存储在类的实例变量中。

每次调用该方法时都会创建一个新对象。如果控件到达带有新运算符的代码行,则将创建一个对象;没有幕后缓存或其他魔法。

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

new关键字完全按照tin上的说明执行,它创建了一个全新的对象,而不管该对象是否已经存在。它创建一个新对象,并将对该对象的引用填充到给定的变量中,覆盖该变量所持有的任何以前的值对象

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

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

简而言之:如果我只打算调用该方法一次,我是否应该编写这样的代码

正如我所说的,在上面的示例中,如果您没有将对象引用分配给方法范围之外的变量,则每个对象都将在方法执行结束时被销毁,因此在您的示例中,您可以随意多次调用该方法,但每次都不会连接到以前的调用

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

更新答案以反映已编辑的问题 '为什么不像对其他变量那样在类的顶部声明FileWriter、FileReader、BufferedReader和BufferedWriter?'

好的,我假设您理解变量实际上不是FileWriter、FileReader、BufferedReader和BufferedWriter,而是变量类型。它们的名字是fw、fr、br和bw。如果你不明白我的意思,就问吧。从现在起,我将通过您使用的名称来引用变量,以使阅读更容易,毕竟fw只是代表FileWriter,所以不应该有太多的混淆

这个问题的关键隐藏在变量本身的名称中。注意它们是如何以Reader或Writer结尾的,这可以给我们一个关于它们用途的微妙线索。显然,FileWriter和BufferedWriter在某种程度上与输出有关。通过查看代码,我们发现我们的怀疑是正确的,除了writeTextJTextArea方法之外,这些变量在任何时候都不会出现。因此,如果变量没有在代码中的任何其他地方使用,那么在使用它们的方法中定义和初始化它们是合乎逻辑的,这不仅使代码更易于阅读,因为我们知道这些变量只与该方法相关,但也有一个好处,就是在方法执行结束时删除这些变量,从而不会留下只使用了很短时间的变量。根据这些规则,我们可以说FileReader和BufferedReader也是如此

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

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!
因为类型根本不匹配


有意义吗?

如果调用10次,java堆栈中将有10个方法框架,每个框架将执行新操作,当框架完成时,它将释放


没有愚蠢的问题…所以现在我应该在得到新答案后编辑这篇文章吗?不总是这样,除非原始问题有更新或不清楚的地方。我问这个问题是因为我记不住
起来!你经常编辑你的答案,这显然很好,只是我没想到会有这么好的回复,我不知道该评论什么帖子或提供反馈!如果每次都要使用相同的实例,则需要将其保存在某个位置。通常情况下,这就是实例成员的作用。嘿,伙计,你的解释其实很清楚,但对我来说,听起来很新鲜的是,当你说对象将在方法执行结束时被销毁。。。那是你给我的一条令人兴奋的信息!那么我应该在什么时候写代码呢?为什么?在@Tom示例中,在对象创建和变量分配方面有什么变化?我不完全确定您的要求,所以如果我有错误,请告诉我。您编写代码的方式没有任何问题,它完全取决于您正在开发的内容,即您何时希望在方法执行后保持对象存在,何时不希望,除了您希望对象变量在方法结束后仍然存在外,对于何时使用一种或另一种方式没有固定的答案,例如,您计划在其他地方使用该对象,或者该对象是否完成了工作,并且您很高兴它被销毁。这是你问题的正确方向吗?是的,你实际上帮了我很多忙。我想让你再看一遍我的问题,我用一些新的代码编辑了它,这可能会帮助你理解我的疑问。很抱歉回复太晚,我一直在工作。我会在另一篇帖子中简明扼要地回复,所以请注意,我的朋友。嘿,伙计,谢谢你的重播,我通读了一遍,我说的很有道理。这很有帮助,peace。如果每个方法调用下一个,堆栈上只有10帧。一旦一个方法完成,它的堆栈框架就被回收。这取决于虚拟数学的实现。这一行是什么意思?在堆栈中分配对每个myObject的引用。分配是在堆栈中还是在堆中?可以说,对象引用或内存位置是在堆栈中分配的,但是,对象内容保留在堆中,并且引用指向堆中查找它的位置。类似于一个人的地址可以在一个小小的电话簿堆栈中找到,而地址指的是大世界堆中的一个地方。换句话说,你的名字在电话簿上,让人们找到你的地址,你的身体在你的家里,如果人们按照这个地址走,他们会找到你的身体。
FileReader fr = new BufferedReader(fr); // Is not valid!