【问题标题】:How to create the correct return type?如何创建正确的返回类型?
【发布时间】:2013-06-19 14:30:02
【问题描述】:

我会在底部发布我的问题。

下面是其他类扩展的类。

public class people {

    class family extends people {   
    }

    class friends extends people {  
    }

    class coworkers extends people {    
    }
}

下面是具有 getAllPeopleByClass 方法的类,该方法由选择类中的 getMembers() 方法调用:

public class processing {

static processing process = null;
private Collection<family> familyList = new ArrayList<family>();
private Collection<coworkers> cowList = new ArrayList<coworkers>();
private Collection<friends> friendList = new ArrayList<friends>();

public processing(){
}

public static processing getInstance() {
    if (process == null)
        process = new processing();
    return process;
}

public <T> Collection<people> getAllPeopleByClass(Class<T> clazz) {
    Collection<people> peopleCollection;
    peopleCollection.addAll(getList(clazz));
    return peopleCollection;
}

private <T> Collection<? extends people> getList(Class<T> clazz) {
    if (clazz == family.class) {  
        return familyList;  
    } else if (clazz == coworkers.class) {
        return cowList;
    } else { // else if clazz == friends.class
        return friendList;
    }
}

最后,使用处理的类:

 public class familySelection {
  public Collection<family> getMembers() {
    Collection<family> f;
    f = processing.getInstance().getAllPeopleByClass(family.class); //type mismatch
    return f; 
  }
}

 public class coworkerSelection {
  public Collection<coworkers> getMembers() {
    Collection<coworkers> c;
    c = processing.getInstance().getAllPeopleByClass(coworkers.class); //type mismatch
    return c;
  }
}


public class friendsSelection {
  public Collection<friends> getMembers() {
    Collection<friends> f;
    f = processing.getInstance().getAllPeopleByClass(friends.class); //type mismatch
    return f;
  }
}

我的问题是我在每个 getMembers() 方法中的 getAllPeopleByClass 调用中都出现了类型不匹配。

我试过这个:

public class familySelection {
  public Collection<family> getMembers() {
    Collection<? extends people> f; //changed to extend from people
    f = processing.getInstance().getAllPeopleByClass(family.class);
    return (Collection<family>) f; //cast warning - dont want that
  }
}

这可行,但我收到一个演员警告,我不想也不想压制它。这是我最接近解决问题的方法。此外,getMembers() 的返回类型必须保持不变。有没有人有办法在没有任何警告的情况下做到这一点?或者甚至以某种方式一般地处理这个?谢谢!

【问题讨论】:

  • 您设计中的主要问题是泛型用于编译时类型强制,但您在运行时执行类型检查。或许可以考虑使用 3 个单独的方法来返回每种类型的集合。

标签: java generics types extends mismatch


【解决方案1】:
public <T> Collection<T> getAllPeopleByClass(Class<T> clazz) {
    Collection<T> peopleCollection = new ArrayList<T>();
    for(people p : getList(clazz)) {
      peopleCollection.add(clazz.cast(p));
    }
    return peopleCollection;
}

【讨论】:

  • 您是否阅读过:这可行,但我收到演员表警告,我不想也不想压制它。
  • @darijan - 您是否完整阅读了我的(更新的)答案? “由于java泛型的限制......”。这是“最正确的”。
  • 这是泛型问题的限制?
  • @StephenD - 是的,编译器无法保证返回的集合中包含实际的类型化类。
  • 有没有办法在没有泛型的情况下实现这一点?不需要代码,但如果是这样,很高兴知道!
【解决方案2】:

使用super 关键字:

public class familySelection {
  public Collection<? super family> getMembers() {
    Collection<? super family> f;
    f = processing.getInstance().getAllPeopleByClass(family.class);
    return f;
  }
}

UPD: 使用super 通配符,当您只将put 值转换为结构时。当您仅在结构中使用 get 值时,请使用extends 通配符。同时使用getput 时不要使用通配符。

【讨论】:

  • 这将编译,但它不会很有用。拥有某种类型的集合,它是家族的超类,并不比根本不使用泛型更有用。
  • OP 确实说过 getMembers() 的返回类型必须保持原样
【解决方案3】:

我会选择这个版本。它还需要警告抑制,但我认为这是更好的地方。

我还允许自己更改您的 Singleton 实现。如果您真的想这样做,请考虑使用枚举。

public enum processing {
    INSTANCE;

    private Collection<family> familyList = new ArrayList<family>();
    private Collection<coworkers> cowList = new ArrayList<coworkers>();
    private Collection<friends> friendList = new ArrayList<friends>();

    public static processing getInstance() {
        return INSTANCE;
    }

    public <T extends people> Collection<T> getAllPeopleByClass(Class<T> clazz) {
        Collection<T> peopleCollection = new ArrayList<T>();
        peopleCollection.addAll(getList(clazz));
        return peopleCollection;
    }

    @SuppressWarnings("unchecked")
    private <T extends people> Collection<T> getList(Class<T> clazz) {
        if (clazz == family.class) {
            return (Collection<T>) familyList;
        } else if (clazz == coworkers.class) {
            return (Collection<T>) cowList;
        } else { // else if clazz == friends.class
            return (Collection<T>) friendList;
        }
    }
}

和familySelection:

public class familySelection {
    public Collection<family> getMembers() {
        Collection<family> f = processing.getInstance().getAllPeopleByClass(family.class);
        return f;
    }
}

【讨论】:

  • 感谢您的帖子。为什么你更喜欢警告可以完全消除?
  • 我在@jtahlborn 编辑他的版本之前就开始写我的回复了。
  • 还有一件事:可能在大多数情况下这并不重要,但他必须为集合中的每个对象执行 cast(p) 方法。他可以做到这一点而不会冒 ClassCastException 的风险,只是因为他知道 getList(clazz) 方法的实现。所以他也在做未经检查的演员,只是不那么明显 - 你不必压制它。
  • 还有另一件事:):getList(clazz) 中的最后一个“else if”应该被取消注释。我不相信每次有人添加新的人员实现时,他都会记得将新集合添加到处理类中。
猜你喜欢
  • 2012-02-21
  • 2018-01-29
  • 1970-01-01
  • 1970-01-01
  • 2020-09-20
  • 1970-01-01
  • 1970-01-01
  • 2020-02-03
相关资源
最近更新 更多