For example, can I create List that will contain String and other List? And if I can do that, what is the specific of my List? I can just say that it contains data of type Object, right?
-
1Collection<?> (docs.oracle.com/javase/tutorial/extra/generics/wildcards.html)CodeFanatic– CodeFanatic2014-08-17 19:34:29 +00:00Commented Aug 17, 2014 at 19:34
-
Could you please clarify? I do not understand what you want to achieve.Gábor Bakos– Gábor Bakos2014-08-17 19:35:27 +00:00Commented Aug 17, 2014 at 19:35
-
If you dont what type is it then youll get yourself in trouble when getting the objects out from the listRod_Algonquin– Rod_Algonquin2014-08-17 19:37:02 +00:00Commented Aug 17, 2014 at 19:37
-
Folks tell you it can't be done because they figure you're brain dead and can't somehow work out what kind of object you have when you get it out of the collection. It simply requires programming.Hot Licks– Hot Licks2014-08-17 19:51:12 +00:00Commented Aug 17, 2014 at 19:51
Add a comment
|
3 Answers
Yes, you can use:
List<Object> list = new ArrayList<>();
list.add("A string");
list.add(new ArrayList<Foo>());
// etc
It's usually not a good idea, as when you get items out of the list, it can be a pain to work out what you need to do with them. If you can design your way out of that, it would be a good idea... but the above will work.
3 Comments
Hot Licks
Of course, folks managed using Java quite well for about 10 years without generics, where every collection object was a collection of
Object.David Tonhofer
And dynamically typed languages like Groovy resolutly prefer that you leave the generics out (though you can write them for the sake of documentation)
Jon Skeet
@HotLicks: Yes, but then in most cases you'd still have a logically single-type collection. Most of the time you'd just unconditionally cast after calling
get.Type-safe heterogeneous collections, without a language that supports sum types, gets pretty hairy. Here's an example of a list containing both String and int.
import java.util.ArrayList;
import java.util.List;
public class Foo {
public static void main(String[] args) {
// Construct the list by wrapping the elements in StringOrInt
List<StringOrInt> list = new ArrayList<>();
list.add(StringOrInt.apply("abc"));
list.add(StringOrInt.apply(4));
// Use the elements by applying a StringOrInt.Visitor.
List<String> list2 = new ArrayList<>();
for (StringOrInt x : list) {
list2.add(x.apply(new StringOrInt.Visitor<String>() {
public String caseString(String x) { return "String: " + x; }
public String caseInt(int x) { return "Int: " + x; }
}));
}
System.out.println(list2); // [String: abc, Int: 4]
}
}
abstract class StringOrInt {
interface Visitor<A> {
A caseString(String x);
A caseInt(int x);
}
private StringOrInt() {}
abstract <A> A apply(Visitor<A> visitor);
static StringOrInt apply(String x) { return new String_(x); }
static StringOrInt apply(int x) { return new Int_(x); }
private static final class String_ extends StringOrInt {
final String x;
String_(String x) { this.x = x; }
<A> A apply(Visitor<A> visitor) { return visitor.caseString(x); }
}
private static final class Int_ extends StringOrInt {
final int x;
Int_(int x) { this.x = x; }
<A> A apply(Visitor<A> visitor) { return visitor.caseInt(x); }
}
}
1 Comment
David Tonhofer
Pretty nice, but I doubt this is worth the trouble.
Enjoy a test case
import java.util.LinkedList;
import java.util.List;
import org.junit.Test;
import static org.junit.Assert.*;
public class TestGenerics {
@Test
public void listOfObjects() {
List<Object> objList = new LinkedList<Object>();
objList.add("alphabeta");
objList.add(Integer.valueOf(888));
assertEquals("alphabeta",(String)(objList.get(0)));
assertEquals(888, ((Integer)(objList.get(1))).intValue());
}
@Test
@SuppressWarnings({ "rawtypes", "unchecked" })
public void listOfElementsThatAreSubclassedFromObject() {
List<? extends Object> objList = new LinkedList();
// objList.add("alphabeta"); // WILL NOT COMPILE
objList.add(null); // Only null can be added to this list
}
@Test
@SuppressWarnings({ "rawtypes", "unchecked" })
public void listOfElementsThatHaveSupertypeObject() {
List<? super Object> objList = new LinkedList();
objList.add("alphabeta");
objList.add(Integer.valueOf(888));
assertEquals("alphabeta",(String)(objList.get(0)));
assertEquals(888, ((Integer)(objList.get(1))).intValue());
}
@Test
@SuppressWarnings({ "rawtypes", "unchecked" })
public void rawListIsAlsoNice() {
List objList = new LinkedList();
objList.add("alphabeta");
objList.add(Integer.valueOf(888));
assertEquals("alphabeta",(String)(objList.get(0)));
assertEquals(888, ((Integer)(objList.get(1))).intValue());
}
}