简体   繁体   English

对象,引用和类。 需要帮助了解一些代码

[英]Object, reference and class. Need help understanding some code

I kind of understand that: 我有点理解:

  • A class is kind of a blueprint that objects can be created from. 类是可以用来创建对象的蓝图。
  • A object is an actual instance or object that gets created. 对象是创建的实际实例或对象。
  • A reference is like an address that points to said object. 引用就像指向该对象的地址。

What exactly happens when the below code is called twice? 两次调用以下代码会发生什么?

Car batmobile = new Car();

Will two objects get created? 是否会创建两个对象? If so, what happens to the first object? 如果是这样,第一个对象发生了什么? In detail, what happens in terms of class, object and reference? 详细地说,在类,对象和引用方面会发生什么?

Part 2: 第2部分:

Is this an infinite loop? 这是一个无限循环吗? Will objects keep getting created since the constructor makes an object and then calls on the constructor again? 自构造函数创建对象以来,对象会继续创建吗? How does the class, object, reference relation work here? 类,对象,引用关系在这里如何工作?

public class Alphabet {
  Alphabet abc;

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

Car batmobile = new Car(); 汽车batmobile = new Car(); Will two objects get created? 是否会创建两个对象?

If it's called twice then yes. 如果调用两次,则为是。 Because the line creates a new instance of an object. 因为该行创建了一个对象的新实例。 So doing that twice would result in two new instances. 因此,执行两次将导致两个新实例。 Note, however, that if you try to execute that same exact line twice in a row then you would get a compiler error because you'd be trying to re-declare the same variable in the same scope. 但是请注意,如果您尝试连续两次执行相同的确切行,则会出现编译器错误,因为您将尝试在同一作用域中重新声明相同的变量。

But otherwise, no, there's only one object being created on that line. 但是否则,不会,在该行上仅创建一个对象。 Car is mentioned twice because it declares the type for the variable ( batmobile ) and for the constructor ( Car() ). 两次提到Car是因为它声明了变量( batmobile )和构造函数( Car() )的类型。 Some languages (C#, JavaScript, untyped languages, etc. but not Java) have shorthand for the first use, since it's easily inferred from the second. 某些语言(C#,JavaScript,无类型语言等,但Java没有)具有速记功能,因为很容易从第二种语言推断出来。 For example: 例如:

var batmobile = new Car();

Is this an infinite loop? 这是一个无限循环吗?

Nope, there's no loop here: 不,这里没有循环:

Public class Alphabet{
    Alphabet abc;

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

There is , however, a stack waiting to be overflown. ,然而,一个堆栈等待飞越。 In order to create an Alphabet one must first create an Alphabet . 为了创建一个Alphabet必须首先创建一个Alphabet Run the code and see the error. 运行代码,然后查看错误。 An infinite loop would just execute infinitely (assuming each iteration of the loop didn't compound the use of some finite resource), for example: 无限循环将无限执行(假设循环的每次迭代都不会增加某些有限资源的使用),例如:

while (true) {
    Car batmobile = new Car();
}

This will execute without end. 这将无休止地执行。 The code you posted, however, will end. 但是,您发布的代码将结束。 With an error. 有错误。 Because each call to the constructor internally calls the constructor. 因为每次对构造函数的调用都会在内部调用构造函数。 The call stack is a finite resource, so it will very quickly be exhausted. 调用堆栈是有限的资源,因此它将很快耗尽。

I use a cookie metaphor to explain Objects and Classes. 我用一个cookie隐喻来解释对象和类。

Think of the memory of a computer as a big lump of cookie dough. 将计算机的内存想像成一大堆饼干面团。 (Yummy, isn't it?) (好吃,不是吗?)

Your class is a cookie cutter. 您的课程是小甜饼刀。 It will create cookies of a particular size and shape as long as you have dough (memory). 只要您有面团(记忆),它将创建特定大小和形状的Cookie。 An object is a cookie cut with the cookie cutter. 一个对象是用cookie切割器剪切的cookie。

1) batmobile is a reference to a Car object. 1)batmobile是对Car对象的引用。 It can only point to a Car or a subclass of car. 它只能指向Car或car的子类。 It has no object instance (dough) attached to it when it is created. 创建对象时,没有附加对象实例(面团)。 When you call new Car() you stamp out an object instance and assign it to a reference called batmobile. 调用new Car()时,将对象实例标记出来,并将其分配给名为batmobile的引用。 There is only one reference. 只有一个参考。

2) Don't do this. 2)不要这样做。 You might end up with a stack overflow, I'm not sure, but it's not going to get you the results that you want. 我不确定,您可能最终会导致堆栈溢出,但这不会为您带来所需的结果。 You might want to look up Singleton pattern. 您可能要查找Singleton模式。 It might help you. 它可能会帮助您。

Now I need help understanding what exactly happens when this code is called twice. 现在,我需要帮助来了解两次调用此代码时究竟发生了什么。

Ex: Car batmobile = new Car(); 例如: Car batmobile = new Car();

Will two objects get created? 是否会创建两个对象?

A Car object will be created each time that line is executed, so if you execute it twice, yes, two objects are created. 每次执行该行时,都会创建一个Car对象,因此,如果执行两次,则将创建两个对象。

If so what happens to the first object. 如果是这样,第一个对象发生了什么。

If nothing else has a reference to it, it becomes eligible for garbage collection by the JVM. 如果没有其他引用,JVM就有资格对其进行垃圾回收。 When and whether that happens depends on many factors within the JVM's garbage collector. 何时以及是否发生这种情况取决于JVM的垃圾收集器中的许多因素。

Can someone explain in detail what happens in terms of class,object and reference. 有人可以详细解释在类,对象和引用方面会发生什么。

Car batmobile

...declares a variable of type Car . ...声明一个Car类型的变量。 Because it's an object type, the variable will end up holding an object reference (or null , which means it's not holding a reference to any object). 因为它是对象类型,所以该变量最终将保存对象引用 (或null ,这意味着它不保存对任何对象的引用)。 The actual object exists independently of any variables that may have a reference to it (and there may be many references to one object). 实际对象独立于可能引用它的任何变量而存在(并且可能有多个引用到一个对象)。 An object reference is like a memory address saying where in memory the object is. 对象引用就像一个内存地址,说明对象在内存中的位置。 (It is not a memory address, but it's like one.) (它不是一个内存地址,但是就像一个。)

new Car();

...creates a new Car object and calls the Car constructor to initialize it. ...创建一个新的Car对象,并调用Car构造函数对其进行初始化。 So: 所以:

Car batmobile = new Car();

...declares a variable, creates an object, calls the Car constructor, and assigns a reference to that object to batmobile . ...声明一个变量,创建一个对象,调用Car构造函数,并将对该对象的引用分配给batmobile

Is this an infinite loop? 这是一个无限循环吗?

It would be, but eventually you'll run out of stack space, so it's a stack overflow error . 可能会,但是最终您会耗尽堆栈空间,因此这是一个堆栈溢出错误 That line calls the Alphabet constructor, which calls the Alphabet constructor, which calls the Alphabet constructor... You get the idea. 该行调用了Alphabet构造函数,该函数调用了Alphabet构造函数,该函数又调用了Alphabet构造函数...您明白了。

Question 1 问题1

Car batmobile = new Car();

This creates one object. 这将创建一个对象。 The object is of type Car and its identifier is 'batmobile'. 该对象为Car类型,其标识符为“ batmobile”。 In terms of its reference, batmobile will be popped onto the stack and it will contain a reference to an object of type Car on the heap. 根据其引用, batmobile将被弹出到堆栈上,并且将包含对堆上Car类型的对象的引用。

This question may help with stack and heap memory explanations. 这个问题可能对堆栈和堆内存的解释有所帮助。

Question 2 问题2

Ironically, seeing as this is posted on SO, this example would result in a stack overflow error. 具有讽刺意味的是,看到此示例已发布在SO上,则此示例将导致堆栈溢出错误。 Each call to the constructor creates a new object with a reference to it placed on the stack before calling the constructor again. 每次对构造函数的调用都会创建一个新对象,并将对该对象的引用放在堆栈上,然后再次调用该构造函数。 The stack is an area of limited memory so eventually this is going to overflow and your program will terminate with a stack overflow error 堆栈是内存有限的区域,因此最终它将溢出,并且您的程序将因堆栈溢出错误而终止

In C++, when you write: 在C ++中,编写时:

SomeClass x;

It automatically creates an instance of SomeClass . 它会自动创建SomeClass的实例。 Not so in Java. 在Java中不是这样。

In Java, the same line above simply creates a variable named x whose type is SomeClass . 在Java中,上面的同一行仅创建了一个名为x的变量,其类型为SomeClass The variable x doesn't refer to anything (any instance) until you initialize to something. 变量x在初始化为某种东西之前不会引用任何东西(任何实例)。

In Java, the line below creates one object and initializes the variable x to point to it. 在Java中,下面的行创建一个对象,并初始化变量x指向它。

SomeClass x = new SomeClass();

Your code block: 您的代码块:

Public class Alphabet{
    Alphabet abc;

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

Doesn't actually do anything, since the constructor is never called. 实际上不执行任何操作,因为从不调用构造函数。 If you did call it like: 如果您确实这样称呼它:

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

The following would happen: 将会发生以下情况:

  1. Create new instance of Alphabet 创建新的Alphabet实例
  2. Call constructor for Alphabet (from main method) 调用Alphabet的构造函数(从main方法)
  3. Create new instance of Alphabet (to be assigned to member variable abc ) 创建新的Alphabet实例(分配给成员变量abc
  4. Call constructor for Alphabet (from constructor of Alphabet) 调用Alphabet的构造函数(来自Alphabet的构造函数)
  5. Continue recursion (steps 3 - 4) until StackOverflowError occurs 继续递归(步骤3-4),直到发生StackOverflowError

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM