你能把一个int数组传递给java中的泛型方法吗?

时间:2009-04-25 07:13:39

标签: java generics

我正在玩一些代码katas并尝试同时更好地理解java泛型。我有这个小方法打印数组,就像我喜欢看到它们一样,我有几个辅助方法接受一个'事物'数组和一个索引,并返回索引上方或下方的“事物”数组(这是一个二进制搜索算法)。

两个问题,

#1我可以避免在splitBottom和splitTop中转换为T吗?它感觉不对,或者我以错误的方式解决这个问题(不要告诉我使用python或其他东西......;)

#2我是否必须编写单独的方法来处理原始数组,还是有更好的解决方案?

public class Util {

    public static <T> void print(T[] array) {
        System.out.print("{");
        for (int i = 0; i < array.length; i++) {
            System.out.print(array[i]);
            if (i < array.length - 1) {
                System.out.print(", ");
            }
        }
        System.out.println("}");
    }

    public static <T> T[] splitTop(T[] array, int index) {
        Object[] result = new Object[array.length - index - 1];
        System.arraycopy(array, index + 1, result, 0, result.length);
        return (T[]) result;
    }

    public static <T> T[] splitBottom(T[] array, int index) {
        Object[] result = new Object[index];
        System.arraycopy(array, 0, result, 0, index);
        return (T[]) result;
    }

    public static void main(String[] args) {

        Integer[] integerArray = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
        print(integerArray);
        print(splitBottom(integerArray, 3));
        print(splitTop(integerArray, 3));

        String[] stringArray = {"one", "two", "three", "four", "five", "six", "seven", "eight", "nine", "ten"};
        print(stringArray);
        print(splitBottom(stringArray, 3));
        print(splitTop(stringArray, 3));

        int[] intArray = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
        // ???
    }
}

6 个答案:

答案 0 :(得分:9)

泛型不能以一致的方式处理基元。这是因为泛型不像C ++中的模板,它只是单个类的编译时添加。

编译泛型时,最终会将上面示例中的Object []作为实现类型。作为int []和byte []等,不要扩展Object []你不能互换地使用它们,即使所涉及的代码是相同的(再次泛型不是模板)

唯一的类int []和Object []共享是Object。您可以将上述方法Object作为类型编写(请参阅System.arraycopy,Array.getLength,Array.get,Array.set)

答案 1 :(得分:3)

  

1我可以避免在splitBottom和splitTop中转换为T吗?它没有   感觉正确,或者我正在谈论这个   错误的方式(不要告诉我使用   python或者其他东西..;))

你不仅可以避免它,而且你不应该这样做。在Java中,不同类型的数组实际上是不同的运行时类型。创建为Object[]的数组无法分配给AnythingElse []的变量。那里的强制转换不会立即失败,因为在泛型中类型T被删除,但是当代码尝试将它用作Something []时,它将抛出ClassCastException,但是它没有。但是它不是。

解决方案是使用Java 6及更高版本中的Arrays.copyOf...方法,或者如果您使用的是早期版本的Java,请使用Reflection创建正确的数组类型。例如,

T [] result =(T [])Array.newInstance(array.getClass()。getComponentType(),size);

  

2我是否必须编写单独的方法来处理原始数组或者是   有更好的解决方案吗?

最好编写单独的方法。在Java中,基本类型的数组与引用类型的数组完全分开;并且没有很好的方法可以同时使用它们。

可以使用Reflection同时处理两者。反射具有Array.get()Array.set()方法,可用于原始数组和引用数组。但是,这样做会失去类型安全性,因为原始数组和引用数组的唯一超类型是Object

答案 2 :(得分:1)

问题1: 转换数组不像您期望的那样工作。 String是一个Object,但String数组不是Object数组。

尝试使用以下内容:

public static <T> T[] splitTop(T[] array, int index) {
    T[] result = Arrays.copyOfRange(array, index + 1, array.length);
    return result;
}

问题2: 对于基元数组,我的功能显然也不起作用。它没有优雅的解决方案 - 例如,查看Arrays库,它为每个基本数组类型提供了几个基本相同的方法副本。

答案 3 :(得分:1)

Java不允许以类型安全的方式构造通用数组。请改用通用序列类型(例如java.util.List)。

以下是我使用通用容器类fj.data.Stream编写测试程序的方法:

import fj.data.Stream;
import static fj.data.Stream.range;

// ...

public int[] intArray(Stream<Integer> s) {
  return s.toArray(Integer.class).array()
}

public static void main(String[] args) {
  Stream<Integer> integerStream = range(1, 10);
  print(intArray(integerStream));
  print(intArray(integerStream.take(3)));
  print(intArray(integerStream.drop(3)));

  // ...
}

答案 4 :(得分:0)

你想要完成的任务有两个问题。

首先,您正在尝试使用原始类型,这些类型实际上并不从Object继承。这会弄乱事情。如果你真的需要这样做,请明确使用Integer而不是int等。

第二个也是更大的问题是Java泛型有类型擦除。这意味着在运行时,您实际上无法引用泛型的类型。这样做是为了让你能够混合泛型支持代码和非通用支持代码,并最终(恕我直言)成为Java开发人员头痛的主要来源,并且证明了泛型应该从第1天开始使用Java。我建议你阅读tutorial中关于它的部分,它将使这个问题更加清晰。

答案 5 :(得分:0)

您可能需要将基元包装到相应的集合中。

我还建议您查看Trove原始集合(http://trove.starlight-systems.com)。这与您的泛型问题无关,但可能非常有趣。