我是java的新手,我想知道如何在java中更好地做到这一点,或者更简单,更清洁,更容易,比如有多种泛型类型的东西
public class Item<T1, T2, T3, T4, T5, T6, T7, T8, T9>{
private T1 t1;
private T2 t2;
private T3 t3;
private T4 t4;
private T5 t5;
private T6 t6;
private T7 t7;
private T8 t8;
private T9 t9;
public Item(T1 t1){
this(t1, null, null, null, null, null, null, null, null);
}
public Item(T1 t1, T2 t2){
this(t1, t2, null, null, null, null, null, null, null);
}
public Item(T1 t1, T2 t2, T3 t3){
this(t1, t2, t3, null, null, null, null, null, null);
}
public Item(T1 t1, T2 t2, T3 t3, T4 t4){
this(t1, t2, t3, t4, null, null, null, null, null);
}
...
答案 0 :(得分:1)
您可能会发现一些有用的建议:
你有一个“telescoping constructor anti-pattern”的案例。 builder design pattern是通常的补救措施。如你所说,你正在寻找一个简单的解决方案,我建议使用lombok注释为你的类实现一个构建器:
@Getter
@Builder
class Item<T1, T2, T3, T4, T5, T6, T7, T8, T9> {
private T1 t1;
private T2 t2;
private T3 t3;
private T4 t4;
private T5 t5;
private T6 t6;
private T7 t7;
private T8 t8;
private T9 t9;
}
你必须像这样初始化Item
:
Item<String, Integer, Double, String, Long, Long, Long, Long, Long> item =
Item.<String, Integer, Double, String, Long, Long, Long, Long, Long>builder()
.t4("text").t2(42).t3(3.14159).build();
不幸的是,类型信息是重复的。请注意,您可以跳过字段并按任何顺序初始化。对于多个构造函数来说,这将是很多工作。其他领域,例如t1
,t5
将保留为空。
考虑从jOOL library采用Tuple9
。如果你看source code of Tuple9,它并不比你的代码简单。这种方法的简单性在于其他人已经完成了实现,而不是你。该库最多支持Tuple16
答案 1 :(得分:1)
您可以使用库,代码预处理器或构建器模式,或者如果您希望保持简单,您可以创建可链接的方法,只允许您按照您想要的顺序设置所需的属性:
public class Item<T1, T2, T3, T4, T5, T6, T7, T8, T9> {
private T1 t1;
private T2 t2;
private T3 t3;
private T4 t4;
private T5 t5;
private T6 t6;
private T7 t7;
private T8 t8;
private T9 t9;
public Item<T1, T2, T3, T4, T5, T6, T7, T8, T9> t1(T1 t1) {
this.t1 = t1;
return this;
}
public Item<T1, T2, T3, T4, T5, T6, T7, T8, T9> t2(T2 t2) {
this.t2 = t2;
return this;
}
// TODO: rest of methods
}
用法:
Item<String, Double, Integer, Long, Long, Long, Long, Long, String> item = new Item()
.t1("hello")
.t2(0.123)
.t3(123)
.t4(123L)
.t5(123_456L)
.t6(123_456_789L)
.t7(654_321L)
.t8(321L)
.t9("goodbye");
或以任何其他顺序:
Item<String, Double, Integer, Long, Long, Long, Long, Long, String> item = new Item()
.t6(123_456_789L)
.t2(0.123)
.t3(123)
.t5(123_456L)
.t7(654_321L)
.t8(321L)
.t4(123L)
.t1("hello")
.t9("goodbye");
或只是有一些属性:
Item<String, Double, Integer, Long, Long, Long, Long, Long, String> item = new Item()
.t6(123_456_789L)
.t2(0.123)
.t3(123);
答案 2 :(得分:0)
免责声明:(停止downvotes; - ))
这只是一个简单的解决方案,可以保存任意数量的不同类型的对象,这些对象可以通过实际类型以一种简单的方式检索,而不保证类型安全。请谨慎使用!
建议的解决方案:
您可以使用简单的List<Object>
。由于您不想明确您的实际要求,这可能已经足够您......以下是一个示例:
public class Item {
List<Object> items = new ArrayList<>();
public <T> Item(T... items) { // well... could also just be Object
Collections.addAll(this.items, items);
}
public <T> T get(int index) {
return (T) items.get(index); // unsafe of course... but no requirement said something about type safety ;-)
}
public static void main(String[] args) {
Item item = new Item("sum", 123L, 234L, true);
if (item.get(3)) {
long sum = item.<Long>get(1) + item.<Long>get(2);
System.out.println(item.get(0) + " is " + sum);
}
}
}
打印:
sum is 357
关于类型安全,您可以通过在检索期间提供类型来改善这一点,如果检索到的对象不是预期类型,则可能会失败:
public class Item {
List<Object> items = new ArrayList<>();
public <T> Item(T... items) {
Collections.addAll(this.items, items);
}
public <T> T get(int index, Class<T> type) {
Object item = items.get(index);
if (type.isInstance(item)) {
return type.cast(item);
}
throw new RuntimeException("failing miserably as index " + index + " isn't of type " + type);
}
public static void main(String[] args) {
Item item = new Item("sum", 123L, 234L, true);
if (item.get(3, Boolean.class)) {
long sum = item.get(1, Long.class) + item.get(2, Long.class);
System.out.println(item.get(0, String.class) + " is " + sum);
}
}
}
正如其他人所说:构建器模式也可能有所帮助,但只要添加更多类型或想要删除某些类型,就需要调整代码。如果要声明一个变量来保存item
,那么使用构建器模式仍然需要编写所有泛型类型信息。这个解决方案不是必需的。当然,这个解决方案也存在一些问题:第一个变体不是类型安全的,可能导致ClassCastException
。如果你想要检索一个没有给定类型的对象,第二个变体可能会导致RuntimeException
,但至少它是类型安全的;否则;-)所以它实际上取决于你想要完成什么。
如果您不喜欢第二个版本中的RuntimeException
,您也可以使用Optional
。我故意省略了这个变体,因为它使代码更加冗长。以下是get
- 它的实现:
public <T> Optional<T> get(int index, Class<T> type) {
Object item = items.get(index);
if (type.isInstance(item)) {
return Optional.of(type.cast(item));
}
return Optional.empty();
}
最后,我可能不会在生产中使用此代码,因为它是一种解决方法,可以节省一些代码。在生产代码中,我更喜欢类型安全而非简单。