作者热门文章
- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我在使用 Java 中的泛型时遇到了一些麻烦。我有一个通用基类 A
它定义了一个静态工厂方法来创建 A
的实例带有初始值。我这样做是为了在创建 A
的实例时设置一些初始值而不是指定一个设置初始值的构造函数,因为它会涉及在构造函数中调用可覆盖的方法(强烈建议不要这样做)。
public class A<T> {
private List<T> values;
public A() {
this.values = new ArrayList<>();
}
public void setValues(List<T> values) {
this.values.clear();
for (T value : values) {
this.values.add(this.modify(value));
}
}
protected T modify(T value) {
// Make modifications to value before it is stored. My real implementation actually does stuff.
return value;
}
public static <T> A<T> create(List<T> values) {
A<T> a = new A<>();
a.setValues(values);
return a;
}
}
B
扩展
A
并指定要使用的泛型类型。
public class B extends A<Integer> {
public B() {
super();
}
}
create
B
中的静态方法创建
B
的实例与初始项目。尝试调用
B.create(...)
时我收到一条错误消息:
Error:(5, 23) java: incompatible types: no instance(s) of type variable(s) T,E exist so that A conforms to B
create
的实现。特定于
B
类(class):
public static B create(List<String> values) {
B b = new B();
b.setValues(values);
return b;
}
Error:(8, 21) java: name clash: create(java.util.List) in B and create(java.util.List) in A have the same erasure, yet neither hides the other
A
上定义静态工厂方法?可以与任何子类一起使用,或者如何在
A
上定义静态工厂方法以及
A
的每个适用子类上的静态工厂方法覆盖/隐藏
A
的实现?
最佳答案
这里可能没有完美的答案。有几个选项可能有意义,但细节可能取决于应用案例。我将列出一些关于 问题的选项。静态工厂方法应该在哪里,它们的名称应该是什么?
A
中的方法创建
A
的实例,并且您不能神奇地将其更改为
B
只需称其为“通过”
B
.
B.create()
仍将创建
A
, 无论你做什么。
create()
B
中的方法如您所见,将导致名称冲突。
ClassName
的类(class),有一个类叫
ClassNames
包含创建实例的方法。
class Customer { /* With package-private constructor, usually ... */ }
public final class Customers {
public static Customer create() { ... }
}
class PremiumCustomer { /* With package-private constructor, usually ... */ }
public final class PremiumCustomers {
public static PremiumCustomer create() { ... }
}
Customer
的类。 ,而不影响现有的代码库。
A
和
B
,它没有传达实际的结构。但是根据这种结构,让一个类具有不同的工厂方法(具有不同的名称)来指示特化可能更有意义:
public final class Customers {
public static Customer createStandard() { ... }
public static PremiumCustomer createPremium() { ... }
}
static
工厂方法。但是您描述的情况引发了另一个问题:
谁应该调用这些方法,如何调用?
static
方法总是失败,并可能导致头痛。您应该考虑改用(“简单”,非静态)工厂。
void example() {
Customer customer = Customer.create();
doSomeComplexStuffWith(customer);
}
Customer.create()
(或
Customers.create()
或
Customers.createDefault()
- 这无关紧要)。
Supplier
的使用。 :
void example(Supplier<? extends Customer> supplier) {
Customer customer = supplier.get();
doSomeComplexStuffWith(customer);
}
example
的执行方法不受此处类型更改的影响:
example(Customers::createStandard); // Run example with standard customers
example(Customers::createPremium); // Run example with premium customers
calling overridable methods in the constructor ... is strongly discouraged
private
或
protected
.然后,您可以建立一个合约,对创建过程有更多的控制权,并确保没有被覆盖的方法引起的不良影响。
关于java - 带有泛型的静态工厂方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51684445/
我是一名优秀的程序员,十分优秀!