使用不同的构造函数参数实例化泛型 类
Instantiate generic classes with different constructor arguments
我有两个相似的 classes,Foo 和 Bar
public class Foo{
private String name;
public Foo(String name){
this.name = name;
}
}
public class Bar{
private String name;
public Bar(String name){
this.name = name;
}
}
我在另一个 class 中有两个方法,它们创建一组 Foo(第一种方法)和 Bar(第二种方法)并且几乎相同。
第一个:
private Set<Foo> buildFoos(final List<String> names)
{
final Set<Foo> set = new HashSet<>();
for (int i = 0; i < names.size(); i++)
{
set.add(new Foo(names.get(i)));
}
return set;
}
第二个:
private Set<Bar> buildBars(final List<String> names)
{
final Set<Bar> set = new HashSet<>();
for (int i = 0; i < names.size(); i++)
{
set.add(new Bar(names.get(i)));
}
return set;
}
如您所见,这两种方法几乎相同,所以我认为我可以使用泛型来仅使用一种方法。我的方法是这样的:
private <T> Set<T> build(final Class<T> clazz, final List<String> names)
{
final Set<T> set = new HashSet<>();
for (int i = 0; i < names.size(); i++)
{
set.add(clazz.getConstructor(String.class).newInstance(names.get(i)));
}
return set;
}
我已经测试过了,它应该可以工作,但我的问题是,如果 Foo 或 Bar 有不同的构造函数会发生什么(例如,Bar 会有另一个字符串作为第二个参数)。我所能想到的就是检查 class 的实例并选择两个构造函数之一(类似这样)
private <T> Set<T> build(final Class<T> clazz, final List<String> names)
{
final Set<T> set = new HashSet<>();
for (int i = 0; i < names.size(); i++)
{
if(clazz.isInstance(Foo.class){
set.add(clazz.getConstructor(String.class).newInstance(names.get(i)));
}
else if(clazz.isInstance(Bar.class){
set.add(clazz.getConstructor(String.class, String.class).newInstance(names.get(i), "example"));
}
}
return set;
}
有没有更好的方法来实现这个目标?
这甚至是一个好习惯吗?
任何提示总是值得赞赏的。提前致谢!
在我看来,用 Function<String, T>
代替 Class<T>
会更好。这样您就不需要反射,并且调用者可以传入构造函数、工厂方法、使用 multi-parameter 构造函数的 lambda,无论他们想要什么。所以你的方法是:
private <T> Set<T> build(final Function<String, T> factory, final List<String> names) {
final Set<T> set = new HashSet<>();
for (String name : names) {
set.add(factory.apply(name));
}
return set;
}
我怀疑这可以使用流式传输更简单地编写,但这是一个单独的问题。 (尽管为了简单起见,我确实借此机会使用了 enhanced-for 循环。)
我有两个相似的 classes,Foo 和 Bar
public class Foo{
private String name;
public Foo(String name){
this.name = name;
}
}
public class Bar{
private String name;
public Bar(String name){
this.name = name;
}
}
我在另一个 class 中有两个方法,它们创建一组 Foo(第一种方法)和 Bar(第二种方法)并且几乎相同。 第一个:
private Set<Foo> buildFoos(final List<String> names)
{
final Set<Foo> set = new HashSet<>();
for (int i = 0; i < names.size(); i++)
{
set.add(new Foo(names.get(i)));
}
return set;
}
第二个:
private Set<Bar> buildBars(final List<String> names)
{
final Set<Bar> set = new HashSet<>();
for (int i = 0; i < names.size(); i++)
{
set.add(new Bar(names.get(i)));
}
return set;
}
如您所见,这两种方法几乎相同,所以我认为我可以使用泛型来仅使用一种方法。我的方法是这样的:
private <T> Set<T> build(final Class<T> clazz, final List<String> names)
{
final Set<T> set = new HashSet<>();
for (int i = 0; i < names.size(); i++)
{
set.add(clazz.getConstructor(String.class).newInstance(names.get(i)));
}
return set;
}
我已经测试过了,它应该可以工作,但我的问题是,如果 Foo 或 Bar 有不同的构造函数会发生什么(例如,Bar 会有另一个字符串作为第二个参数)。我所能想到的就是检查 class 的实例并选择两个构造函数之一(类似这样)
private <T> Set<T> build(final Class<T> clazz, final List<String> names)
{
final Set<T> set = new HashSet<>();
for (int i = 0; i < names.size(); i++)
{
if(clazz.isInstance(Foo.class){
set.add(clazz.getConstructor(String.class).newInstance(names.get(i)));
}
else if(clazz.isInstance(Bar.class){
set.add(clazz.getConstructor(String.class, String.class).newInstance(names.get(i), "example"));
}
}
return set;
}
有没有更好的方法来实现这个目标? 这甚至是一个好习惯吗? 任何提示总是值得赞赏的。提前致谢!
在我看来,用 Function<String, T>
代替 Class<T>
会更好。这样您就不需要反射,并且调用者可以传入构造函数、工厂方法、使用 multi-parameter 构造函数的 lambda,无论他们想要什么。所以你的方法是:
private <T> Set<T> build(final Function<String, T> factory, final List<String> names) {
final Set<T> set = new HashSet<>();
for (String name : names) {
set.add(factory.apply(name));
}
return set;
}
我怀疑这可以使用流式传输更简单地编写,但这是一个单独的问题。 (尽管为了简单起见,我确实借此机会使用了 enhanced-for 循环。)