无法使用 Java 泛型将 int 类型转换为 E



在泛型之前一直使用Java做得很好。我很难将此队列转换为使用接受任何数据类型的泛型。

我不明白为什么当item应该表示"任何"数据类型时item不能转换为int

答案加上对泛型的一些解释会很有用,因为我还需要创建一个 remove 函数。

private int initialCapacity = 10;
private int size = 0;
private int[] content;
public static <E> void add(E item) {
    int size = 0;
    int[] content;
    // If we run out of space in the array
    if (size == content.length) {
        // 1) Create a new, larger array (2x)
        int[] newArray = new int[content.length * 2];
        // 2) Copy the content from the old array to the new one
        for (int c = 0; c < content.length; c++) {
            newArray[c] = content[c];
        }
        // 3) Let the old array point to the new array
        content = newArray;
    }
    //Add the item to the content of the array list
    content[size] = item;
    size++;
}

让我们从顶部开始。 E是一个类型参数,所以我们应该首先弄清楚它的范围。通常,对于队列,type 参数适用于整个队列(而不仅仅是单个add(操作,因为我们希望队列具有一致的类型。因此,首先将您的类声明为:

public class YourQueue<E> {
    ...
}

并从方法声明中删除<E> add ,使其public void add(E item)。不知道为什么你声明它是静态的,因为它应该添加到给定的队列中。

第三,如果你要使用数组来存储YourQueue<E>的元素,它不应该是一个整数数组,因为所有类型的对象都不能转换为整数。它应该是一个声明为 E[] 的数组。

在 Java 中,泛型不支持基元类型。只需使用 Integer 而不是 int ,对于您的应用程序,它大多是相同的。

也请看这里:为什么Java泛型不支持基元类型?

对你的问题的简单回答是,int是一种基本数据类型(或基元(,除非对象是包装该特定基本数据类型的包装类,否则它不能自动转换为基本数据类型。在本例中,包装类为 Integer。根据您创建队列的目标,将item转换为 int 不是您想要的,而是您希望使用一个可以在其中容纳item的数组,而不是 int

代码content[size] = item;说将contentsize单元格分配给item的值。如果item不是Integer那么这将失败。由于在编译时,item的类型不明确,因此将失败。你可以通过将 int 数组替换为 Object 数组来解决这个问题,因为 java 中的每个类都有 Object 作为父类或祖先。

一个更冗长的答案如下:

我认为您的问题可以这样改写:


"我为基元类型int创建了一个队列实现,但我不确定如何使用泛型以使队列可以使用泛型。

这是仅使用 add 方法(工作代码(的原始整数队列实现:

public class IntQueue {
   private int initialCapacity = 10;
   private int size = 0;
   private int[] content = new int[initialCapacity];
   public void add(int item) {
      // If we run out of space in the array
      if (size == content.length) {
          // 1) Create a new, larger array (2x)
          int[] newArray = new int[content.length * 2];
          // 2) Copy the content from the old array to the new one
          for (int c = 0; c < content.length; c++) {
              newArray[c] = content[c];
          }
          // 3) Let the old array point to the new array
          content = newArray;
      }
      //Add the item to the content of the array list
      content[size] = item;
      size++;
   } 
}

下面是修改后的队列实现,仅使用 add 方法来使用泛型:

public class GenericQueue<E> {
   private int initialCapacity = 10;
   private int size = 0;
   private int[] content = new int[initialCapacity];
   public static <E> void add(E item) {
      int size = 0;
      int[] content;
      // If we run out of space in the array
      if (size == content.length) {
          // 1) Create a new, larger array (2x)
          int[] newArray = new int[content.length * 2];
          // 2) Copy the content from the old array to the new one
          for (int c = 0; c < content.length; c++) {
              newArray[c] = content[c];
          }
          // 3) Let the old array point to the new array
          content = newArray;
      }
      //Add the item to the content of the array list
      content[size] = item;
      size++;
   } 
}

这给出了错误

GenericQueue.java:26: error: incompatible types: E cannot be converted to int
      content[size] = item;
                      ^
  where E is a type-variable:
    E extends Object declared in method <E>add(E)
1 error

出于某种原因,仅使用泛型方法标头并不能使代码正常工作。我错过了什么?


答:

您缺少一些东西。首先,add 方法不应是静态的,否则将始终只有一个列表。

所以:

   public static <E> void add(E item) {

应该是:

   public void add(E item) {

其次,您有两个称为 content 的数组,一个是字段内容,另一个是 add 内部的局部变量。应从代码中删除局部变量,以便它不会屏蔽字段。同样,您有一个size的局部变量,应从 add 方法中删除该变量。

所以:

   public static <E> void add(E item) {
      int size = 0;
      int[] content;

应该变成:

   public void add(E item) {

您缺少对代码的更改,这些更改期望您的数据是整数。泛化代码时,需要考虑要泛化代码的哪一部分。在这种情况下,您希望创建一个适用于任何一种数据类型的列表。您的初始列表使用整数数组来保存数据,因此整数数组需要更改为任何类型的数组,即您的通用符号。在您的案例中 E.这意味着所有具有整数数组的代码都应转换为具有 E 数组的代码。唯一的例外是数组的实例化,因为您不能使用 Generic 来实例化数组,而是需要使用 Object。

使用 int 数组的部分是:

private int[] content = new int[initialCapacity];
int[] newArray = new int[content.length * 2];

可以按如下方式更改这些内容:

private E[] content = new Object[initialCapacity];
E[] newArray = new Object[content.length * 2];

您可能会问,创建Object列表与泛型类型列表之间有什么区别。由于Object是所有类类型的父类,因此Object列表可以保存不同类型的对象(如整数和字符串(的数据,而泛型列表必须选择一种类型的对象,并且所有对象都必须属于该类型。具有这种保证可以更轻松地使用列表,因为您不必在使用列表之前检查列表中的项目类型。

最新更新