The simple answer to your question is that an int
is a basic data type (or primitive), and an object cannot be converted into a basic data type automatically unless it is a wrapper class that is wrapping that particular basic data type. In this case the wrapper class is Integer. Based on your goal of making a queue, converting item
to an int is not what you want, instead you want to use an array that can hold item
in it rather than int
.
The code content[size] = item;
says to assign the size
cell of content
to the value of item
. If item
is not an Integer
then this will fail. Since, at compile time, the type of item
is ambiguous this will fail. You can solve this problem by replacing your int array with an Object
array, since every class in java has Object
as a parent or ancestor.
A more verbose answer follows:
I think that your question could be rephrased like this:
"I created a queue implementation for the primitive type int, but I'm not sure how to use generics so that the queue can use generics.
Here is the original integer queue implementation with just the add method (working code):
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++;
}
}
Here is the modified queue implementation with just the add method to use Generics:
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++;
}
}
This gives the error
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
For some reason, just using a generic method header didn't make the code work. What am I missing?"
Answer:
There are a few of things that you are missing. First, your add method shouldn't be static, otherwise you will always only have one list.
So:
public static <E> void add(E item) {
should be:
public void add(E item) {
Second, you have two arrays called content
, one that is the field content, and one that is a local variable inside of add
. The local variable should be removed from your code so that it doesn't mask the field. Similarly, you have a local variable for size
that should be removed from your add method.
So:
public static <E> void add(E item) {
int size = 0;
int[] content;
should become:
public void add(E item) {
You are missing the changes to your code that expect your data to be an int.
When generalizing your code, you need to think about what part of the code that is being generalized. In this case, you want to make a list that will work for any one type of data. Your initial list used an array of integers to hold the data, so that array of integers will need to be changed to an array of any type, i.e. your generic symbol. In your case E. That means that all cases of code that have an integer array should be converted to code that has an E array. The only exception to this is for the instantiation of an array, since you can't use a Generic to instantiate an array, instead you need to use Object.
The parts that use the int array are:
private int[] content = new int[initialCapacity];
int[] newArray = new int[content.length * 2];
These can be changed as follows:
private E[] content = new Object[initialCapacity];
E[] newArray = new Object[content.length * 2];
You may be asking what the difference between making a list of Object
vs. a list of generic type. Since Object
is a parent of all class types, a list of Object
could hold data of different types of objects such as Integers and Strings, while a generic list will have to choose one type of object, and all objects will have to be of that type. Having this kind of guarantee makes it easier to use the list because you don't have to check the type of the item in the list before using it.