通过调用隐式默认构造函数实例化给定 class 的对象
Instantiate object of given class by invoking implicit default constructor
目前,我有这样一种情况,我正在尝试实例化 class 的对象,将 class 作为参数给出,并使用默认值初始化对象的属性(例如无效的)。问题是,我的 class 没有任何构造函数,而且由于各种原因我 不能 添加一个。可能的classes也没有被superclass连接起来,它们都是Object的直接subclasses。我尝试实例化的 classes 如下所示:
public class MyClass {
public String prop1;
public int prop2;
public int prop3;
}
这意味着 classes 仅包含属性而没有方法,因此没有显式构造函数。如果我事先知道 class,我当然可以这样做:
public MyClass create() {
return new MyClass();
}
在上述情况下,编译器为我生成了 MyClass 的默认构造函数,并使用它们的默认值启动所有属性。正如评论中所指出的,这意味着我在技术上有一个构造函数,但我只能使用“new”关键字并事先知道 class 来访问它。现在,我正在尝试做的(基本上)如下:
public someClass create(Class<?> someClass) {
return new someClass();
}
当然,'new' 关键字在这种情况下不起作用,所以我尝试了很多替代方案,none 目前有效:
- 使用
someClass.getConstructor().newInstance()
或 someClass.getDeclaredConstructor().newInstance()
。代码已编译,但我得到了预期的“NoSuchMethodException”,因为它找不到 someClass 的 -method 或构造函数
- 从
Object newObject = someClass.cast(new Object())
等对象投射。正如预期的那样,这也会崩溃,因为您无法从 superclass 转换为 subclass
我现在唯一真正的选择,因为可能的 classes 的范围不是太大,是为每个 class 使用“instanceof”和然后在每个分支中使用“new”关键字。但是你可以想象,我不太喜欢那个。
那么我是在尝试做不可能的事情还是有办法做到这一点?
解决方案: 结果证明第一种方法完全有效,它只是不起作用,因为我的一些 classes 是数组,我没有意识到这一点。如果我采用数组中对象的实际 classes,它就可以工作。抱歉造成混淆,一直以来都是我的错误!
方法 Class::getConstructor
returns public 构造函数,因此它可能无法检测到非 public 无参数构造函数:
Returns a Constructor object that reflects the specified public constructor of the class represented by this Class object. The parameterTypes parameter is an array of Class objects that identify the constructor's formal parameter types, in declared order. If this Class object represents an inner class declared in a non-static context, the formal parameter types include the explicit enclosing instance as the first parameter.
The constructor to reflect is the public constructor of the class represented by this Class object whose formal parameter types match those specified by parameterTypes.
因此,应该定义和实现方法 create(Class<?> someClass)
来调用 Class::newInstance
, however, as it is deprecated since Java 9 它应该替换为 someClass.getDeclaredConstructor().newInstance()
。
此外,已检查的异常可能会被捕获并包装到 RuntimeException
public static <T> T create(Class<T> someClass) {
try {
return someClass.getDeclaredConstructor().newInstance();
} catch (InstantiationException | IllegalAccessException | NoSuchMethodException | InvocationTargetException ex) {
throw new RuntimeException("Failed to create instance of class " + someClass.getName(), ex);
}
}
测试:
MyClass mc = create(MyClass.class);
System.out.println(mc); // overridden toString
输出
MyClass :: prop1 = null; prop2 = 0; prop3 = 0
目前,我有这样一种情况,我正在尝试实例化 class 的对象,将 class 作为参数给出,并使用默认值初始化对象的属性(例如无效的)。问题是,我的 class 没有任何构造函数,而且由于各种原因我 不能 添加一个。可能的classes也没有被superclass连接起来,它们都是Object的直接subclasses。我尝试实例化的 classes 如下所示:
public class MyClass {
public String prop1;
public int prop2;
public int prop3;
}
这意味着 classes 仅包含属性而没有方法,因此没有显式构造函数。如果我事先知道 class,我当然可以这样做:
public MyClass create() {
return new MyClass();
}
在上述情况下,编译器为我生成了 MyClass 的默认构造函数,并使用它们的默认值启动所有属性。正如评论中所指出的,这意味着我在技术上有一个构造函数,但我只能使用“new”关键字并事先知道 class 来访问它。现在,我正在尝试做的(基本上)如下:
public someClass create(Class<?> someClass) {
return new someClass();
}
当然,'new' 关键字在这种情况下不起作用,所以我尝试了很多替代方案,none 目前有效:
- 使用
someClass.getConstructor().newInstance()
或someClass.getDeclaredConstructor().newInstance()
。代码已编译,但我得到了预期的“NoSuchMethodException”,因为它找不到 someClass 的 - 从
Object newObject = someClass.cast(new Object())
等对象投射。正如预期的那样,这也会崩溃,因为您无法从 superclass 转换为 subclass
我现在唯一真正的选择,因为可能的 classes 的范围不是太大,是为每个 class 使用“instanceof”和然后在每个分支中使用“new”关键字。但是你可以想象,我不太喜欢那个。
那么我是在尝试做不可能的事情还是有办法做到这一点?
解决方案: 结果证明第一种方法完全有效,它只是不起作用,因为我的一些 classes 是数组,我没有意识到这一点。如果我采用数组中对象的实际 classes,它就可以工作。抱歉造成混淆,一直以来都是我的错误!
方法 Class::getConstructor
returns public 构造函数,因此它可能无法检测到非 public 无参数构造函数:
Returns a Constructor object that reflects the specified public constructor of the class represented by this Class object. The parameterTypes parameter is an array of Class objects that identify the constructor's formal parameter types, in declared order. If this Class object represents an inner class declared in a non-static context, the formal parameter types include the explicit enclosing instance as the first parameter.
The constructor to reflect is the public constructor of the class represented by this Class object whose formal parameter types match those specified by parameterTypes.
因此,应该定义和实现方法 create(Class<?> someClass)
来调用 Class::newInstance
, however, as it is deprecated since Java 9 它应该替换为 someClass.getDeclaredConstructor().newInstance()
。
此外,已检查的异常可能会被捕获并包装到 RuntimeException
public static <T> T create(Class<T> someClass) {
try {
return someClass.getDeclaredConstructor().newInstance();
} catch (InstantiationException | IllegalAccessException | NoSuchMethodException | InvocationTargetException ex) {
throw new RuntimeException("Failed to create instance of class " + someClass.getName(), ex);
}
}
测试:
MyClass mc = create(MyClass.class);
System.out.println(mc); // overridden toString
输出
MyClass :: prop1 = null; prop2 = 0; prop3 = 0