首页 > 解决方案 > 以这种方式使用泛型时,尝试重构并避免“参数不匹配,无法转换为 SomeClass”

问题描述

好的,所以开始事情并给出上下文 - 我正在重构一些旧代码,并决定采用“0 个警告,0 个 lint 警告”规则。这意味着任何警告都会使构建崩溃...

所以,我目前的问题是原始类型列表。让我发布一些代码以提供更好的上下文:

public abstract class Event implements Cloneable {
  // contents of this class aren't very important
  private long timestamp;
}

public interface EventObservable<T extends Event> {
    List<T> pollEvents();

    List<T> subscribe(EventCallback<T> callback) throws UnsupportedOperationException;

    boolean unsubscribe();
   // more less-significant methods
}

public abstract class AbstractEventObservable<T extends Event> implements EventObservable<T> {
  // nothing very significant
}

public class SomeEventObservable extends AbstractEventObservable<SomeEvent> {
  // storage, helpers, and overriding AbstractEventObservable methods
}

EventObservable当将各种s 添加到 a时,一切正常List<EventObservable>。我正在尝试更改它以List<EventObservable<Event>>消除有关使用 raw-type 的警告EventObservable。此列表仅创建并填写一次...

但是,当我更改此行时:

final List<EventObservable> list = new ArrayList<>(8);

对其中任何一个: final List<EventObservable<Event>>final List<EventObservable<? extends Event>>final List<EventObservable<? super Event>>

这里的这一点是发出警报的第一件事:

private List<EventObservable<? extends Event>> getEventObservablesList(...) {

            list.add(getDeviceInfoEventObservable(...)); // returns DeviceInfoEventObservable extends AbstractEventObservable<Event>

            list.add(getInstalledAppsEventObservable(...)); // returns InstalledAppsEventObservable extends AbstractEventObservable<InstalledAppsEvent>

            list.add(getAppInstalledEventObservable(...)); // returns AppInstalledEventObservable extends AbstractEventObservable<AppInstalledEvent>

            list.add(getAppUninstalledEventObservable(...)); //returns AppUninstalledEventObservable extends AbstractEventObservable<AppUninstalledEvent>

            list.add(getNetworkSwitchEventObservable(...)); //returns NetworkSwitchEventObservable implements EventObservable<NetworkSwitchEvent>

我有点想在这里应用 PECS,但在某些时候我需要生成和使用列表。我需要用不同事件的 EventObservables 来填充它,即使我EventObservable<? extends Event>在将它们添加到列表EventObservable<? super Event>的地方使用,并在我只是遍历列表的地方使用,在某些时候我点击了 `List<EventObservable< ? extends Event>> 不能分配给 List<EventObservable<? 超级活动>>

那么,我最好的方法是什么?

欢迎任何建议。

隐含的、隐藏的问题也是“我如何在List<EventObservable<? extends Event>>and之间架起桥梁List<EventObservable<? super Event>>?我真的很想避免List<EventObservable<?>>,因为不知何故,这并不比压制对我的警告更好。它们都会有不同种类的Events。所以这就是为什么我Event也想出现在那里,因为EventObservable<?>看起来它在技术上可以接受任何东西,甚至是字符串。

编辑:

我不能真正发布 MCVE,但流程是这样的:

代码实际上工作正常,测试通过。但它们是原始类型的,我想改变这一点,也许有<? extends Event>一端,和<? super Event>,类似的东西 - 或者更好。现在我想在全部打开警告后摆脱警告,我的选择是:

我不打算重新设计整个事情,并且 usingEventObservable<?>看起来并不比抑制警告好多少,但它肯定是一个不太理想的重构,所以警告消失了。或者也许不是,我还不知道,当我将它应用到EventObservable使用原始类型的任何地方时,我会知道的。

下面是一些代码来说明这一点:

public class Initialization class {
   private List<EventObservable> observableList; //i would like to avoid rawtype here

   private List<EventObservable> initList() {   //similar comment applies here
       List<EventObservable<Event>> list = new ArrayList()

       list.add(getSomeObservable(...)); //this works fine, because SomeObservable has a Event generic type, since it returns different types of Events

       list.add(getOtherObservable(...)); // this breaks down, because OtherObservable emits Event2

       list.add(getYetAnotherObservable(...)); //this breaks too, because YetAnotherObservable emits Event3

       return list;
    }

    public init()  {
      // unnecessary stuff
 
      observableList = initObservableList(...);  // this also breaks in different ways depending on how i declare observableList and return type of initObservableList()

     // more stuff
   }

   private SomeObservable getSomeObservable() { ... }

   private OtherObservable getOtherObservable() { /* instantiate OtherObservable */ }

   private YetAnotherObservable getYetAnotherObservable() { /* same */ }


   private void test() {
      EventObservable<Event> bla = getOtherObservable() // works fine
      EventObservable<OtherEvent> bla2 = getOtherObservable() // doesn't work, required type EventObservable<OtherEvent>, provided OtherObservable


      EventObservable<OtherEvent> bla3 = new AbstractEventObservable<OtherEvent> { ... }
      EventObservable<Event> test = bla3; // fails, required type EventObservable<Event>, provided EventObservable<OtherEvent>


      // sanity tests just to refresh my memory on generics
            List<Number> numbers;
            List<? extends Number> numbers2;
            List<Integer> integers = new ArrayList<Integer>();
            List<Float> floats = new ArrayList<Float>();
            numbers = floats; //nope, required type List<Number>, provided List<Integer>
            numbers.addAll(integers); //fine
            numbers.addAll(floats); //fine

            numbers2 = floats; 
            numbers2.addAll(integers); //nope, Required Collection<? extends capture of ? extends Number>, provided List<Integer>
      
   }
}


public class SomeObservable extends AbstractEventObservable<Event> {
  // unnecessary contents
}

public class OtherObservable extends AbstractEventObservable<OtherEvent> {
  // same as above
}

public class YetAnotherObservable extends AbstractEventObservable<YetAnotherEvent> {
  // ditto
}

public abstract class Event { /* mentioned above */ }
public class OtherEvent extends Event { ... }
public class YetAnotherEvent extends Event { ... }

所以,我宁愿选择EventObservable<Event>,而是列出那些很麻烦的列表。如果我开始使用,List<EventObservable<? extends Event>>那么当我更改它的 getter 的返回类型时,我会打开一个全新的蠕虫罐 -initList()方法。即使我<? extends Event>在任何地方都使用(好吧,在我尝试过的一堆文件中),我最终还是遇到了一个方法返回有界通配符并被赋予另一个采用有界通配符的方法,但是它说捕获# 1 和 capture#2 可能不同。

所以我猜我不应该在任何地方返回通配符。所以现在我认为打破这 3 个 observables 并使 Event 成为它们的通用类型可能是“最简单的”。我没有聪明的主意。

标签: javagenerics

解决方案


推荐阅读