How do I insert elements of different data types into a single stack in Java?
It seems to defeat the purpose of generics, but here it goes:
Stack<Object>s = new Stack<Object>();
s.add("hello");
s.add(1); // int is autoboxed to Integer
The catch will be that when retrieving the Object
s from the Stack
, it's going to take some effort to find out what type of each element is -- it will require using instanceof
and typecasts:
while (!s.isEmpty()) {
Object e = s.pop();
if (e instanceof String)
System.out.println("String: " + (String)e);
else if (e instanceof Integer)
System.out.println("Integer: " + (Integer)e);
else
System.out.println("Other type: " + e);
}
And now, we have something resembling the fragile code of the pre-Java 5 days before generics was added to the language.
Generally, you'll want to solve this using inheritance. Possibly using a marker interface:
interface MyMarker
{
}
class Foo implements MyMarker
{
}
class Bar implements MyMarker
{
}
Interfaces are practical in cases like this, because you can implement an unlimited number of interfaces in a single class, and you can add extra interfaces anywhere in the class hierchy.
You can then put Foo and Bar in the same stack:
Stack<MyMarker> s = new Stack<MyMarker>();
s.add(new Foo());
s.add(new Bar());
This is the way to go if it's at all possible. Otherwise you'll have to do it like coobird suggests.
The generic argument of the stack should be a common super type of all the element runtime types. For completely heterogeneous collections, Object
is the common super type of all reference types. So:
Queue<Object> stack = Collections.asLifoQueue(new ArrayDeque<Object>());
stack.add("red");
stack.add(Color.GREEN);
stack.add(stack);
Obviously you when you come to pop those elements off the stack you will need to do instanceof
checking to route to appropriate code (and probably cast).
Probably better is to introduce a layer of indirection. Instead of putting the objects on the queue directly, wrap them in a meaningful object. The instanceof
checks can all be replace by calls to (virtual) methods that perform the operations you require. This is how polymorphism is supposed to be.