Java和C ++之间的对象创建的主要区别是什么?

时间:2022-09-01 11:36:15

I'm preparing for an exam in Java and one of the questions which was on a previous exam was:"What is the main difference in object creation between Java and C++?"

我正准备参加Java考试,之前考试的一个问题是:“Java和C ++之间对象创建的主要区别是什么?”

I think I know the basics of object creation like for example how constructors are called and what initialization blocks do in Java and what happens when constructor of one class calls a method of another class which isn't constructed yet and so on, but I can't find anything obvious. The answer is supposed to be one or two sentences, so I don't think that description of whole object creation process in Java is what they had in mind.

我想我知道对象创建的基础知识,例如如何调用构造函数以及Java中的初始化块以及当一个类的构造函数调用另一个尚未构造的类的方法时会发生什么等等,但我可以找不到任何明显的东西。答案应该是一两句话,所以我不认为Java中整个对象创建过程的描述就是他们想到的。

Any ideas?

7 个解决方案

#1


19  

In addition to other excellent answers, one thing very important, and usually ignored/forgotten, or misunderstood (which explains why I detail the process below):

除了其他优秀的答案之外,还有一件非常重要的事情,通常被忽略/遗忘或误解(这解释了我为何详细介绍了以下流程):

  • In Java, methods are virtual, even when called from the constructor (which could lead to bugs)
  • 在Java中,方法是虚拟的,即使从构造函数调用(这可能导致错误)

  • In C++, virtual methods are not virtual when called from the constructor (which could lead to misunderstanding)
  • 在C ++中,从构造函数调用虚拟方法时不是虚拟的(这可能会导致误解)

What?

  • Let's imagine a Base class, with a virtual method foo().
  • 让我们设想一个基类,使用虚方法foo()。

  • Let's imagine a Derived class, inheriting from Base, who overrides the method foo()
  • 让我们设想一个继承自Base的派生类,它覆盖方法foo()

The difference between C++ and Java is:

C ++和Java之间的区别是:

  • In Java, calling foo() from the Base class constructor will call Derived.foo()
  • 在Java中,从Base类构造函数调用foo()将调用Derived.foo()

  • In C++, calling foo() from the Base class constructor will call Base.foo()
  • 在C ++中,从Base类构造函数调用foo()将调用Base.foo()

Why?

The "bugs" for each languages are different:

每种语言的“错误”都不同:

  • In Java, calling any method in the constructor could lead to subtle bugs, as the overridden virtual method could try to access a variable which was declared/initialized in the Derived class.
  • 在Java中,调用构造函数中的任何方法都可能导致细微的错误,因为重写的虚方法可能会尝试访问在Derived类中声明/初始化的变量。

Conceptually, the constructor’s job is to bring the object into existence (which is hardly an ordinary feat). Inside any constructor, the entire object might be only partially formed – you can know only that the base-class objects have been initialized, but you cannot know which classes are inherited from you. A dynamically-bound method call, however, reaches “forward” or “outward” into the inheritance hierarchy. It calls a method in a derived class. If you do this inside a constructor, you call a method that might manipulate members that haven’t been initialized yet – a sure recipe for disaster.

从概念上讲,构造函数的工作是使对象存在(这不是一个普通的壮举)。在任何构造函数中,整个对象可能只是部分形成 - 您只能知道基类对象已经初始化,但您无法知道哪些类是从您继承的。但是,动态绑定的方法调用会“转发”或“向外”进入继承层次结构。它在派生类中调用方法。如果你在构造函数中执行此操作,则调用一个可能操作尚未初始化的成员的方法 - 这是一个确定的灾难方法。

Bruce Eckel, http://www.codeguru.com/java/tij/tij0082.shtml

Bruce Eckel,http://www.codeguru.com/java/tij/tij0082.shtml

  • In C++, one must remember a virtual won't work as expected, as only the method of the current constructed class will be called. The reason is to avoid accessing data members or even methods that do not exist yet.
  • 在C ++中,必须记住虚拟将无法按预期工作,因为只会调用当前构造类的方法。原因是避免访问数据成员甚至是尚不存在的方法。

During base class construction, virtual functions never go down into derived classes. Instead, the object behaves as if it were of the base type. Informally speaking, during base class construction, virtual functions aren't.

在基类构造期间,虚函数永远不会进入派生类。相反,该对象的行为就像它是基类型一样。非正式地说,在基类构造期间,虚函数不是。

Scott Meyers, http://www.artima.com/cppsource/nevercall.html

Scott Meyers,http://www.artima.com/cppsource/nevercall.html

#2


22  

What is the main difference in object creation between Java and C++?

Java和C ++之间的对象创建的主要区别是什么?

Unlike Java, in C++ objects can also be created on the stack.

与Java不同,C ++对象也可以在堆栈上创建。

For example in C++ you can write

例如,在C ++中,您可以编写

Class obj; //object created on the stack

In Java you can write

在Java中你可以写

Class obj; //obj is just a reference(not an object)
obj = new Class();// obj refers to the object

#3


8  

Besides heap/stack issues I'd say: C++ constructors have initialization lists while Java uses assignment. See http://www.parashift.com/c++-faq-lite/ctors.html#faq-10.6 for details.

除了堆/堆栈问题,我会说:C ++构造函数具有初始化列表,而Java使用赋值。有关详细信息,请参阅http://www.parashift.com/c++-faq-lite/ctors.html#faq-10.6。

#4


4  

I would answer: C++ allows creating an object everywhere: on the heap, stack, member. Java forces you allocate objects on the heap, always.

我会回答:C ++允许在任何地方创建一个对象:堆,堆栈,成员。 Java强制您始终在堆上分配对象。

#5


2  

In Java, the Java Virtual Machine (JVM) that executes Java code has to might1 log all objects being created (or references to them to be exact) so that the memory allocated for them can later be freed automatically by garbage collection when objects are not referenced any more.

在Java中,执行Java代码的Java虚拟机(JVM)必须记录所有正在创建的对象(或者对它们的引用是准确的),以便以后可以通过垃圾回收自动释放为它们分配的内存。再引用。

EDIT: I'm not sure whether this can be attributed to object creation in the strict sense but it surely happens somewhen between creation and assignment to a variable, even without an explicit assignment (when you create an object without assigning it, the JVM has to auto-release it some time after that as there are no more references).

编辑:我不确定这是否可以归因于严格意义上的对象创建,但它确实在创建和赋值给变量之间发生,即使没有显式赋值(当你创建一个没有赋值的对象时,JVM有在那之后的一段时间自动释放它,因为没有更多的引用)。

In C++, only objects created on the stack are released automatically (when they get out of scope) unless you use some mechanism that handles this for you.

在C ++中,只有在堆栈上创建的对象才会自动释放(当它们超出范围时),除非您使用某种机制来为您处理此问题。

1: Depending on the JVM's implementation.

1:取决于JVM的实现。

#6


1  

There is one main design difference between constructors in C++ and Java. Other differences follow from this design decision.

C ++和Java中的构造函数之间存在一个主要的设计差异。其他差异来自此设计决策。

The main difference is that the JVM first initializes all members to zero, before starting to execute any constructor. In C++, member initialization is part of the constructor.

主要区别在于JVM在开始执行任何构造函数之前首先将所有成员初始化为零。在C ++中,成员初始化是构造函数的一部分。

The result is that during execution of a base class constructor, in C++ the members of the derived class haven't been initialized yet! In Java, they have been zero-initialized.

结果是在执行基类构造函数期间,在C ++中派生类的成员尚未初始化!在Java中,它们已被零初始化。

Hence the rule, which is explained in paercebal's answer, that virtual calls called from a constructor cannot descend into a derived class. Otherwise uninitialized members could be accessed.

因此,在paercebal的答案中解释的规则是,从构造函数调用的虚拟调用不能下降到派生类中。否则可以访问未初始化的成员。

#7


-1  

Assuming that c++ uses alloc() when the new call is made, then that might be what they are looking for. (I do not know C++, so here I can be very wrong)

假设c ++在进行新调用时使用alloc(),那么这可能就是他们正在寻找的东西。 (我不懂C ++,所以在这里我可能会非常错误)

Java's memory model allocates a chunk of memory when it needs it, and for each new it uses of this pre-allocated area. This means that a new in java is just setting a pointer to a memory segment and moving the free pointer while a new in C++ (granted it uses malloc in the background) will result in a system call.

Java的内存模型在需要时分配一块内存,并且对于每个新内存使用此预分配区域。这意味着java中的一个新东西只是设置一个指向内存段的指针并移动*指针,而C ++中的新函数(授予它在后台使用malloc)将导致系统调用。

This makes objects cheaper to create in Java than languages using malloc; at least when there is no initialization ocuring.

这使得用Java创建的对象比使用malloc的语言更便宜;至少在没有初始化的时候。

In short - creating objects in Java is cheap - don't worry about it unless you create loads of them.

简而言之 - 用Java创建对象很便宜 - 除非你创建它们,否则不要担心它。

#1


19  

In addition to other excellent answers, one thing very important, and usually ignored/forgotten, or misunderstood (which explains why I detail the process below):

除了其他优秀的答案之外,还有一件非常重要的事情,通常被忽略/遗忘或误解(这解释了我为何详细介绍了以下流程):

  • In Java, methods are virtual, even when called from the constructor (which could lead to bugs)
  • 在Java中,方法是虚拟的,即使从构造函数调用(这可能导致错误)

  • In C++, virtual methods are not virtual when called from the constructor (which could lead to misunderstanding)
  • 在C ++中,从构造函数调用虚拟方法时不是虚拟的(这可能会导致误解)

What?

  • Let's imagine a Base class, with a virtual method foo().
  • 让我们设想一个基类,使用虚方法foo()。

  • Let's imagine a Derived class, inheriting from Base, who overrides the method foo()
  • 让我们设想一个继承自Base的派生类,它覆盖方法foo()

The difference between C++ and Java is:

C ++和Java之间的区别是:

  • In Java, calling foo() from the Base class constructor will call Derived.foo()
  • 在Java中,从Base类构造函数调用foo()将调用Derived.foo()

  • In C++, calling foo() from the Base class constructor will call Base.foo()
  • 在C ++中,从Base类构造函数调用foo()将调用Base.foo()

Why?

The "bugs" for each languages are different:

每种语言的“错误”都不同:

  • In Java, calling any method in the constructor could lead to subtle bugs, as the overridden virtual method could try to access a variable which was declared/initialized in the Derived class.
  • 在Java中,调用构造函数中的任何方法都可能导致细微的错误,因为重写的虚方法可能会尝试访问在Derived类中声明/初始化的变量。

Conceptually, the constructor’s job is to bring the object into existence (which is hardly an ordinary feat). Inside any constructor, the entire object might be only partially formed – you can know only that the base-class objects have been initialized, but you cannot know which classes are inherited from you. A dynamically-bound method call, however, reaches “forward” or “outward” into the inheritance hierarchy. It calls a method in a derived class. If you do this inside a constructor, you call a method that might manipulate members that haven’t been initialized yet – a sure recipe for disaster.

从概念上讲,构造函数的工作是使对象存在(这不是一个普通的壮举)。在任何构造函数中,整个对象可能只是部分形成 - 您只能知道基类对象已经初始化,但您无法知道哪些类是从您继承的。但是,动态绑定的方法调用会“转发”或“向外”进入继承层次结构。它在派生类中调用方法。如果你在构造函数中执行此操作,则调用一个可能操作尚未初始化的成员的方法 - 这是一个确定的灾难方法。

Bruce Eckel, http://www.codeguru.com/java/tij/tij0082.shtml

Bruce Eckel,http://www.codeguru.com/java/tij/tij0082.shtml

  • In C++, one must remember a virtual won't work as expected, as only the method of the current constructed class will be called. The reason is to avoid accessing data members or even methods that do not exist yet.
  • 在C ++中,必须记住虚拟将无法按预期工作,因为只会调用当前构造类的方法。原因是避免访问数据成员甚至是尚不存在的方法。

During base class construction, virtual functions never go down into derived classes. Instead, the object behaves as if it were of the base type. Informally speaking, during base class construction, virtual functions aren't.

在基类构造期间,虚函数永远不会进入派生类。相反,该对象的行为就像它是基类型一样。非正式地说,在基类构造期间,虚函数不是。

Scott Meyers, http://www.artima.com/cppsource/nevercall.html

Scott Meyers,http://www.artima.com/cppsource/nevercall.html

#2


22  

What is the main difference in object creation between Java and C++?

Java和C ++之间的对象创建的主要区别是什么?

Unlike Java, in C++ objects can also be created on the stack.

与Java不同,C ++对象也可以在堆栈上创建。

For example in C++ you can write

例如,在C ++中,您可以编写

Class obj; //object created on the stack

In Java you can write

在Java中你可以写

Class obj; //obj is just a reference(not an object)
obj = new Class();// obj refers to the object

#3


8  

Besides heap/stack issues I'd say: C++ constructors have initialization lists while Java uses assignment. See http://www.parashift.com/c++-faq-lite/ctors.html#faq-10.6 for details.

除了堆/堆栈问题,我会说:C ++构造函数具有初始化列表,而Java使用赋值。有关详细信息,请参阅http://www.parashift.com/c++-faq-lite/ctors.html#faq-10.6。

#4


4  

I would answer: C++ allows creating an object everywhere: on the heap, stack, member. Java forces you allocate objects on the heap, always.

我会回答:C ++允许在任何地方创建一个对象:堆,堆栈,成员。 Java强制您始终在堆上分配对象。

#5


2  

In Java, the Java Virtual Machine (JVM) that executes Java code has to might1 log all objects being created (or references to them to be exact) so that the memory allocated for them can later be freed automatically by garbage collection when objects are not referenced any more.

在Java中,执行Java代码的Java虚拟机(JVM)必须记录所有正在创建的对象(或者对它们的引用是准确的),以便以后可以通过垃圾回收自动释放为它们分配的内存。再引用。

EDIT: I'm not sure whether this can be attributed to object creation in the strict sense but it surely happens somewhen between creation and assignment to a variable, even without an explicit assignment (when you create an object without assigning it, the JVM has to auto-release it some time after that as there are no more references).

编辑:我不确定这是否可以归因于严格意义上的对象创建,但它确实在创建和赋值给变量之间发生,即使没有显式赋值(当你创建一个没有赋值的对象时,JVM有在那之后的一段时间自动释放它,因为没有更多的引用)。

In C++, only objects created on the stack are released automatically (when they get out of scope) unless you use some mechanism that handles this for you.

在C ++中,只有在堆栈上创建的对象才会自动释放(当它们超出范围时),除非您使用某种机制来为您处理此问题。

1: Depending on the JVM's implementation.

1:取决于JVM的实现。

#6


1  

There is one main design difference between constructors in C++ and Java. Other differences follow from this design decision.

C ++和Java中的构造函数之间存在一个主要的设计差异。其他差异来自此设计决策。

The main difference is that the JVM first initializes all members to zero, before starting to execute any constructor. In C++, member initialization is part of the constructor.

主要区别在于JVM在开始执行任何构造函数之前首先将所有成员初始化为零。在C ++中,成员初始化是构造函数的一部分。

The result is that during execution of a base class constructor, in C++ the members of the derived class haven't been initialized yet! In Java, they have been zero-initialized.

结果是在执行基类构造函数期间,在C ++中派生类的成员尚未初始化!在Java中,它们已被零初始化。

Hence the rule, which is explained in paercebal's answer, that virtual calls called from a constructor cannot descend into a derived class. Otherwise uninitialized members could be accessed.

因此,在paercebal的答案中解释的规则是,从构造函数调用的虚拟调用不能下降到派生类中。否则可以访问未初始化的成员。

#7


-1  

Assuming that c++ uses alloc() when the new call is made, then that might be what they are looking for. (I do not know C++, so here I can be very wrong)

假设c ++在进行新调用时使用alloc(),那么这可能就是他们正在寻找的东西。 (我不懂C ++,所以在这里我可能会非常错误)

Java's memory model allocates a chunk of memory when it needs it, and for each new it uses of this pre-allocated area. This means that a new in java is just setting a pointer to a memory segment and moving the free pointer while a new in C++ (granted it uses malloc in the background) will result in a system call.

Java的内存模型在需要时分配一块内存,并且对于每个新内存使用此预分配区域。这意味着java中的一个新东西只是设置一个指向内存段的指针并移动*指针,而C ++中的新函数(授予它在后台使用malloc)将导致系统调用。

This makes objects cheaper to create in Java than languages using malloc; at least when there is no initialization ocuring.

这使得用Java创建的对象比使用malloc的语言更便宜;至少在没有初始化的时候。

In short - creating objects in Java is cheap - don't worry about it unless you create loads of them.

简而言之 - 用Java创建对象很便宜 - 除非你创建它们,否则不要担心它。