对象,参考和类。需要帮助理解一些代码

时间:2015-08-19 14:09:31

标签: java class object reference

我有点明白:

  • 类是一种可以从中创建对象的蓝图。
  • 对象是创建的实际实例或对象。
  • 引用就像指向所述对象的地址。

下面的代码被调用两次时到底发生了什么?

Car batmobile = new Car();

是否会创建两个对象?如果是这样,第一个对象会发生什么? 详细说明,在类,对象和引用方面会发生什么?

第2部分:

这是一个无限循环吗?因为构造函数创建一个对象然后再次调用构造函数,是否会继续创建对象?类,对象,引用关系如何在这里工作?

public class Alphabet {
  Alphabet abc;

  public Alphabet() {
    abc = new Alphabet();
  }
}

5 个答案:

答案 0 :(得分:2)

  

Car batmobile = new Car();是否会创建两个对象?

如果它被称为两次那么是。因为该行创建了一个对象的新实例。这样做两次会导致两个新实例。但请注意,如果您尝试连续两次执行相同的确切行,则会出现编译器错误,因为您试图在同一范围内重新声明相同的变量。

但是否则,不,那条线上只创建了一个对象。 batmobile被提及两次,因为它声明了变量(Car())和构造函数(var batmobile = new Car(); )的类型。有些语言(C#,JavaScript,无类型语言等但不是Java)在第一次使用时有简写,因为它很容易从第二种语言中推断出来。例如:

Public class Alphabet{
    Alphabet abc;

    Public Alphabet(){
        abc = new Alphabet();
    }
}
  

这是一个无限循环吗?

不,这里没有循环:

Alphabet

,但是,堆栈等待溢出。要创建Alphabet,必须先创建while (true) { Car batmobile = new Car(); } 。运行代码并查看错误。无限循环只会无限执行(假设循环的每次迭代都没有使用某些有限资源),例如:

{{1}}

这将无止境地执行。但是,您发布的代码将结束。有错误。因为每次对构造函数的调用都在内部调用构造函数。调用堆栈是一个有限的资源,因此很快就会耗尽。

答案 1 :(得分:1)

我使用cookie比喻来解释对象和类。

将计算机的记忆想象成一块饼干面团。 (好吃,不是吗?)

你的班级是一个千篇一律。只要你有面团(记忆),它就会创造出特定大小和形状的饼干。一个物体是用饼干切割器切割的饼干。

1)batmobile是对Car对象的引用。它只能指向汽车或汽车的子类。它在创建时没有附加对象实例(面团)。当您调用新的Car()时,您将标记一个对象实例并将其分配给名为batmobile的引用。只有一个参考。

2)不要这样做。你可能最终会出现堆栈溢出,我不确定,但它不会得到你想要的结果。您可能想要查找Singleton模式。它可能会对你有帮助。

答案 2 :(得分:0)

  

现在我需要帮助了解在两次调用此代码时究竟发生了什么。

     

例如:Car batmobile = new Car();

     

是否会创建两个对象?

每次执行该行时都会创建一个Car对象,所以如果执行两次,是的,就会创建两个对象。

  

如果是这样,第一个对象会发生什么。

如果没有其他内容可以引用它,它就有资格通过JVM进行垃圾回收。何时以及是否发生这种情况取决于JVM垃圾收集器中的许多因素。

  

有人可以详细解释在课程,对象和参考方面会发生什么。

Car batmobile

...声明类型为Car的变量。因为它是一个对象类型,变量最终会持有一个对象引用(或null,这意味着它没有持有对任何对象的引用)。实际对象独立于任何可能引用它的变量(并且可能有许多对一个对象的引用)。对象引用是 like 一个内存地址,说明对象在内存中的位置。 (一个内存地址,但它就像一个。)

new Car();

...创建一个新的Car对象并调用Car构造函数来初始化它。所以:

Car batmobile = new Car();

...声明一个变量,创建一个对象,调用Car构造函数,并将该对象的引用分配给batmobile

  

这是一个无限循环吗?

它会,但最终你会耗尽堆栈空间,因此它是堆栈溢出错误。该行调用Alphabet构造函数,该构造函数调用Alphabet构造函数,该构造函数调用Alphabet构造函数...您明白了。

答案 3 :(得分:0)

问题1

Car batmobile = new Car();

这会创建一个对象。该对象的类型为Car,其标识符为“batmobile”#39;就其引用而言,batmobile将被弹出到堆栈上,它将包含对堆上类型为Car的对象的引用。

这个question可能有助于堆栈和堆内存解释。

问题2

具有讽刺意味的是,看到这个在SO上发布,这个例子会导致堆栈溢出错误。每次调用构造函数都会创建一个新对象,并在再次调用构造函数之前将对它的引用放在堆栈上。堆栈是一个内存有限的区域,因此最终会溢出,程序将以堆栈溢出错误终止

答案 4 :(得分:0)

在C ++中,当你写:

SomeClass x;

它会自动创建SomeClass的实例。在Java中不是这样。

在Java中,上面的同一行只是创建一个名为x的变量,其类型为SomeClass。在初始化为某些内容之前,变量x不引用任何内容(任何实例)。

在Java中,下面的行创建了一个对象并初始化变量x以指向它。

SomeClass x = new SomeClass();

您的代码块:

Public class Alphabet{
    Alphabet abc;

    Public Alphabet(){
        abc = new Alphabet();
    }
}

实际上没有做任何事情,因为从不调用构造函数。如果你这样称呼它:

public static void main(String[] args){
    new Alphabet();
}

以下情况会发生:

  1. 创建新的Alphabet实例
  2. 调用Alphabet的构造函数(来自main方法)
  3. 创建Alphabet的新实例(将分配给成员变量abc
  4. 调用Alphabet的构造函数(来自Alphabet的构造函数)
  5. 继续递归(步骤3 - 4)直到StackOverflowError发生