5

I have an Object that sometimes contains a List<Object>. I want to check it with instanceof, and if it is, then add some elements to it.

void add(Object toAdd) {
    Object obj = getValue();
    if (obj instanceof List<?>) {
        List<?> list = obj;
        if (list instanceof List<Object>) {    // Error
            ((List<Object>) list).add(toAdd);
        } else {
            List<Object> newList = new ArrayList<Object>(list);
            newList.add(toAdd);
            setValue(newList);
        }
        return;
    }
    throw new SomeException();
}

And it says I can't check if it is instanceof List<Object> because java doesn't care and erased the type in <>. Does this mean I have to create new ArrayList every time? Or is there a way to check that, eg. with reflection?

Wolf480pl
  • 53
  • 1
  • 1
  • 5
  • 2
    What the heck is this piece of code supposed to do? – poitroae Feb 03 '13 at 15:41
  • 2
    It is known as Type erasure in Java http://stackoverflow.com/questions/339699/java-generics-type-erasure-when-and-what-happens – Jiri Kremser Feb 03 '13 at 15:43
  • @Michael this is going to be a wrapper around snakeyaml. If I have a list in yaml, it will parse it to some list in Java. If I want to add an element to this list, I need to know what type of list it is. That's why I make a new ArrayList of known type and add all the old elements to it, plus one new. Then I replace the old list with the new one, and when I call snakeyaml to convert it back to yaml, my added element will be there. – Wolf480pl Feb 03 '13 at 15:55
  • 1
    @Wolf480pl: "If I want to add an element to this list, I need to know what type of list it is." No you don't. How does snakeyaml "know what type of list it is"? As long as snakeyaml doesn't care what you put in there, it doesn't matter. – newacct Feb 03 '13 at 22:02
  • @newacct Lol, I've just noticed I can cast a list to any List and add to it and it won't throw anything. – Wolf480pl Feb 04 '13 at 12:51

1 Answers1

4

I was wrong in my previous answer since i not fully understood your requirements. if your added item is an Object you may add it without any problem as long as you Have a list of something. You don't have to recreate the list

void add(Object toAdd) {
    Object obj = getObject();
    if (obj instanceof List<?>) {
        ((List<Object>)obj).add(toAdd);
        return;
    }
    throw new SomeException();
}

UPDATE

as answer to few comments, there is no problem to add any object to a list, and there is no problem to find out what type of object it is during iteration after it:

List<String> x1 = new ArrayList<String>();
Object c3 = x1;
x1.add("asdsad");
Integer y2 = new Integer(5);
if (c3 instanceof List<?>){
     ((List<Object>)c3).add((Object)y2);
}

for (Object i : (List<Object>)c3){
    if (i instanceof String){
        System.out.println("String: " + (String)i);
    }
    if (i instanceof Integer){
        System.out.println("Integer: "+ (Integer)i);
    }
}
Michael
  • 2,677
  • 3
  • 26
  • 47
  • I want to make sure the parameter is not a subclass of Object. Will getActualTypeArguments() == Object.class work? – Wolf480pl Feb 03 '13 at 16:03
  • Also, is this going to be faster than copying a <50 elements ArrayList? – Wolf480pl Feb 03 '13 at 16:09
  • 1
    This is completely wrong. This is only for if the object's class is a subclass of ArrayList or something, and which extends it with a specific type parameter. None of which is what the OP is doing. – newacct Feb 03 '13 at 21:59
  • @newacct, you are right and the answer have been edited, the answer was written before the question has been edited and explained more clearly, as regard to the subclass of ArrayList, you are also right, my mistake as i had time shortage. Although the hint for knowing the type of contained object through reflection and ParameterizedType is valuable. – Michael Feb 03 '13 at 22:33
  • -1 Your edit is still wrong. A `List>` is *not* necessarily a `List`. – Paul Bellora Feb 04 '13 at 00:50
  • @Paul Bellora, List> is necessarily a List of Objects, you can't create a List of primitives, give it a try.. everything else is Object – Michael Feb 04 '13 at 08:55
  • A `List>` could be a `List` and an `Object` could be an `Integer`. In this case you've added an `Integer` to a `List` via an unchecked cast so it will only fail sometime later when the `Integer` is accessed like a `String`. Since the OP is assuming any `List>` must be a `List` (I guess because of snakeyaml), you should change your answer to reflect that. "if your added item is an Object you may add it without any problem as long as you Have a list of something" is wrong. – Paul Bellora Feb 04 '13 at 13:43
  • @Paul Bellora, the answer was edited to demonstrate to you how it will be easily accessed after it without any problem , it works! and a list of something is exactly the same as a list of object , there is no mistake here, OP has meant that its List can hold different object types – Michael Feb 04 '13 at 13:55