'new'关键字在Java中实际上做了什么,我应该避免创建新对象吗?

zem*_*eme 31 java constructor object new-operator

我刚刚注册了,但是自从我开始学习计算机编程以来,我一直在很好地利用这个网站,我一直在自学并考虑我的一点兴趣.

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

class MyClass {
    void myMethod() {
        AnotherClass myObject = new AnotherClass();
        myObject.doStuff();
    }
}
Run Code Online (Sandbox Code Playgroud)

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

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

所以现在我应该在得到新答案后编辑这篇文章吗?顺便说一下...天哪,很快,非常感谢!哇我很困惑,我想这是因为我一直在教自己......不管怎样,每次new AnotherClassmyObject变量创建一个Object 都没用?我的意思是,如果我想在整个程序中使用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);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

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

lin*_*ash 23

是的,如果您拨打myMethod()10次​​,它将创建10个唯一且独立的对象.

new关键字不正是它在锡说,它创造了一个全新的对象,无论一个人是否已经存在.它创建一个新对象,并在给定的变量内填充对该对象的引用,覆盖变量所持有的任何先前值(对象).

每次都重新分配myObject变量吗?

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

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

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

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

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

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

好吧,我想你明白变量实际上并没有叫FileWriter,FileReader,BufferedReader,和BufferedWriter,而这是可变类型.他们的名字是fw,fr,br,和bw.如果你不明白我的意思只是问.从现在开始,我将通过您所做的名称来引用变量,以使阅读变得更加容易,毕竟fw只是代表,FileWriter所以不应该有太多的混淆.

这个问题的关键隐藏在变量本身的名称中.注意它们是如何结束的,Reader或者Writer这可以给我们一个关于它们用途的微妙线索.显然FileWriter,BufferedWriter并且以某种方式与输出有关.通过查看代码,我们看到我们的怀疑是正确的,除了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
Run Code Online (Sandbox Code Playgroud)

从这个例子可以更清楚地了解为什么变量是在方法中定义的而不是实例变量并在构造函数中初始化.它允许更清晰的代码以及更准备.

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

那么这个问题与变量类型有关.我们无法为所有信息重用单个变量,因为类型需要不同.

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

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
Run Code Online (Sandbox Code Playgroud)

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

FileReader fr = new BufferedReader(fr); // Is not valid!
Run Code Online (Sandbox Code Playgroud)

因为类型根本不匹配.

合理?


Bal*_*a R 2

现在,假设我在运行程序时调用 myMethod() 10 次,这是如何工作的?每次都会创建一个新对象吗?

是的!

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