сколько объектов создано в следующем коде? - PullRequest
2 голосов
/ 10 ноября 2009
class ClassA {
    void h() { }
}

class ClassB extends ClassA{

    public static void main(String[] args){
       ClassA a = new ClassA();
       ClassB b = new ClassB();
  }
}

Да, все думают, что это так просто, и обязательно должны быть созданы только два объекта.

Но после того, как я прочитал «Думай на Java, 2-е издание», я думаю, что здесь может быть что-то более интересное.

В «Think in Java» есть предложение: «Когда вы создаете объект производного класса, он содержит в себе подобъект базового класса. Этот подобъект такой же, как если бы вы создали объект базовый класс сам по себе. "

Это на странице 278 для 2-го издания. Вы также можете увидеть это по этой ссылке "http://www.codeguru.com/java/tij/tij0065.shtml" (раздел с большим названием" Инициализация базового класса ")

Ответы [ 7 ]

13 голосов
/ 10 ноября 2009

Должно быть 2. Функция main является статической, поэтому ей не нужен объект.

ClassA a является объектом, а ClassB b является объектом

РЕДАКТИРОВАТЬ : ClassB не состоит из двух объектов, потому что extends - это отношение is-a, а не has-a. (та мик)

EDIT : Существует также объект String[], который создается системой времени выполнения, и, возможно, любое количество строковых объектов помещается в этот массив. Я намеренно игнорирую их, но признаю их возможное существование. (та diveshpremdeep и Адам Гуд)

ЗАКЛЮЧИТЕЛЬНОЕ РЕДАКТИРОВАНИЕ : Чтобы определить, сколько объектов создано (программой, а не системой времени выполнения), вы можете использовать программу javap в командной строке следующим образом (если test.java содержит твой пример)

$ javac test.java
$ javap -c ClassB

выход:

Compiled from "test.java"
class ClassB extends ClassA{
ClassB();
  Code:
   0:   aload_0
   1:   invokespecial   #1; //Method ClassA."<init>":()V
   4:   return

public static void main(java.lang.String[]);
  Code:
   0:   new #2; //class ClassA
   3:   dup
   4:   invokespecial   #1; //Method ClassA."<init>":()V
   7:   astore_1
   8:   new #3; //class ClassB
   11:  dup
   12:  invokespecial   #4; //Method "<init>":()V
   15:  astore_2
   16:  return

}

Как вы можете видеть, есть только два бита байт-кода, которые new (что создает объекты, которые я предполагаю). Один для класса ClassA, а другой для класса ClassB. Вы можете заметить, что команда invokespecial вызывается впоследствии для вызова конструктора, а также как вызывается конструктор класса ClassA из конструктора класса ClassB, но внутри конструктора не создается новый объект (это пустой конструктор по умолчанию).

вызов javap -c ClassA показывает столь же скучный конструктор, который вызывает конструктор для Object.

В итоге: байт-код new создает объекты в куче, а не invokespecial, который просто заполняет детали памяти, выделенной байт-кодом new.

3 голосов
/ 10 ноября 2009

Если вы имеете в виду объекты внутри блока метода main, то 2. Это можно проверить, например, с помощью дампа кучи Java и следующего расширения кода:

class ClassA {
    void h() { }
}

class ClassB extends ClassA{
    public static void main(String[] args) throws Exception {
        System.in.read();
        main1(args);
        System.in.read();
    }

    public static void main1(String[] args){
       ClassA a = new ClassA();
       ClassB b = new ClassB();
  }
}

Итак:

  1. Скомпилируйте класс и запустите его. Выполнение программы останавливается на System.in.read ().
  2. Узнайте идентификатор процесса.
  3. Выполнить jmap -dump:format=b,file=snapshot1.jmap PROCESS_ID
  4. Нажмите любую клавишу в консоли, чтобы продолжить выполнение.
  5. Выполнить jmap -dump:format=b,file=snapshot2.jmap PROCESS_ID
  6. Нажмите любую клавишу еще раз, чтобы завершить программу.

После этого вы получите два снимка дампа кучи Java, которые вы можете сравнить.

Я получил следующие значения (с Java 1.6.0_15, OSX):

  • snapshot1.jmap: 17584 объекта
  • snapshot1.jmap: 17586 объектов

Разница составляет 2, что также является количеством созданных объектов.

3 голосов
/ 10 ноября 2009

3 конструктора, вызываемых для создания 2 объектов.

2 голосов
/ 10 ноября 2009

Создаются два объекта - экземпляр ClassA и экземпляр ClassB.

Вызов нового ClassB () не вызывает метод main (). Конструктор по умолчанию, который имеет вид

public ClassB() {}

будет использоваться. То же самое относится и к ClassA.

1 голос
/ 10 ноября 2009

Только

2

Хотя B расширяет A, когда он создается, конструктор в A выполняется, но в конце создается только один объект из B.

1 A + 1 B = 2 объекта

Что касается:

"Когда вы создаете объект производного класса, он содержит в себе подобъект базового класса. Этот подобъект такой же, как если бы вы создали объект базового класса самостоятельно."

Это означает, что возможно следующее:

 ClassA a = new ClassA();
 a = new ClassB();

То есть вы можете назначить экземпляр B ссылке типа A, потому что:

"... Этот подобъект такой же, как если бы вы создали объект базового класса самостоятельно"

Вот что такое "is-a" . Вы можете сказать, что «каждый B - это A», и это правда.

То, что вы не можете сделать, - это вызвать метод, определенный в B, который не определен в A

Надеюсь, это поможет.

0 голосов
/ 10 ноября 2009

Похоже, это один из тех вопросов, которые задает ваш профессор, чтобы заставить вас мыслить абстрактно.

При этом я готов поставить 4 создаваемых объекта:

1) Class A

2) Class B

3) String[]

4) Since there is no such thing as a string array it is a char array.

Конечно, это чисто теоретическая идея

0 голосов
/ 10 ноября 2009

Конструктор по умолчанию вызывает конструктор super () (родительский конструктор по умолчанию) автоматически. Поэтому, если вы создадите объект ClassB, будет создан и объект ClassA.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...