简体   繁体   English

在Java中_not_调用超类构造函数的任何方法?

[英]Any way to _not_ call superclass constructor in Java?

If I have a class: 如果我有课:

class A {
   public A() { }
}

and another 和另一个

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

is there any way to get BB() not to call AA() ? 有没有办法让BB() 不要AA()

There is absolutely no way to do this in Java; 在Java中绝对没有办法做到这一点; it would break the language specification. 它会破坏语言规范。

JLS 12 Execution / 12.5 Creation of New Class Instances JLS 12执行/ 12.5创建新类实例

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 [...] 如果这个构造函数以同一个类中的另一个构造函数的显式构造函数调用开始(使用this ),那么[...]
  3. This constructor does not begin with an explicit constructor invocation of another constructor in the same class (using this ). 此构造函数不以同一个类中的另一个构造函数的显式构造函数调用开头(使用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 ). 如果此构造函数用于 Object 以外的类则此构造函数将以超类构造函数的显式或隐式调用开始 (使用super )。
  4. Execute the instance initializers and instance variable initializers for this class [...] 为此类执行实例初始值设定项和实例变量初始值设定项[...]
  5. Execute the rest of the body of this constructor [...] 执行此构造函数的其余部分[...]

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. 例如,在上面的代码中,您可以定义构造函数以接受Writer实现作为参数。

如果您不想调用超类构造函数, 则对象模型还有其他问题。

The possibility is that you can call the super class constructor of your choice. 可能的是你可以调用你选择的超类构造函数。 That is possible by calling the super class constructor explicitly as : 这可以通过显式调用超类构造函数来实现:

super(para_1, para_2,........);

class BaseA {
    BaseA(){
        System.out.println("This is BaseA");
    }
    BaseA(int a){
        System.out.println("This is BaseA a");
    }


}

class A extends BaseA {

    A(){
        super(5);
        System.out.println("This is A");
    }

    public static void main(String[] args) {
        A obj=new A();

    }
}


Output will be:
This is BaseA a
This is A

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);
        // 
        // ...
    }
    // ....
}

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. is-a原则将被违反。 So if you really need it, then polymorphism isn't what you're after. 所以如果你真的需要它,那么多态性就不是你想要的了。

需要构造每个超类,然后调用构造函数没有其他方法。

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. 我不确定Classloader或JVM是否检查是否正在调用super() ,但是,正如Bozho写的那样,在这样做时你可能会以不一致的对象结束。

Nope - you cannot do it and why would you want to do it anyway? 不 - 你不能这样做,为什么你还想要呢? That would mess up your object model. 这会弄乱你的对象模型。

Anyways - i believe if you still want to do it and then you would have to manipulate the generated byte code.... there are a couple of libraries available that make it easy to instrument the byte code. 无论如何 - 我相信如果你仍然想要这样做,那么你将不得不操纵生成的字节代码....有几个库可用,可以很容易地检测字节代码。

Strongly suggest against doing it... 强烈建议不要这样做......

Every object in java is a subclass of Object (object with a capital 'O'). java中的每个对象都是Object的子类(具有大写“O”的对象)。 when you create an object of a subclass the super class constructor is invoked. 当您创建子类的对象时,将调用超类构造函数。 Even if your class is not inhereting anyother class, implicitly it is inheriting Object, so the Object constructor has to be called. 即使你的类不是其他任何类,隐式地它继承了Object,因此必须调用Object构造函数。 So super() is invoked for this purpose. 因此,为此目的调用了super()。

Assuming you mean 假设你的意思

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

then sure you can 那你肯定可以

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

Not very useful. 不是很有用。 The interface [not Java keyword] to class A says that you need to run its constructor in order to construct it, not unreasonably. A的接口[不是Java关键字]表示你需要运行它的构造函数来构造它,而不是不合理地。 The exception is that serialisable classes are constructed without calling the constructors of the serialisable classes. 例外情况是构造可序列化类而不调用可序列化类的构造函数。

  1. As pointed out by another poster, B doesn't extend A, so it won't call A's constructor anyways. 正如另一张海报所指出的那样,B不会扩展A,因此无论如何它都不会调用A的构造函数。

  2. There is no way to do this in Java. 在Java中无法做到这一点。

  3. You can probably accomplish equivalently what you want to do as follows: 您可以完全按照以下方式完成您想要执行的操作:

a) in each class of your hierarchy, include a constructor with a unique signature that calls the superclass's constructor with its arguments. a)在层次结构的每个类中,包含一个带有唯一签名的构造函数,该签名使用其参数调用超类的构造函数。 For example, declare a class "Noop" and a constructor that takes that as an argument: 例如,声明一个类“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");
    }
}

If you run this you will get the output 如果你运行它,你将获得输出

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

So, effectively you have created a class3 constructor that only calls constructors that don't do anything. 因此,实际上您已经创建了一个class3构造函数,它只调用不执行任何操作的构造函数。

Java deserialisation doesn't call the constructor, but it seems that it is based on some internal JVM tricks. Java反序列化不会调用构造函数,但似乎它基于一些内部JVM技巧。

However, there is a framework that allows you to do that in a portable manner: Objenesis ( http://www.theserverside.com/discussions/thread/44297.html ) 但是,有一个框架允许您以可移植的方式执行此操作:Objenesis( http://www.theserverside.com/discussions/thread/44297.html

I've seen this recently in Spring, when using CGLIB proxies, Spring creates two class instances, but the constructor is called only once: https://stackoverflow.com/a/11583641/2557118 我最近在Spring中看到过这种情况,当使用CGLIB代理时,Spring会创建两个类实例,但构造函数只调用一次: https//stackoverflow.com/a/11583641/2557118

This behavior is added in Spring 4: 在Spring 4中添加了此行为:

CGLIB-based proxy classes no longer require a default constructor. 基于CGLIB的代理类不再需要默认构造函数。 Support is provided via the objenesis library which is repackaged inline and distributed as part of the Spring Framework. 通过objenesis库提供支持,该库在线重新打包并作为Spring Framework的一部分进行分发。 With this strategy, no constructor at all is being invoked for proxy instances anymore. 使用此策略,根本不再为代理实例调用构造函数。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 在 Java 中,有没有办法在同一个构造函数中调用 this() 和 super()? - In Java, is there any way to call this() and super() in same constructor? Java 等效于 Kotlin class 与超类构造函数调用 - Java equivalent of Kotlin class with superclass constructor call 在调用超类的构造函数之前,有没有办法在Java中初始化子类的成员变量? - Is there any way to initialize member variables of a subclass in Java before the superclass' constructor is called? ObjectInputStream-读取对象-有没有办法防止对无arg超类构造函数的调用? - ObjectInputStream - reading an object - Is there a way to prevent a call to a no arg superclass constructor? 超类中没有可用的构造函数(Java) - There is no available constructor in the superclass (Java) 在Java中,您可以通过父类的子类的构造函数调用父类的超类构造函数吗? - In Java, can you call a parent class's superclass constructor through the constructor of the child class of the parent class? java,在超类中使用构造函数扩展类 - java, extending class with constructor in superclass Java:超类构造函数需要准备 - Java: Superclass constructor needs preparation 子类Java的超类构造器行为 - SuperClass Constructor Behavior for SubClass Java 在Java中调用超类的重载构造函数 - Calling an overloaded constructor of superclass in Java
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM