Java 8 兼容性问题:如何在 Java 8 中将对象数组转换为子类型列表?

Deb*_*Roy 2 java java-8

所以我有一个在 Java 7 上运行良好的程序,但在 Java 8 中它无法编译并出现错误。所以,我解决了 Java 兼容性问题,我想我找到了原因(或者我找到了吗?http://bugs. java.com/bugdatabase/view_bug.do?bug_id=7144506 ) 。我想知道是否有一种简短的有效方法来复制我的原始代码片段在 Java 8 中所做的事情。这是一个表示这种情况的程序。在我的代码中,有一个 setter 方法可以完成填充数组的工作,但我无法控制它的填充方式。

import java.util.List;
import java.util.Arrays;

public class HelloWorld{
    public static void main(String []args){
        B someObject=new B();
        List<A> a = someObject.getA() == null ? Collections.EMPTY_LIST : Arrays.asList(someObject.getA());
        for ( A item : a ) {
            System.out.println(item.value);
        }
    }
}

class A{
    String value;
    public A(String value){
        this.value = value;
    }
}

class B{
    Object[] getA(){
        Object arr[]= new Object[4];
        arr[0]=new A("hello");
        arr[1]=new A("mello");
        arr[2]=new A("jello");
        arr[3]=new A("cello");
        return arr;
    }
}
Run Code Online (Sandbox Code Playgroud)

错误当然是:

HelloWorld.java:8: error: incompatible types: bad type in conditional expression                                                                                                
        List<A> a = someObject.getA() == null ? Collections.EMPTY_LIST : Arrays.asList(someObject.getA());                                                                      
                                                                                      ^                                                                                         
    inference variable T has incompatible bounds                                                                                                                                
      equality constraints: A                                                                                                                                                   
      lower bounds: Object                                                                                                                                                      
  where T is a type-variable:                                                                                                                                                   
    T extends Object declared in method <T>asList(T...)                                                                                                                         
Note: HelloWorld.java uses unchecked or unsafe operations.                                                                                                                      
Note: Recompile with -Xlint:unchecked for details.                                                                                                                              
1 error                     
Run Code Online (Sandbox Code Playgroud)

我需要一种(最好是一条线/优雅的)替代方法,它也可以有效地完成相同的任务。

编辑:澄清。我无法控制 B 班返回给我的东西。我也不能以任何方式修改 A 类(我认为这在任何情况下都无济于事)。我只能控制 HelloWorld 做什么。

Rol*_*and 6

如果您无法访问 B,但确定您获得了 A,则可以尝试以下操作:

Object[] objArray = someObject.getA(); // omit calling getA() twice
List<A> a = objArray == null ? Collections.emptyList() :
                 Stream.of(objArray)
                         .map(o -> (A) o) // or place your transform function in here
                         .collect(Collectors.toList());
Run Code Online (Sandbox Code Playgroud)

正如@JBNizet 指出的那样:最简单但不安全且因此不是真正推荐的解决方案,就是添加一个List-cast:

List<A> a = objArray == null ? Collections.emptyList() : (List)Arrays.asList(objArray);
Run Code Online (Sandbox Code Playgroud)

如果您不确定数组中的内容,您应该使用以下内容仅过滤掉 A:

List<A> a = objArray == null ? Collections.emptyList() :
                 Stream.of(objArray)
                         .filter(o -> o instanceof A)
                         .map(o -> (A) o) // or place your transform function in here
                         .collect(Collectors.toList());
Run Code Online (Sandbox Code Playgroud)

或与方法引用相同:

List<A> a = objArray == null ? Collections.emptyList() :
                 Stream.of(objArray)
                         .filter(A.class::isInstance)
                         .map(A.class::cast) // or place your transform function in here
                         .collect(Collectors.toList());
Run Code Online (Sandbox Code Playgroud)

编辑:添加objArray以省略getA()在@Holger 的回答中看到的两次调用。调用它两次可能比所有其他建议的解决方案更昂贵。

  • 如果您绝对想保留您拥有的不安全代码,并且如果它不是 A,当您从该列表中获取元素时可能会中断,您可以使用 `List&lt;A&gt; a = someObject.getA() == null ? Collections.emptyList() : ((List)Arrays.asList(someObject.getA()));`。不过,我不会推荐它。 (2认同)
  • 好的。我的意思是不安全的代码不在 B 中。在你的问题中不安全的代码在 HelloWorld 中。 (2认同)
  • 没问题。正如@Holger 所说,你的代码调用`getA()`两次可能不会那么高效。我个人会选择任何流解决方案(`Stream.of`、`Arrays.stream` 等)......越简单越好。或者:越容易理解越好;-) (2认同)