有什么方法可以_不_调用Java中的超类构造函数吗?
如果我有一个类:
class A {
public A() { }
}
还有另一个类,
class B extends A {
public B() { }
}
有什么方法可以让 BB()
不 调用 AA()
吗?
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()
?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(12)
在Java中绝对没有办法做到这一点;它会破坏语言规范。
JLS 12 执行/12.5 创建新类实例
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
您可以实现的最接近所需行为的方法是将通常在构造函数中执行的初始化委托给模板方法,然后您可以在子类实现中重写该方法。例如:
但是,正如其他人指出的那样,这通常表明您的设计存在问题,并且在这种情况下我通常更喜欢组合方法;例如,在上面的代码中,您可以定义构造函数来接受 Writer 实现作为参数。
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:
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.Java 反序列化不会调用构造函数,但它似乎基于一些内部 JVM 技巧。
但是,有一个框架允许您以可移植的方式执行此操作:Objenesis (http ://www.theserverside.com/discussions/thread/44297.html)
我最近在 Spring 中看到了这一点,当使用 CGLIB 代理时,Spring 创建两个类实例,但构造函数仅被调用一次: < a href="https://stackoverflow.com/a/11583641/2557118">https://stackoverflow.com/a/11583641/2557118
Spring 4 中添加了此行为:
Java deserialisation doesn't call the constructor, but it seems that it is based on some internal JVM tricks.
However, there is a framework that allows you to do that in a portable manner: 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
This behavior is added in Spring 4:
您可以调用您选择的超类构造函数。这可以通过显式调用超类构造函数来实现:
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 :
不,如果可以的话,您的派生对象就不会真正是它现在派生的对象,不是吗? is-a 原则将被违反。因此,如果您确实需要它,那么多态性就不是您所追求的。
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.
每个超类都需要被构造,除了调用构造函数之外没有其他方法。
Every superclass needs to be constructed and there is no other way then calling a constructor.
我认为唯一的方法就是弄乱字节码。
我不确定类加载器或 JVM 是否检查
super()
是否被调用,但是,正如 Bozho 所写,这样做时您可能会得到不一致的对象。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.不——你做不到,为什么你还要这么做呢?这会弄乱你的对象模型。
无论如何 - 我相信如果你仍然想这样做,那么你将不得不操作生成的字节代码......有几个可用的库可以轻松地检测字节代码。
强烈建议不要这样做...
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...
java中的每个对象都是Object(带有大写“O”的对象)的子类。当您创建子类的对象时,将调用超类构造函数。即使您的类没有继承任何其他类,它也隐式继承了 Object,因此必须调用 Object 构造函数。因此为此目的调用 super() 。
Every object in java is a subclass of Object (object with a capital '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. So super() is invoked for this purpose.
假设你的意思是
那么肯定你可以
不是很有用。类
A
的接口 [不是 Java 关键字] 表示您需要运行其构造函数才能构造它,这并非没有道理。例外情况是,在不调用可序列化类的构造函数的情况下构造可序列化类。Assuming you mean
then sure you can
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. The exception is that serialisable classes are constructed without calling the constructors of the serialisable classes.正如另一位发帖者所指出的,B 不会扩展 A,因此它无论如何也不会调用 A 的构造函数。
正如
在 Java 中没有办法做到这一点。
您可能可以等效地完成您想要执行的操作,如下所示:
a) 在层次结构的每个类中,包含一个具有唯一签名的构造函数,该构造函数使用其参数调用超类的构造函数。例如,声明一个类“Noop”和一个将其作为参数的构造函数:
如果运行此命令,您将得到输出
因此,实际上您已经创建了一个 class3 构造函数,该构造函数仅调用不执行任何操作的构造函数。
As pointed out by another poster, B doesn't extend A, so it won't call A's constructor anyways.
There is no way to do this in Java.
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. For example, declare a class "Noop" and a constructor that takes that as an argument:
If you run this you will get the output
So, effectively you have created a class3 constructor that only calls constructors that don't do anything.
我有一个类似的要求,我需要我的子类不通过超类的构造函数,并且我想要超类的其余好处。由于超级类也是我的,这就是我所做的。
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.