使用更改的构造函数实例化同一类的不同版本,并“摘要”修饰符
我正在编写使用外部库的Java程序。我想编写我的代码,以便它与两个特定库的两个不同版本兼容。
问题是,他们更改了一个类(在我的示例中称为configuration
),添加了一个抽象方法,并将构造函数从无符合参数化构造函数更改为参数化构造函数。我无法影响外部图书馆,我必须与我所拥有的东西一起工作。
旧类示例
public class Configuration {
public Configuration() {
//Some code...
}
public static void main(String[] args) {
Configuration conf = new Configuration();
//Some code...
}
}
新类示例
public abstract class Configuration {
public Configuration(boolean isCool, Map<String, String> entries, Object otherThing) {
//Some code...
}
public abstract int doSomething();
public static void main(String[] args) {
Configuration conf = new MyConfiguration(false, null, new Object());
//Some code...
}
}
我的实现
public class MyConfiguration extends Configuration {
public MyConfiguration(boolean isCool, Map<String, String> entries, Object otherThing) {
super(isCool, entries, otherThing);
}
public MyConfiguration() {
//needs super constructor call!?
}
public int doSomething() {
//Some code...
return -1;
}
public static void main(String[] args) {
int version = 0;
Configuration conf = version > 2 ? new MyConfiguration(false, null, new Object()) : new MyConfiguration();
//Some code...
}
}
但是,旧类没有参数化的构造函数,因此,如果这样做,我会遇到错误。
- 有什么技巧我不必为超级构造函数打电话吗?
- 也许有一种方法可以使用反思来完成我想要的事情?
I am writing a Java program which uses external libraries. I want to write my code so it is compatible with two different versions of one specific library.
The problem is, they changed a class (called Configuration
in my example) to abstract, added an abstract method and changed the constructor from a no-argument to parameterized constructor. I am not able to influence the external library and I have to work with what I got.
Old class example
public class Configuration {
public Configuration() {
//Some code...
}
public static void main(String[] args) {
Configuration conf = new Configuration();
//Some code...
}
}
New class example
public abstract class Configuration {
public Configuration(boolean isCool, Map<String, String> entries, Object otherThing) {
//Some code...
}
public abstract int doSomething();
public static void main(String[] args) {
Configuration conf = new MyConfiguration(false, null, new Object());
//Some code...
}
}
My implementation
public class MyConfiguration extends Configuration {
public MyConfiguration(boolean isCool, Map<String, String> entries, Object otherThing) {
super(isCool, entries, otherThing);
}
public MyConfiguration() {
//needs super constructor call!?
}
public int doSomething() {
//Some code...
return -1;
}
public static void main(String[] args) {
int version = 0;
Configuration conf = version > 2 ? new MyConfiguration(false, null, new Object()) : new MyConfiguration();
//Some code...
}
}
The no-argument constructor of my custom class MyConfiguration
needs to call the constructor of the superclass in order to be compiled. However, the old class does not have a parameterized constructor, so I will run into an error if I do that.
- Are there any tricks how I don't have to call the super constructor?
- Maybe there is a way using reflection to do what I want?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
您的示例有些奇怪,因为新类示例包含对您的
myConfiguration
的引用。通常,最好维护两个版本的
myConfiguration
类或放弃对该库的旧版本的支持。或者,考虑不要使用进行如此急剧更改的库。为了完整,有一个骇客解决您的字面问题。假设类
configuration
不可序列化如图所示,或者至少是旧版本,则可以使用特定的序列化行为。当可序列化类扩展了非序列化类时,其实例化的实例将导致超级类默认构造函数的调用。因此,使用它的代码看起来像:
可以针对新版本编译此类。
create()
方法首先检查是否存在默认构造函数。当缺失时,即使用新版本运行,将调用新构造函数。否则,它可以将一个实例与没有数据流的流进行审理,因此在调用超类默认构造函数之后,readObject
可能会执行实际设置。这一切都需要一个不在乎不兼容的构造函数的懒惰验证者,只要没有人试图实际调用构造函数。正如一开始所说的,您最好使用其他解决方案。
Your example is a bit odd, as the new class example contains a reference to your
MyConfiguration
.Generally, you’re better off maintaining two versions of your
MyConfiguration
class or dropping support for the old version of that library. Or, consider not to use a library that makes such drastic changes.For completeness, there is a hack addressing your literal question. Assuming that the class
Configuration
is not serializable as shown or at least, the old version isn’t, you can utilize a specific Serialization behavior. When a serializable class extends a non-serializable class, deserializing an instance of it will cause the invocation of the superclass’s default constructor.So, the code utilizing it could look like:
This class can be compiled against the new version. The
create()
method first checks for the presence of the default constructor. When absent, i.e. running with the new version, the new constructor is called. Otherwise, it deserializes an instance with a stream having no data, so after the superclass’s default constructor has been called, thereadObject
may perform the actual setup.This all requires a lazy verifier that doesn’t care for the incompatible constructors, as long as no-one tries to actually invoke the constructor. As said at the beginning, you’re likely better off with other solutions.