Java 返回不同类型的方法?

Java 返回不同类型的方法?,java,collections,iterator,Java,Collections,Iterator,我正在写一个方法 这是层次结构树: IProtocoll | |--ProtocolImpl1 | |--ProtocolImpl2 | |--ProtocolImpl3 方法本身如下所示: public static List<IProtocol> getProtocolsByType(String type, Transaction trx) { Iterator<IProtocol> protocols = trx.getProtocols();

我正在写一个方法

这是层次结构树:

IProtocoll
|
|--ProtocolImpl1
|
|--ProtocolImpl2
|
|--ProtocolImpl3
方法本身如下所示:

public static List<IProtocol> getProtocolsByType(String type, Transaction trx) {
    Iterator<IProtocol> protocols = trx.getProtocols();
    List<IProtocol> protocolsList = new ArrayList<IProtocol>();
    while (protocols.hasNext()) {
        if (StringHeper.isEqual(protocolls.next().getProtocolType(), type) {
            protocolsList.add(protocolls.next());
        }
    }
    return protocolsList
}
List<ProtocolImpl1> list = (List<ProtocolImpl1>) ProtocolHelper.getProtocolsByType("PROTOCOL1", trx)

for (ProtocolImpl1 protocol : list) {
    ProtocolHelper.createProtocolType1(protocol)
}
公共静态列表getProtocolsByType(字符串类型,事务trx){
迭代器协议=trx.getProtocols();
List protocolsList=新的ArrayList();
while(protocols.hasNext()){
if(StringHeper.isEqual(protocols.next().getProtocolType(),type){
protocolsList.add(protocolls.next());
}
}
返回协议列表
}
以及使用示例

List<IProtocol> list = ProtocolHelper.getrProtocolsByType("PROTOCOL1", trx)

for (IProtocol protocol : list) {
    ProtocolHelper.createProtocolType1((ProtocolImpl1) protocol)
}
List List=ProtocolHelper.getrProtocolsByType(“PROTOCOL1”,trx)
用于(IProtocol协议:列表){
ProtocolHelper.createProtocolType1((ProtocolImpl1)协议)
}
现在,正如在类型层次结构中看到的那样,这个方法有3种可能返回什么

String type
定义了应返回的协议类型。
trx.getProtocols()
将返回一个包含所有3种协议类型的迭代器


有没有一种方法可以以某种方式统一此方法,使其返回这三种类型中的一种,而不必在以后使用该方法时使用不必要的强制转换?

您可以这样使用它:

public static List<IProtocol> getProtocolsByType(String type, Transaction trx) {
    Iterator<IProtocol> protocols = trx.getProtocols();
    List<IProtocol> protocolsList = new ArrayList<IProtocol>();
    while (protocols.hasNext()) {
        if (StringHeper.isEqual(protocolls.next().getProtocolType(), type) {
            protocolsList.add(protocolls.next());
        }
    }
    return protocolsList
}
List<ProtocolImpl1> list = (List<ProtocolImpl1>) ProtocolHelper.getProtocolsByType("PROTOCOL1", trx)

for (ProtocolImpl1 protocol : list) {
    ProtocolHelper.createProtocolType1(protocol)
}
List List=(List)ProtocolHelper.getProtocolsByType(“PROTOCOL1”,trx)
for(ProtocolImpl1协议:列表){
ProtocolHelper.createProtocolType1(协议)
}
如果您还希望避免该强制转换,那么根据您当前的代码,我看到的唯一方法是在ProtocolHelper中创建单独的方法:

List<ProtocolImpl1> getAllProtocolsOfType1(trx);
List<ProtocolImpl2> getAllProtocolsOfType2(trx);
List<ProtocolImpl3> getAllProtocolsOfType3(trx);
列出getAllProtocolsOfType1(trx);
列出getAllProtocolsOfType2(trx);
列出getAllProtocolsOfType3(trx);

但当然,如果协议数量增加,那么这种扩展性就不强。

您可以尝试以下方法:

public static <T extends IProtocol> List<T> getProtocolsByType(Class<T> typeClass, Transaction trx) {    
  Iterator<IProtocol> protocols = trx.getProtocols();
  List<T> protocolsList = new ArrayList<T>();
  while( protocols.hasNext() ) {
     //call next() only once
     IProtocol p = protocols.next();

     //Check if p is an instance of typeClass or a subtype
     if ( typeClass.isAssignableFrom( p.getClass() ) {
        protocolsList.add( (T)p );
     }
   }
   return protocolsList;
}

List<ProtocolImpl1> list = ProtocolHelper.getrProtocolsByType( ProtocolImpl1.class, trx)
公共静态列表getProtocolsByType(类typeClass,事务trx){
迭代器协议=trx.getProtocols();
List protocolsList=新的ArrayList();
while(protocols.hasNext()){
//只调用next()一次
IProtocol p=协议。下一步();
//检查p是typeClass的实例还是子类型
if(typeClass.isAssignableFrom(p.getClass()){
协议列表添加((T)p);
}
}
返回协议列表;
}
List List=ProtocolHelper.getrProtocolsByType(ProtocolImpl1.class,trx)
因此,与其将类型作为字符串传递,不如传递希望获得的实现类


强制转换
(T)p
是必要的,但由于您检查
p
是否属于
T
类型或子类型,这是安全的。

泛型是救世主。请使用以下方法:

public static <T extends IProtocol> List<IProtocol> getProtocolsByType(Class<T> clazz, Transaction transaction) {    
  //do logic here
}
公共静态列表getProtocolsByType(类clazz,事务处理){
//你在这里讲逻辑吗
}
尝试使用java泛型。
公共静态列表getProtocolsByType
类型T可以是扩展IProtocol的任何类型。 查看有关它们的oracle教程->
他们会解决你的问题。

这里有一个可能的解决方案:

public <I extends IProtocol> List<I> getProtocols(Class<I> protocolClass) {
    Iterator<IProtocol> protocols = trx.getProtocols();
    List<I> protocolsList = new ArrayList<I>();
    while (protocols.hasNext()) {
      if (protocols.next().getClass().equals(protocolClass)) {
          protocolsList.add((I) protocols.next());
      }
    }
    return protocolsList;

}
公共列表GetProtocolClass(类协议类){
迭代器协议=trx.getProtocols();
List protocolsList=新的ArrayList();
while(protocols.hasNext()){
if(protocol.next().getClass().equals(protocolClass)){
protocolsList.add((I)protocols.next());
}
}
返回协议列表;
}
与其将类型指定为字符串,不如将其指定为类。使用上述签名,您无需强制转换


唯一的问题是,对I的强制转换会导致警告,但由于我们已经检查了类类型,我们知道它会强制转换为OK。

如果您觉得有必要将具有接口类型的对象强制转换为其实现,这应该会敲响警钟。您的抽象可能不正确,通过更改接口可以避免整个cast(当然这并不总是可能的,但值得检查)只是关于您发布的代码的旁注:您在循环中调用了两次
protocolls.next()
,因此可能会跳过元素。请注意
next()
将迭代器前进一步,因此如果要重用该元素,则需要存储返回值(例如,在if子句中,然后将其添加到列表中)。请注意,调用者可能应该使用:
列表将其分配回
列表
?@如果我正确理解了OP,他不想使用它,因为您将不得不再次强制转换为实际类型。
列表您不认为OP应该使用
IProtocol
调用重写的方法吗?。如果
的契约IProtocol
及其实现类保持良好,那么OP应该这样做。如果他需要其他方法,那么可能需要返回一个具体的类集合fine@TheLostMind是的,那是正确的。如果你只能使用
IProtocol
,那么你肯定应该这样做。