From: Lew on 6 Jun 2010 13:38 Tom Anderson wrote: >> See: >> >> http://java.sun.com/docs/books/jls/third_edition/html/typesValues.html#110257 Kevin McMurtrie wrote: >> >> tom Don't quote sigs. > Java sometimes adds a non-generics method like this: When you say "Java ... adds", do you mean in the java[x].* packages? > public void add (Object foo) > { > add((SomeClass)foo); > } Can you give an example from the API? > It can lead to ClassCastException on nonexistent lines. What do you mean? -- Lew
From: Joshua Cranmer on 6 Jun 2010 14:19 On 06/06/2010 07:02 AM, Vikram wrote: > Hi, > > In java generics, the following code gives compile time error. > > List<Object> list = new ArrayList<String>(); // compile time error Step back and think for a moment. Since we have a list of Strings, we need to forbid adding a generic Object to the list. Allowing you to cast List<String> to List<Object> would permit a list.add(new Object()), which is clearly not what we want to allow [1]. What we want then is a list of things whose type we don't know--but we can guarantee them to be at least of type Object. The proper type for this is the wildcard List<? extends Object>; the typing rules would then allow you to observe a list.getFirst() as returning Object but prohibit you from adding a plain old Object to that list. > Where as the following does not give any compile time error > > List list = new ArrayList<String>(); It doesn't give an error, but it does give you the unchecked conversion for using a raw type. > If no generics is specified, isin't it implied that it contains > object? What is the reason the second statement does not give any > compile time error? Actually, a raw type is roughly equivalent to List<?> [2]; List<?> is equivalent to List<? extends Object>. [1] The reason that the array analogue allows you to do Object[] o = new String[5]; is because the type of the array is stored, so actually saying o[1] = new Object(); will fail at runtime with an ArrayStoreException. The generic types are not reified in Java [3], so the compiler can't do the same guarantee at runtime that arrays do. [2] A main point of distinction: List.class is of type Class<List>, not Class<List<?>>, and you can't really convert between the two. Even the Java developers admit this is a mistake, but they won't fix it since doing so would break existing code. This has caused me a great deal of frustration... [3] Well, Collections.checkedList (et al.) do actually let you achieve the same runtime storage checking, and it is always possible to make your own wrappers for types you create. But it's not given to your for free by the language, owing mostly to the desire to gain backwards/forwards compatibility and partial library migration. -- Beware of bugs in the above code; I have only proved it correct, not tried it. -- Donald E. Knuth
From: Daniel Pitts on 6 Jun 2010 14:43 On 6/6/2010 4:02 AM, Vikram wrote: > Hi, > > In java generics, the following code gives compile time error. > > List<Object> list = new ArrayList<String>(); // compile time error > > Where as the following does not give any compile time error > > List list = new ArrayList<String>(); > > > If no generics is specified, isin't it implied that it contains > object? What is the reason the second statement does not give any > compile time error? List<? extends Object> list = new ArrayList<String>(); // compiles fine The difference between all three: List<Object> list = new ArrayList<String>(); This says "A reference to List which can have any type of Objects added and retrieved is assigned a List which can only have Strings added and retrieved " List list = new ArrayList<String>(); This says "A reference to a List which is of a Raw type, is assigned a List which can only have Strings added and retrieved. " The raw type remains as a backward compatibility in Java, and should not be used in new code if possible. List<? extends Object> list = new ArrayList<String>(); This says "A reference to a List which can have any Object retrieved, but only objects of an unknown type can be added, is assigned a List which can only have Strings added and retrieved. " -- Daniel Pitts' Tech Blog: <http://virtualinfinity.net/wordpress/>
From: markspace on 6 Jun 2010 20:38 Daniel Pitts wrote: > List<? extends Object> list = new ArrayList<String>(); // compiles fine > List<? extends Object> list = new ArrayList<String>(); > This says "A reference to a List which can have any Object retrieved, > but only objects of an unknown type can be added, is assigned a List > which can only have Strings added and retrieved. " Small note: Since Object is the upper bound of all objects, <? extends Object is the same as just <?>: List<?> list = new ArrayList<String>(); And of course for either both <?> and <? extends Object>, any generic type on the right hand side is compatible and can be assigned. Also, "only objects of an unknown type can be added" isn't quite correct. Since the type is unknown, you can't add any types, period. (Except possibly null, I'd have to check.) You can only remove Objects.
From: Kevin McMurtrie on 7 Jun 2010 02:11 In article <hugmeo$5cm$1(a)news.albasani.net>, Lew <noone(a)lewscanon.com> wrote: > Tom Anderson wrote: > >> See: > >> > >> http://java.sun.com/docs/books/jls/third_edition/html/typesValues.html#1102 > >> 57 > > Kevin McMurtrie wrote: > >> > >> tom > > Don't quote sigs. > > > Java sometimes adds a non-generics method like this: > > When you say "Java ... adds", do you mean in the java[x].* packages? > > > public void add (Object foo) > > { > > add((SomeClass)foo); > > } > > Can you give an example from the API? > > > It can lead to ClassCastException on nonexistent lines. > > What do you mean? Doh! I accidentally sent before I finished. Generics can break inheritance. For example, the generics declaration below demands that an override of put() take only a String as the key. At the same time, HashMap without generics must take an Object as a key. The compiler fixes this by adding a hidden method. This compiles with a warning: public class SnoopingMap<V> extends java.util.HashMap<String, V> { @Override public V put(String key, V value) { System.out.println(key + " -> " + value); return super.put(key, value); } public static void main (String args[]) { SnoopingMap m= new SnoopingMap(); m.put(new Integer(4), new Integer(5)); } } But fails to run with an error on a bogus line number: Exception in thread "main" java.lang.ClassCastException: java.lang.Integer cannot be cast to java.lang.String at SnoopingMap.put(SnoopingMap.java:1) at SnoopingMap.main(SnoopingMap.java:13) The javap utility shows the hidden method: public java.lang.Object put(java.lang.Object, java.lang.Object); Signature: (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; Code: 0: aload_0 1: aload_1 2: checkcast #16; //class java/lang/String 5: aload_2 6: invokevirtual #17; //Method put:(Ljava/lang/String;Ljava/lang/Object;)Ljava/lang/Object; 9: areturn LineNumberTable: line 1: 0 That translates to this code, which will not compile if you add it yourself: public Object put(Object key, Object value) { return put((String)key, value); { -- I won't see Google Groups replies because I must filter them as spam
First
|
Prev
|
Next
|
Last
Pages: 1 2 3 Prev: logging into site using form validation http components Next: documentation versus contract |