Общий конструктор

Пусть у нас есть следующий класс:

public class MyClass<T>{
    public <E> MyClass(E e){ System.out.println(e.toString);}
}
public class Main{
    public static void main(String[] args){
        new MyClass(new String("string"));//will be invoked comstructor MyClass(Object)
    }
}

Как известно, когда мы создаем новый экземпляр класса, сначала вызывается метод этого класса, который вызывает конструктор. Вопросы:

  1. Верно ли, что по умолчанию тип возвращаемого значения конструктора void?
  2. Является ли стирание типа from после этого конструктора public <E> MyClass(E e){ System.out.println(e.toString);} эквивалентным public MyClass(Object o){ System.out.println(o.toString);}?

person St.Antario    schedule 06.10.2013    source источник
comment
Конструкторы никогда не могут ничего вернуть.   -  person Steven    schedule 06.10.2013
comment
@St.Antario: То, что вы определяете, не является конструктором. Это просто еще один метод.   -  person Enno Shioji    schedule 06.10.2013
comment
@ЭнноШиоджи. Как? Это универсальный конструктор.   -  person Rohit Jain    schedule 06.10.2013
comment
E здесь совершенно не нужен   -  person newacct    schedule 08.10.2013


Ответы (1)


Верно ли, что по умолчанию тип возвращаемого значения конструктора недействителен?

Вы не указываете явный возвращаемый тип конструктору. Однако конструктор внутренне преобразуется в метод non-static с именем <init>, тип возвращаемого значения которого void.

Из спецификации JVM, раздел 2.9. :

На уровне виртуальной машины Java каждый constructor, написанный на языке программирования Java (JLS §8.8), отображается как метод инициализации экземпляра со специальным именем <init>. Это имя предоставляется компилятором. Поскольку имя <init> не является допустимым идентификатором, его нельзя использовать непосредственно в программе, написанной на языке программирования Java. Методы инициализации экземпляра можно вызывать только внутри виртуальной машины Java с помощью инструкции invokespecial (§invokespecial), и их можно вызывать только для неинициализированных экземпляров класса. Метод инициализации экземпляра принимает права доступа (JLS §6.6) конструктора, из которого он был получен.

Точно так же статические инициализаторы внутренне преобразуются в метод static<clinit>, опять же с типом возвращаемого значения void.

Является ли стирание типа from после этого конструктора public <E> MyClass(E e){ System.out.println(e.toString);} эквивалентным public MyClass(Object o){ System.out.println(o.toString);}?

Да. Стирание параметра типа является его крайней левой границей. В этом случае, поскольку нет привязки к E, стирание равно Object.

Если бы вы объявили свой конструктор как:

public <E extends Integer> MyClass(E e){ System.out.println(e.toString);}

стирание этого будет:

public MyClass(Integer e){ System.out.println(e.toString);}

Поскольку крайняя левая граница E теперь равна Integer.


Ссылки:

person Rohit Jain    schedule 06.10.2013
comment
@Bohemian Пожалуйста, не стесняйтесь добавлять все, что я мог пропустить. Спасибо :) - person Rohit Jain; 06.10.2013
comment
Однако конструктор внутренне преобразуется в нестатический метод с именем ‹init›, тип возвращаемого значения которого равен void. К чему приводит это преобразование? В этом случае new MyClass(new String("string")); во время компиляции компилятор проверяет наличие конструктора и сразу после этого компилятор скрывает конструктор до <init>. Это правда? - person St.Antario; 06.10.2013
comment
@Святой Антарио. Когда класс компилируется, только компилятор создает метод <init> для конструктора. - person Rohit Jain; 06.10.2013
comment
(уже +1) выглядит неплохо :) как всегда энциклопедично. Хорошая работа. - person Bohemian♦; 06.10.2013