Java 使用泛型检索泛型类型的类列表
我对Java中的泛型比较陌生,所以如果这是学校里经常教的东西,我很抱歉(我几乎是自学成才的)。假设我有下面的接口和抽象类Java 使用泛型检索泛型类型的类列表,java,generics,Java,Generics,我对Java中的泛型比较陌生,所以如果这是学校里经常教的东西,我很抱歉(我几乎是自学成才的)。假设我有下面的接口和抽象类 public interface IChallenge<T> { boolean handle(T e); Class<? extends T> getType(); } 当我试图将一个特定的类传递给handle方法时,我的问题就出现了。由于泛型可以是任何类,并且同一类型可以有多个质询,因此我将质询存储在一个映射中,其类型作为键 pr
public interface IChallenge<T> {
boolean handle(T e);
Class<? extends T> getType();
}
当我试图将一个特定的类传递给handle
方法时,我的问题就出现了。由于泛型可以是任何类,并且同一类型可以有多个质询,因此我将质询存储在一个映射中,其类型作为键
private Map challenge.handle(A));
但我很难弄清楚“某物”里有什么。如果我使用通配符?
符号,那么IntelliJ表示句柄
必须包含一个需求参数:捕获?当我通过A级考试时,我最好不要指定AbstractChallenge
的类型,但我想要一个更好的解决方案
有什么想法吗?谢谢 你想要的是这样的(我在这里接受了评论): 以下是一个例子:
Integer a = Integer.valueOf(5);
// #1 -> ok: a is a Number
challenges.get(a.getClass()).removeIf(c -> c.handle(a));
// #2 -> ok: a is an Integer
challenges.get(a.getClass()).removeIf(c -> c.handle(a));
// #3 -> ok: a is an Object
challenges.get(a.getClass()).removeIf(c -> c.handle(a));
// #4 ->ko: a is not a String
challenges.get(a.getClass()).removeIf(c -> c.handle(a));
如果您希望避免这种情况,但仍然能够处理任何挑战,您应该确保持有/构建挑战的类正确地执行此操作:
public <T> void addChallenge(Class<T> type, IChallenge<T> challenge) {
challenges.computeIfAbsent(type, ignored -> new ArrayList<>()).add(challenge);
}
由于除了ChallengeHolder
类提供的功能外,公众无法访问挑战,因此使用对象
或类
应该没有问题
如果您需要按需创建IChallenge
,那么您可能需要这样一个实现:
public class LazyChallenge<T> implements IChallenge<T> {
private final Class<IChallenge<T>> impl;
private IChallenge<T> value;
public LazyChallenge(IChallenge<T> impl) {
this.impl = impl;
}
public boolean handle(T o) {
if (value == null) {
try {
value = impl.getConstructor().newInstance();
} catch (java.lang.ReflectiveOperationException e) { // ... a bunch of exception your IDE will fill in ...
throw new IllegalStateException(e);
}
}
return value.handle(o);
}
}
或者可以使用lambda来避免反射:
public class LazyChallenge<T> implements IChallenge<T> {
private final Class<IChallenge<T>> supplier;
private IChallenge<T> value;
public LazyChallenge(Supplier<IChallenge<T>> supplier) {
this.supplier = supplier;
}
public boolean handle(T o) {
if (value == null) {
value = supplier.get();
}
return value.handle(o);
}
}
如果我要实现它,我会使用lambda方法,因为这样可以避免反射陷阱(try-catch、可见性问题,特别是考虑到java9++引入了模块,…)
上面定义的LazyChallenge
可能有助于避免创建多个StringChallenge
。在这种情况下,最好让it实现Supplier
,而不是IChallenge
整个离题并没有改变我之前指出的:确保只有
ChallengeHolder
读/写地图。如果我理解正确,您希望类作为地图的键,而不是对象的键。所以这应该是私有的Map>challenges=newhashmap()代码>。还要注意,我将列表类型从AbstractChallenge
更改为IChallenge
。使用接口而不是抽象实现总是更好的。获取所有处理特定类型的“挑战”类。2.从该列表中,删除任何成功处理事件的“挑战”?@markspace Yes!我已经正确地计算了删除挑战(如果已完成)的方法,但还没有计算出如何获取具有指定类型的挑战列表。我将重新编辑我的帖子以使其更清晰。@magicmn我最初尝试过(虽然是用AbstractChallenge而不是IChallenge),IntelliJ说Required type:List Provided:List我不完全确定如何使用您指定的addChallenge
方法。现在,对于创建的每个质询,我都有一个类>
列表,当加载特定质询时,程序将使用.newInstance()
实例化。我应该换一种方式吗?我只需要一次加载一定数量的挑战,而不是全部
challenges.get(Integer.class).add((Number a) -> a.intValue() > 10); // #1
challenges.get(Integer.class).add((Integer a) -> a.intValue() > 10); // #2
challenges.get(Integer.class).add((Object a) -> a != null); // #3
challenges.get(Integer.class).add((String a) -> a.length() > 10); // #4
Integer a = Integer.valueOf(5);
// #1 -> ok: a is a Number
challenges.get(a.getClass()).removeIf(c -> c.handle(a));
// #2 -> ok: a is an Integer
challenges.get(a.getClass()).removeIf(c -> c.handle(a));
// #3 -> ok: a is an Object
challenges.get(a.getClass()).removeIf(c -> c.handle(a));
// #4 ->ko: a is not a String
challenges.get(a.getClass()).removeIf(c -> c.handle(a));
public <T> void addChallenge(Class<T> type, IChallenge<T> challenge) {
challenges.computeIfAbsent(type, ignored -> new ArrayList<>()).add(challenge);
}
class ChallengeHolder {
private final Map<Class<?>, List<IChallenge<?>>> challenges;
public ChallengeHolder() {
this.challenges = new HashMap<>();
}
public <T> void addChallenge(Class<T> type, IChallenge<T> challenge) {
challenges.computeIfAbsent(type, ignored -> new ArrayList<>()).add(challenge);
}
public boolean handle(Object a) {
List<IChallenge<T>> challengers = challenges.get(a);
if (challengers == null) return false;
return challengers.removeIf(c -> c.handle(a));
}
}
public class LazyChallenge<T> implements IChallenge<T> {
private final Class<IChallenge<T>> impl;
private IChallenge<T> value;
public LazyChallenge(IChallenge<T> impl) {
this.impl = impl;
}
public boolean handle(T o) {
if (value == null) {
try {
value = impl.getConstructor().newInstance();
} catch (java.lang.ReflectiveOperationException e) { // ... a bunch of exception your IDE will fill in ...
throw new IllegalStateException(e);
}
}
return value.handle(o);
}
}
challengeHolder.addChallenge(String.class, new LazyChallenge<>(StringChallenge.class));
public class LazyChallenge<T> implements IChallenge<T> {
private final Class<IChallenge<T>> supplier;
private IChallenge<T> value;
public LazyChallenge(Supplier<IChallenge<T>> supplier) {
this.supplier = supplier;
}
public boolean handle(T o) {
if (value == null) {
value = supplier.get();
}
return value.handle(o);
}
}
challengeHolder.addChallenge(String.class, new LazyChallenge<>(StringChallenge::new));
class ChallengeHolder {
private final Map<Class<?>, List<Supplier<IChallenge<?>>>> challenges;
public ChallengeHolder() {
this.challenges = new HashMap<>();
}
public <T> void addChallenge(Class<T> type, Supplier<IChallenge<T>> challenge) {
challenges.computeIfAbsent(type, ignored -> new ArrayList<>()).add(challenge);
}
public boolean handle(Object a) {
List<IChallenge<T>> challengers = challenges.get(a);
if (challengers == null) return false;
return challengers.removeIf(c -> c.get().handle(a));
}
}
StringChallenge existing = ... ;
// always reuse an existing
challengeHolder.addChallenge(String.class, () -> existing);
// bring a new challenge each time that ChallengeHolder::handle is called
challengeHolder.addChallenge(String.class, StringChallenge::new);