在泛型之前一直使用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;
说将content
的size
单元格分配给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
列表可以保存不同类型的对象(如整数和字符串(的数据,而泛型列表必须选择一种类型的对象,并且所有对象都必须属于该类型。具有这种保证可以更轻松地使用列表,因为您不必在使用列表之前检查列表中的项目类型。