Any way to _not_ call superclass constructor in Ja

2019-02-05 16:50发布

If I have a class:

class A {
   public A() { }
}

and another

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

is there any way to get B.B() not to call A.A()?

13条回答
Ridiculous、
2楼-- · 2019-02-05 17:10

There is absolutely no way to do this in Java; it would break the language specification.

JLS 12 Execution / 12.5 Creation of New Class Instances

Just before a reference to the newly created object is returned as the result, the indicated constructor is processed to initialize the new object using the following procedure:

  1. Assign the arguments for the constructor [...]
  2. If this constructor begins with an explicit constructor invocation of another constructor in the same class (using this), then [...]
  3. This constructor does not begin with an explicit constructor invocation of another constructor in the same class (using this). If this constructor is for a class other than Object, then this constructor will begin with an explicit or implicit invocation of a superclass constructor (using super).
  4. Execute the instance initializers and instance variable initializers for this class [...]
  5. Execute the rest of the body of this constructor [...]
查看更多
唯我独甜
3楼-- · 2019-02-05 17:11

The closest you can achieve to the desired behaviour is to delegate initialisation normally performed in the constructor to a template method, which you then override in your subclass implementation. For example:

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();
  }
}

However, as other people have noted this can typically indicate a problem with your design and I typically prefer the composition approach in this scenario; for example in the above code you could define the constructor to accept a Writer implementation as a parameter.

查看更多
太酷不给撩
4楼-- · 2019-02-05 17:16

I think the only way to do it is messing up with the byte-code.
I'm not sure if the Classloader or the JVM checks if super() is being called, but, as Bozho wrote, you probably would end with inconsistent objects when doing so.

查看更多
做自己的国王
5楼-- · 2019-02-05 17:19

No and if you could, your derived object wouldn't really be the object it's deriving from now would it? The is-a principle would be violated. So if you really need it, then polymorphism isn't what you're after.

查看更多
Animai°情兽
6楼-- · 2019-02-05 17:21

I had a similar requirement where I needed my child class NOT to go through the super class' constructor, and I wanted the rest of the benefits of the super class. Since super class is also mine, here's what I did.

class SuperClass {
    protected SuperClass() {
        init();
    }

    // Added for classes (like ChildClassNew) who do not want the init to be invoked.
    protected SuperClass(boolean doInit) {
        if (doInit)
            init();
    }

    //
}

class ChildClass1 extends SuperClass {
    ChildClass1() {
        // This calls default constructor of super class even without calling super() explicitly.
        // ...
    }
    // ....
}

class ChildClass2 extends SuperClass {
    ChildClass2() {
        // This calls default constructor of super class even without calling super() explicitly.
        // ...
    }
    // ....
}

class ChildClassNew extends SuperClass {
    ChildClassNew() {
        /*
         * This is where I didn't want the super class' constructor to 
         * be invoked, because I didn't want the SuperClass' init() to be invoked.
         * So I added overloaded the SuperClass' constructor where it diesn;t call init().
         * And call the overloaded SuperClass' constructor from this new ChildClassNew.
         */
        super(false);
        // 
        // ...
    }
    // ....
}
查看更多
smile是对你的礼貌
7楼-- · 2019-02-05 17:24

If you don't want to call the superclass constructor, there is something else wrong with your object model.

查看更多
登录 后发表回答