0

I recently finished an online course in AP Computer Science (Java) and on the final exam there was a question that went something like this:

Which of these needs a String cast to use String methods on it:
I. ArrayList a = new ArrayList();
II. ArrayList<Object> b = new ArrayList<Object>();
III. ArrayList<String> c = new ArrayList<String>();

Something about this confused me: can option I ever even be able to be casted? It has no generic definition so, unless the Java compiler defauted to ArrayList<Object>, what class is E then?


This is my test code (the suppress comments are needed because this is an "unchecked" operation):

ArrayList a = new ArrayList();

@SuppressWarnings("unchecked")
a.add(new Object());

@SuppressWarnings("unchecked")
a.add(new String("test"));

@SuppressWarnings("unchecked")
a.add(null);

System.out.println((String)(a.get(0)));  

No matter what is in the arguments for the add() method, it always gives the compiler error:

test.java:14: error: <identifier> expected
        a.add(new Object());
             ^

If I try to add an identifier anywhere on the code (e.g.: a<Object>.add(new Object())) it gives the exact same error as before.

The question is what is actually happening when no parameter is passed to the generics parameter and can anything be added to this list in the first place, let alone cast into another object? Thanks in advance!

lxcky
  • 1,668
  • 2
  • 13
  • 26
  • "Identifier expected" means "syntax error". I don't think this has anything to do with generics. I don't see anything wrong with the code you have however. Please double-check it, and I'll have the IDE up in a second. – markspace Sep 02 '14 at 23:58
  • @markspace I double-checked it. I'm guessing that it wants an object of type E (or at least a subclass of E) and it's not finding it. – portablesounds Sep 03 '14 at 00:02

2 Answers2

1

You have a simple syntax error. @SuppressWarnings can't be used on aribrary statements like a.add(x), only class declarations, method declarations and variable declarations. That's why it asks for an identifier, the @SuppressWarnings is expecting to see one of those three, not a simple statement.

   public static void main(String[] args) {
      ArrayList a = new ArrayList();
      a.add(new Object());
      a.add(new String("test" );
      a.add(null);
      System.out.println((String) (a.get(0)));
   }

The code compiles fine like this.

So what happens when you use a raw type? Nothing. No type checking is done. The above code produces a java.lang.ClassCastException error on the println statement. It doesn't catch that you put an Object in when you meant to put a String, and it doesn't know until runtime that your cast on the println will be bad.

markspace
  • 10,621
  • 3
  • 25
  • 39
0

When it is not specified, it defaults to the bound of the generic, and if that is not specified it is by default object.

This means that :

List lst = new ArrayList();

Is totally equivalent to :

List<Object> lst = new ArrayList<Object>();

On such a list, everything can be added or retrieved, because everything in Java extends Object, except primitives (but then autoboxing comes into play).

So, you can correctly write :

lst.add("String");
lst.add(new Date());
lst.add(new Integer(1));
lst.add(1); // It is converted to an Integer by auto-boxing

And you can correctly write :

String str = (String)lst.get(0);

But you have to be aware of possible runtime cast exceptions :

String str2 = (String)lst.get(1); // Will give error, cause element 1 is a date.

If you have a specific ArrayList subclass that defines a generic bound, like for example :

public class MyList<E extends MyClass> extends ArrayList<E> { 

The you can still use it without generics :

MyList lst = new MyList();

But it will accept only MyClass or subclasses of MyClass :

lst.add(new MyClass());
lst.add(new MySubClass());
MyClass a = lst.get(0);
MyClass b = lst.get(1);
MySubClass c = (MySubClass)lst.get(1);

But nothing else :

lst.add("String"); // Will give compile time error
Simone Gianni
  • 11,426
  • 40
  • 49
  • Hmmm then why isn't the code compiling even though I can't find a thing wrong with the syntax? Also if that's true then I shouldn't have to suppress the "unchecked" error either. – portablesounds Sep 03 '14 at 00:08
  • @markspace answered to why it was not compiling while i was writing the full explanation :) – Simone Gianni Sep 03 '14 at 00:10
  • unchecked is not an error, is just a warning the compiler gives you to let you know that you are using a parametrized class without using generics parameters. – Simone Gianni Sep 03 '14 at 00:32