在Java中,是否可以使用"原始无参数化类"而不是使用虚拟接口?



我在Java中接触泛型已经有一段时间了,我有了这个:

Map<List<MyGenericType>, Set<List<MyGenericType>>> x = new HashMap<>();

事实上,MyGenericType需要一个通用参数,因为它是这样定义的:

public class MyGenericType<X> {}

我用MyGenericType的抢占式擦除声明了x,因为我不想仅仅为了分组而制作一个空的标记接口。为了拥有一个集合,这会对我有利吗?还是我必须制作一个标记接口才能实现这一点?

(编辑(即:

  1. public interface SomeCommonInterface {...}
  2. MyGenericType implements SomeCommonInterface ...
  3. Map<List<SomeCommonInterface>, Set<List<SomeCommonInterface>>> x = new HashMap<>();

回想一下,IntegerDouble都扩展了Number,而Number又扩展了Object

List<Number>决不能用作List<Integer>,反之亦然List<Number> x = new ArrayList<Integer>不编译。这被称为"不变性",它是"正确的",因为如果它真的编译了,你可以在整数列表中添加双精度,这显然是不对的。不过,它往往会让人反感,这就是我提到它的原因。如果你想要协方差或方差,你必须选择这个List<? extends Number> list = new ArrayList<Integer>();编译。但list.add(5);不会,因为如果它这样做了,你就可以再次向整数列表中添加双精度,这是不对的。

一旦你完全省略了一件事的泛型,所有对泛型的类型检查都是不可能的,你不希望这样。你能"逍遥法外"吗?嗯,嗯,编译器会在你面前抛出一堆警告,你会关闭很多类型检查。如果你的意思是"逍遥法外":;它会编译"吗;?是的,确实如此。如果你的意思是:;这段代码会通过任何合理的java程序员的代码审查吗不,不会

简单的解决方案:在这里使用MyGenericType<?>有什么问题?

注意:映射中的键应该是不可变的;列表不是。因此,使用它是一个相当糟糕的计划;那应该代表什么?

这不是一个真正的答案,但正如这里的评论中所说,我认为添加通配符不会解决任何问题。

根据Map的使用地点,您可能会有某种安全性。我有几次站在你的立场上,我知道的唯一解决方案是:

@Getter
static class Box<T> {
private Map<List<MyGenericType<T>>, Set<List<MyGenericType<T>>>> x = new HashMap<>();
}

即:通过"曝光"来曝光CCD_ 19;"包装物";,定义了类型变量。如果调用方在实例化Box时提供了一个类型,那么您将获得所需的类型安全性:

new Box<Integer>().getX().put(...); // you can only put a MyGenericType<Integer> in here now

否则,当使用原始类型甚至?时,可以在键和值中放入不同的类型。

最新更新