繁体   English   中英

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

[英]Java 8 compatibility issue: How to convert Object array to Subtype List in 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;
    }
}

错误当然是:

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                     

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

编辑:澄清。 我无法控制B类会返回给我什么。 我也无法以任何方式修改A类(我认为这在任何情况下都不会有所帮助)。 我只能控制HelloWorld的功能。

如果您无权访问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());

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

List<A> a = objArray == null ? Collections.emptyList() : (List)Arrays.asList(objArray);

如果不确定数组中的内容,则应使用以下内容仅过滤掉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());

或与方法引用相同:

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());

编辑:添加了objArray来省略两次调用getA() ,如getA()的答案所示。 两次调用它可能比所有其他提议的解决方案贵。

最安全的解决方案是将数组复制到正确类型的数组,即

Object[] array = someObject.getA();
List<A> a = array==null? Collections.emptyList():
    Arrays.asList(Arrays.copyOf(array, array.length, A[].class));

在Java 8中,可以选择改用Stream API,该API稍短一些:

Object[] array = someObject.getA();
List<A> a = array==null? Collections.emptyList():
    Arrays.asList(Arrays.stream(array).toArray(A[]::new));

如果您担心数组复制的开销,那么,在您的原始代码中,您两次调用了getA() ,这比单纯的数组副本施加了更高的开销。 上述解决方案可以解决此问题。

进行未经检查的操作“因为我知道我在做什么”很少会奏效。 在这种情况下,您只需将成本从创建列表移到使用列表的位置。

Object[] array = example.getLabelCodes();

将对象数组转换为列表。

List<String> stringArray = Arrays.asList(Arrays.stream(array).toArray(String[]::new));

将列表转换回对象数组。

Object[] objectArray = stringArray.toArray();

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM