Java自限泛型

时间:2017-01-26 07:13:39

标签: java generics

我有自己的通用,如:

public interface SelfConfigurable<E extends SelfConfigurable<E>> {
    E configure(JsonObject settings);
}

另一个界面,也是泛型类型,扩展了我之前的界面:

public interface ConfigurableSegmentFilter<T> extends SegmentFilter<T>, SelfConfigurable<ConfigurableSegmentFilter<T>> {
}

我也有像这样的实现

public abstract class ConfigurableSegmentFilterSkeleton<T> implements ConfigurableSegmentFilter<T> {
    @Override
    public ConfigurableSegmentFilter<T> configure(JsonObject settings) {
     ... }
}

我通过反射实例化对象,并希望在添加到List之前配置它:

List<ConfigurableSegmentFilter<?>> result = ...

ConfigurableSegmentFilter newFilter = Reflection.newInstance() + casting

result.add(newFilter.configure(...)); <-- compile error 'cannot be applien to SelfConfigurable' but why?

//when i call to configure directly i am getting:
SelfConfigurable configure = newFilter.configure(...) <-- why SelfConfigurable??

我收到编译错误!它告诉我xxx.configure()返回SelfConfigurable接口而不是ConfigurableSegmentFilter,我无法理解它为什么会发生。

还有一件事,当我将newFilter与开始按预期工作的通配符绑定时

List<ConfigurableSegmentFilter<?>> result = ...

ConfigurableSegmentFilter<?> newFilter = ... //<-- bound with <?>

result.add(newFilter.configure(...)); <-- No error! But why?

ConfigurableSegmentFilter vs ConfigurableSegmentFilter<?>

的唯一区别

2 个答案:

答案 0 :(得分:0)

'raw'类型与通用类型参数设置为'Object'的通用类型不同。

这样做的原因是为了避免运行时强制转换异常。

例如,让我们考虑一个涉及'java.util.List'类的简单场景:

List a = ... # a elements could be a mix of any type.
List<?> b = ... # b elements are all instance of a known class '?'.
List<Object> c = ... # c elements are all instances of Object.
List<String> d = ... # d elements are all instances of String.

应该清楚为什么将任何其他列表中的元素移动到'd'必须有问题,因为不能保证这些元素是'String's

然而,其他任何组合呢?

  1. a,c或d - &gt;湾

    b.addAll(c); // error!!!
    

    '?'这里代表一个未知类型...例如它可能是String,在这种情况下我们回到明确的情况c - &gt; d。这个限制到位的原因是,当实际知道集合的类型参数的一些其他代码(比如String)并且正在消耗它时,防止运行时异常会拉动非字符串实例导致运行时强制转换异常

  2. b,a,d - &gt; c或b,c,d - &gt;一个。

    允许,毕竟什么'?'所有实例都是'对象',所以没问题。一个

  3. 还要注意一些参考指定我的问题(至少是一个警告):

       c = a; // unchecked warning; 
       c = d; // error as now you would be able to add non-strings to 'd' thru 'c'.
       c = b; // error, same as above where the the element type is unknown.
       a = d; a = b; // same as with 'c'.
       d = c; d = a; // error for obvious reason. 
    

答案 1 :(得分:0)

当您使用原始类型的表达式时,您&#34;关闭&#34;使用该表达式执行的所有泛型,包括方法签名和超类型签名。这意味着,原始类型ConfigurableSegmentFilter仅扩展原始类型SelfConfigurable,因此其实例方法.configure()将返回E的删除,即SelfConfigurable

这就是为什么你应该避免使用原始类型,因为它们只是为了向后兼容。当type参数未知时,您可以使用通配符参数化类型。

相关问题