Какой-либо путь к _not_ называет конструктора суперкласса в Java?

Если у меня есть класс:

class A {
   public A() { }
}

и другой

class B extends A {
   public B() { }
}

есть ли любой способ добраться B.B() не звонить A.A()?

24
задан polygenelubricants 6 June 2010 в 19:30
поделиться

10 ответов

  1. Как указал другой автор, B не расширяет A, поэтому он в любом случае не будет вызывать конструктор A.

  2. В Java нет возможности сделать это.

  3. Вы, вероятно, можете эквивалентно выполнить то, что хотите, следующим образом:

a) в каждый класс вашей иерархии включить конструктор с уникальной сигнатурой, который вызывает конструктор суперкласса со своими аргументами. Например, объявите класс «Noop» и конструктор, который принимает это в качестве аргумента:

public class NoOp {
}

public class class1 {
    class1() {
        System.out.println("class1() called");
    }
    class1(String x, String y) {
        System.out.println("class1(String, String) called");
}
    class1(NoOp x) {
        System.out.println("class1(NoOp) called");
    }
}

public class class2 extends class1 {
    class2() {
        System.out.println("class2() called");
    }
    class2(String x, String y) {
        System.out.println("class2(String, String) called");
}
    class2(NoOp x) {
        super(x);
        System.out.println("class2(NoOp) called");
    }
}

public class class3 extends class2 {
    class3() {
        System.out.println("class3() called");
    }
    class3(String x, String y) {
        super(new NoOp());
        System.out.println("class3(String, String) called");
    }
    class3(NoOp x) {
        super(x);
        System.out.println("class3(NoOp) called");
    }
    public static void main(String args[]) {
        class3 x = new class3("hello", "world");
    }
}

Если вы запустите это, вы получите результат

class1(NoOp) called
class2(NoOp) called
class3(String, String) called

Таким образом, вы фактически создали конструктор class3, который вызывает только конструкторы, которые не я ничего не делаю.

0
ответ дан 28 November 2019 в 22:51
поделиться

Нет, вы не можете этого сделать, и зачем вам это делать? Это испортит вашу объектную модель.

В любом случае - я считаю, что если вы все еще хотите это сделать, тогда вам придется манипулировать сгенерированным байтовым кодом ... есть несколько доступных библиотек, которые упрощают инструментирование байтового кода.

Настоятельно не рекомендую делать это ...

0
ответ дан 28 November 2019 в 22:51
поделиться

Нет, и если бы вы могли, ваш производный объект на самом деле не был бы объектом, из которого он выводится сейчас, не так ли? Принцип is-a будет нарушен. Поэтому, если вам это действительно нужно, то полиморфизм — это не то, к чему вы ищете.

0
ответ дан 28 November 2019 в 22:51
поделиться

В Java нет абсолютно никакого способа сделать это; это нарушит спецификацию языка.

Выполнение JLS 12 / 12.5 Создание экземпляров нового класса

Непосредственно перед тем, как в качестве результата будет возвращена ссылка на вновь созданный объект, указанный конструктор обрабатывается для инициализации нового объекта с использованием следующей процедуры:

  1. Назначить аргументы для конструктора [...]
  2. Если этот конструктор начинается с явного вызова конструктора другого конструктора в том же классе (используя this ), то [...]
  3. Этот конструктор не начинается с явного вызова конструктора другого конструктора в том же классе (используя this ). Если этот конструктор предназначен для класса, отличного от Object , , то этот конструктор начнется с явного или неявного вызова конструктора суперкласса (с использованием super ).
  4. Выполнить инициализаторы экземпляра и инициализаторы переменных экземпляра для этого класса [...]
  5. Выполнить остальную часть тела этого конструктора [...]
28
ответ дан 28 November 2019 в 22:51
поделиться

Каждый объект в java является подклассом Object (объект с большой буквы 'O'). когда вы создаете объект подкласса, вызывается конструктор суперкласса. Даже если ваш класс не наследует никакой другой класс, неявно он наследует Object, поэтому конструктор Object должен быть вызван. Поэтому для этой цели вызывается super().

0
ответ дан 28 November 2019 в 22:51
поделиться

Если вы имеете в виду

class B extends A {
     public B() { }
}

, то конечно можете

class B extends A {
     public B() {
         this(abort());
     }
     private B(Void dummy) {
         /* super(); */
     }
     private static Void abort() {
         throw null;
     }
}

Не очень полезно. Интерфейс [не ключевое слово Java] к классу A говорит о том, что вам нужно запустить его конструктор, чтобы построить его, и не без оснований. Исключением является то, что сериализуемые классы создаются без вызова конструкторов сериализуемых классов.

0
ответ дан 28 November 2019 в 22:51
поделиться

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

0
ответ дан 28 November 2019 в 22:51
поделиться

Самое близкое к желаемому поведению, которое вы можете достичь, - это делегирование инициализации, обычно выполняемой в конструкторе, методу шаблона, который вы затем переопределяете в реализации вашего подкласса. Например:

public class A {
  protected Writer writer;

  public A() {
    init();
  }

  protected void init() {
    writer = new FileWriter(new File("foo.txt"));
  }
}

public class B extends A {
  protected void init() {
    writer = new PaperbackWriter();
  }
}

Однако, как отмечали другие люди, это обычно может указывать на проблему с вашим дизайном, и я обычно предпочитаю подход композиции в этом сценарии; например, в приведенном выше коде вы можете определить конструктор для принятия реализации Writer в качестве параметра.

20
ответ дан 28 November 2019 в 22:51
поделиться

Если вы не хотите вызывать конструктор суперкласса, значит в вашей объектной модели что-то еще не так.

8
ответ дан 28 November 2019 в 22:51
поделиться

Я думаю, что единственный способ сделать это - испортить байт-код.
Я не уверен, проверяет ли загрузчик классов или JVM, вызывается ли super(), но, как написал Божо, вы, вероятно, получите в итоге несовместимые объекты.

0
ответ дан 28 November 2019 в 22:51
поделиться
Другие вопросы по тегам:

Похожие вопросы: