Prev: Putting passwords in a properties file?
Next: Interview
From: Lew on 7 Oct 2009 07:59 Roedy Green wrote: > & is used where you would expect to use comma. extends is used where > you would expect to use implements. super does not mean super. I assume you're talking about something like public class Foo <T extends Collection<?> & Comparable<? super T>> I don't know why you would expect a comma where '&' is used - that would be incredibly ambiguous. Commas between type parameters represent different type parameters, i.e., where more than one type is specified: Map <T extends Foo, U extends Bar> Replacing '&' in intersection types (and doesn't '&' communicate the idea of "intersection" just perfectly?) with a comma would conflict with that usage. Why would "implements" be better than "extends"? The supertype doesn't have to be an interface. The idea of "extension" is much more natural for type analysis than "implementation". Really, "implementation" is not at all a natural concept for type analysis. And how does "super" not mean super? The type that is "super" ('?' in the example here) is a supertype; using "super" as the keyword seems entirely natural. And why are we bitching about this five-year-old syntax anyway? It's a done deal. Java already has generics defined the way Java already has generics defined. It will be far, far more productive to learn the syntax than to try to change it. Especially if the proposed changes are far, far less sensible than the status quo. -- Lew
From: Thomas Pornin on 7 Oct 2009 08:48 According to Roedy Green <see_website(a)mindprod.com.invalid>: > It just bugs me that specifying the contents of a container should be > any more complicated that specifying the contents of an array. Arrays in Java are simple because they have a special feature which generics-enhanced collections do not: arrays know their element type. When you create a String[], the array instance knows that it contains String instances and nothing else. This allows subtyping between array types. For instance, consider the following: String[] a = new String[10]; Object[] b = a; b[0] = new Integer(42); this code snippet compiles; in particular, the contents of 'a' are silently converted to 'Object[]'. The third line also compiles finely (an Integer is certainly an Object, and storing an Object reference into an array of Object references looks fine on the face of it). Upon execution, of course, the third line triggers an ArrayStoreException because the array is really an array of String, not just any Object, and the instance knows it. The store operation entails a dynamic type check. Now, try to replace this with a List: List<String> a = new ArrayList<String>(); List<Object> b = a; b.set(0, new Integer(42)); this code snippet does not compile: the contents of 'a' cannot be silently converted to the 'List<Object>' type. Why so ? Because the list instance does NOT know it element type. Generics work by so-called 'type erasure' which means that at the bytecode+JVM level, the instance knows that it is 'an ArrayList', not 'an ArrayList of String'. Consequently, the storage of an Integer into the list (in the third line) cannot trigger an appropriate runtime exception: the list cannot enforce the rule that it shall contain only String instances because it has no way to know that it shall contain only String instances. Because of that, the compiler cannot allow the silent conversion of a List<String> into a List<Object>. You can bypass the compiler by using a naked List type: List<String> a = new ArrayList<String>(); List b = a; b.set(0, new Integer(42)); System.out.println(a.get(0).length()); this code snippet compiles with a warning ('uses unchecked or unsafe operations') because the compiler cannot ensure anymore that the container invariant (the list contains only String instances) is maintained. At runtime, the third line is executed without any problem, but this breaks the invariant: the list now contains an 'Integer'. This problem is illustrated by the fourth line: the 'get(0)' method is called on 'a', which is a List<String>, hence it is quite natural to expect, from the caller point of view, that a String instance is obtained, and calling length() on a String instance should be no problem. However, this triggers a ClassCastException. You cannot escape the JVM type system, but here the runtime type check can be applied only when getting values out of the list (the caller knows the type to expect, but the list itself does not). I am quite sure that you already know all this, but I wrote it to stress my point: container types are intrinsically messy and complex, i.e. they do not allow subtyping. This is a generic property which is not limited to Java. To cope with containers in a context of subtyping, a language type system must include some way to handle _partial_ information on the contained type, which implies the whole armada of bounded wildcards. But for Java arrays, the designers of Java thought that such complexity ought to be avoided, and they could avoid it, by adding a runtime type check upon storage. That check allows the use of arrays in much simpler ways, with seemless integration in the Java type system. To sum up, it is not that collections-with-generics are overly complex. It is that Java arrays are overly simple, through the use of a trick which needs some quite extensive support from the JVM: the JVM has to know the arrays as being special entities, must have special access opcodes, and must integrate the array types special properties into the bytecode verification phase. This trickery made you believe that interactions of types with containers are inherently simple, and that is simply not the case. > There does not seem to be sufficient benefit to justify all the fuss. The benefits here are backward compatiblity: generics could be introduced into the language while requiring only very limited extra support from the JVM. In a way, if you want Java without the fuss implied by backward compatibility, use C#. --Thomas Pornin
From: Tom Anderson on 7 Oct 2009 17:10 On Tue, 6 Oct 2009, Lew wrote: > Arne Vajh?j wrote: >> Lew wrote: >>> Arne Vajh?j wrote: >>>> <T> is new syntax. Just not new keywords. And it definitely added >>>> complexity - just consider how many questions are asked about it here. >>> >>> It is most assuredly not new syntax. The Java version that introduced it >>> hits end-of-service-life in less than four weeks. It was introduced over >>> five years ago. In what IT context is five years considered "new"? >> >> It was new syntax when it was added. > > So was the "assert" keyword. So were anonymous classes. Heck, the Java > language itself was new when it first came out. Come on. You should write to these chaps and complain about their name: http://www.new.ox.ac.uk/ tom -- Model 706-8073-421, Robot Sonic
From: Patricia Shanahan on 7 Oct 2009 18:07 Tom Anderson wrote: > On Wed, 7 Oct 2009, Lew wrote: > >> Roedy Green wrote: >>> & is used where you would expect to use comma. extends is used where >>> you would expect to use implements. super does not mean super. >> >> Why would "implements" be better than "extends"? The supertype >> doesn't have to be an interface. The idea of "extension" is much more >> natural for type analysis than "implementation". > > The supertype also doesn't have to be a class. This: > > List<? extends Runnable> > > Is unnatural. The "?" can represent either a class that implements Runnable or an interface that extends it. There are a total of three cases, class extends class, interface extends interface, and class implements interface. "extends" is appropriate for two of the cases, and the same keyword has to handle class implements interface and interface extends interface, so I think "extends" is the less bad choice. Perhaps it was a mistake to use a special keyword for introducing an interface in a class declaration. If the superclass and all interfaces had been introduced by "extends" the problem would not exist. >> And how does "super" not mean super? The type that is "super" ('?' in >> the example here) is a supertype; using "super" as the keyword seems >> entirely natural. > > Before generics, super meant exactly one thing: "the method with this > signature in the parent class of the class in which the current method > is defined". That's completely unrelated to it use in generics. In the first statement of a constructor, "super" introduces the superclass constructor parameter list. It has never had only one meaning. In general, Java has gone with a strategy of a short list of reserved words, recycling them to deal with several related concepts whenever possible in preference to adding new ones. The most extreme case of this is "static". Patricia
From: Tom Anderson on 7 Oct 2009 19:29
On Wed, 7 Oct 2009, Patricia Shanahan wrote: > Tom Anderson wrote: >> On Wed, 7 Oct 2009, Lew wrote: >> >>> Roedy Green wrote: >>>> & is used where you would expect to use comma. extends is used where >>>> you would expect to use implements. super does not mean super. >>> >>> Why would "implements" be better than "extends"? The supertype doesn't >>> have to be an interface. The idea of "extension" is much more natural for >>> type analysis than "implementation". >> >> The supertype also doesn't have to be a class. This: >> >> List<? extends Runnable> >> >> Is unnatural. > > The "?" can represent either a class that implements Runnable or an > interface that extends it. There are a total of three cases, class > extends class, interface extends interface, and class implements > interface. "extends" is appropriate for two of the cases, and the same > keyword has to handle class implements interface and interface extends > interface, so I think "extends" is the less bad choice. Absolutely. It's still counterintuitive. Anyway, why only have one keyword there? Why not allow either "extends" or "implements" there, with the same meaning? > Perhaps it was a mistake to use a special keyword for introducing an > interface in a class declaration. If the superclass and all interfaces > had been introduced by "extends" the problem would not exist. Hey, we could just have used a colon. >>> And how does "super" not mean super? The type that is "super" ('?' in the >>> example here) is a supertype; using "super" as the keyword seems entirely >>> natural. >> >> Before generics, super meant exactly one thing: "the method with this >> signature in the parent class of the class in which the current method is >> defined". That's completely unrelated to it use in generics. > > In the first statement of a constructor, "super" introduces the > superclass constructor parameter list. It has never had only one meaning. That's a call to the constructor with the given signature in the parent class of the class in which the current method is defined. It has exactly the same meaning as when used to make a super method call. > In general, Java has gone with a strategy of a short list of reserved > words, recycling them to deal with several related concepts whenever > possible in preference to adding new ones. The most extreme case of this > is "static". Is it? Doesn't that just mean a feature lives in the class rather than the instance? I'd nominate "final" for most overloaded, i think. tom -- This is the best kind of weird. It can make a corpse laugh back to death. -- feedmepaper |