我没有这个短语,所以我去举一个例子
class AbstractUser<A extends AbstractAccount<? extends AbstractType>> {
// I want a method that has access to Type
// And returns the specific Type that extends AbstractType
protected <T extends AbstractType> T doSomething(T type) {
// do stuff
// and return the type specific type T
}
}
class AbstractAccount<T extends AbstractType> {
}
class AbstractType {
}
class Type extends AbstractType {
}
class Account extends AbstractAccount<Type> {
}
class AccountAdmin extends AbstractAccount<Type> {
}
class User extends AbstractUser<Account> {
}
我想要的是在User
类中我可以做getType()
,它返回特定类型的AbstractAccount
,在这种情况下为Account
。
如何在不指定其他模板的情况下执行此操作?换句话说,我希望该方法中?
中? extends AbstractType
的任何类型
所以我愿意
final Account account = ...
final AccountAdmin admin = ...
final User user = ...
user.doSomething(account); // should work
user.doSomething(AccountAdmin); // should fail
答案 0 :(得分:4)
您显然无法在AbstractUser
中创建这样的方法:
public Class<A> getType() { return A.class; }
这是因为类型擦除。运行时不知道A
是什么。
一种解决方法是使此方法抽象化:
public abstract Class<A> getType();
现在,您可以在子类中实现此方法:
class User extends AbstractUser<Account> {
public Class<Account> getType() { return Account.class; }
}
编辑:
现在,我意识到您想要扩展AbstractType
的类型,解决方法仍然可以使用。您只需要在getType
中创建另一个AbstractAccount
,并使Account
实现该方法。
答案 1 :(得分:1)
为此,您实际上无法绕开AbstractUser
中的另一个类型参数:
class AbstractUser<T extends AbstractType, A extends AbstractAccount<T>> {
protected abstract T getType();
}
您需要一种方法来引用A的type参数的类型,这可以达到目的。
答案 2 :(得分:0)
从Java 8开始,您可以定义一个构造函数,该构造函数使用Supplier
返回适当类型的实例。
您说:
我想要的是在User类中可以执行getType()并返回特定类型的AbstractAccount,在这种情况下为Account。
您要:doSomething(T type)
。
因此,我假设您不希望使用Class<T>
的实例,而需要T
的实例。根据您的示例,此T
应该为Account
。
据此:
class AbstractUser<T extends AbstractType, A extends AbstractAccount<T>> {
private Supplier<T> accountSupplier;
public AbstractUser(Supplier<T> accountSupplier) {
this.accountSupplier = accountSupplier;
}
protected T getType() {
return accountSupplier.get();
}
}
然后类User
如下所示:
class User extends AbstractUser<Type, Account> {
public User() {
super(Account::new);
}
}
请注意,类AbstractUser
仍未声明为abstract
。如果拥有此类的唯一原因是通过子类提供不同类型的AbstractAccount
,那么现在我们可以在没有子类的情况下做到这一点。
User user = new User();
可以重写为AbstractUser user = new AbstractUser(Type::new);
(在这种情况下,AbstractUser
不是最好的名字)。