有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

Java中带泛型的静态多态性

我希望创建一些干净的代码,可以递归地挖掘集合并打印它找到的第一个整数。来自C++背景的方法看起来像这样:

class Test {
static void print(Integer i) {
  System.out.println(i);
}

static <T> void print(ArrayList<T> arr) {
  T entry= arr.at(0);
  Test.print (entry);
}

static void Test() {
    ArrayList<ArrayList<Integer>> arrayOfArrayOfInt= create();
    print( arrayOfArrayOfInt );
}
}

不幸的是,这不起作用

一种替代方法是放弃静态多态性,创建一个函数print(Object o),然后进行大量instanceof检查,以转移到正确的行为。这是由于Java的类型擦除而实现的唯一方法,还是有更优雅的方法


共 (2) 个答案

  1. # 1 楼答案

    下面的方法将递归地挖掘一个Object,并返回一个包含它找到的第一个IntegerOptional,如果找不到,则返回Optional.empty()

    static Optional<Integer> firstInt(Object o) {
        if (o instanceof Integer)
            return Optional.of((Integer) o);
        if (o instanceof int[]) {
            int[] array = (int[]) o;
            return array.length > 0 ? Optional.of(array[0]) : Optional.empty();
        }
        if (o instanceof Object[])
            return firstInt(Arrays.asList((Object[]) o));
        if (o instanceof Iterable) {
            for (Object o2 : (Iterable<?>) o) {
                Optional<Integer> result = firstInt(o2);
                if (result.isPresent())
                    return result;
            }
        }
        return Optional.empty();
    }
    

    您可以使用多态性来实现这一点,但是您必须创建这样的接口Searchable

    interface Searchable {
        Optional<Integer> search();
    }
    

    然后为您想要搜索的所有具体类型创建包装器类。例如:

    public final class SearchableList<T extends Searchable> extends AbstractList<T> implements Searchable {
    
        private final List<T> list;
    
        SearchableList(List<T> list) {
            this.list = list;
        }
    
        // rest omitted
    }
    

    然而,这将是一个非常复杂的混乱局面,我会避免它,宁愿使用instanceof检查

  2. # 2 楼答案

    简短回答:是的,放弃静态多态性,使用instanceof。或者写一个本地循环来完成你的工作

    Java的泛型比C++的模板弱得多。特别是,编译器不会为您生成新的专门化。使用它们所能做的就是对已经通过常规方法定义的类和方法进行更严格的静态类型检查(例如,手工编写或使用工具生成)。正如您所怀疑的,类型擦除是相关的

    对于Java泛型,以下代码:

    static <T> void print(ArrayList<T> arr) {
      T entry= arr.at(0);
      Test.print (entry);
    }
    

    由于类型擦除,始终有效地使用此选项:

    static Object void print(ArrayList<Object> arr) {
      Object entry= arr.at(0);
      Test.print (entry);
    }
    
    <>它不会产生与C++模板相同的专门化。

    您的特定代码不起作用,因为它缺少几个特定的方法,您必须手动提供这些方法。但我想我能看到你想要去的地方。(我假设您希望最终的代码能够处理比List<List<Integer>>更广泛的类型。)使用Java泛型无法得到令人满意的解决方案。(你可以让它工作,但你必须手工编写大量代码,这些模板对你没有帮助。而且会有一些糟糕的边缘情况。)切换到动态类型检查和instanceof;这就是Java做这件事的方式