From vapor1 at teleport.com Fri May 1 00:01:57 2009 From: vapor1 at teleport.com (Derek Foster) Date: Fri, 1 May 2009 03:01:57 -0400 (EDT) Subject: PROPOSAL: Enhanced for each loop iteration control Message-ID: <13546403.1241161317584.JavaMail.root@elwamui-hound.atl.sa.earthlink.net> Catching up on my proposal commenting: While I appreciate what this construct is trying to do, I have to admit that I find the syntax unpalatable. Firstly, I have very rarely needed to call Iterator.delete() in a loop. (I can think of maybe four or five occasions.) As such, it has usually not been a great deal of trouble to just write the loop using an explicit iterator. On the other hand, I much more frequently would like to be able to use an index. However, the proposal seems to assume that if a user wants either an iterator or an index, that the user wants both. In practice, I usually want either one OR the other, but pretty much never both. (For instance, Iterators are good for iterating LinkedLists, and indices are good for ArrayLists, but using the wrong one on a list of any significant size will create a performance problem.) I would much prefer to have a simpler syntax that allowed me to work just with an index or just with an iterator... Actually, I'd be happy if just indices were supported. Something like: Thing[] fooCollection = ...whatever...; String[] results = new String[fooCollection.length]; for (Thing foo : fooCollection) { results[#foo] = foo.toString(); } where "#foo" was defined by the compiler as "the index of foo within the collection it is iterating over". Derek -----Original Message----- >From: Ruslan Shevchenko >Sent: Apr 22, 2009 1:23 AM >To: "Joseph D. Darcy" >Cc: coin-dev at openjdk.java.net >Subject: Re: PROPOSAL: Enhanced for each loop iteration control > >> Catching up on proposal commenting, while I find the design generally >> acceptable, I remain unconvinced that the inability to replace all >> pre-JDK 5 for loops with some newer, improved for loop is a serious >> enough problem to justify further language changes beyond the enhanced >> for loop in JDK 5. >> >> Some data on how often such a new construct would be applicable would >> help here. >> > > Partially it was RemoveInLoop (which count access to remove within while >operator) in >http://mail.openjdk.java.net/pipermail/coin-dev/2009-April/001496.html >Number was quite low (for example 62 in JDK) > >I will try to add count for remove-in-for and index-access during next >iteration in my set of coin syntax-patterns. (during next week-end if we >have no time constraints) > > >> -Joe >> >> Stephen Colebourne wrote: >>> Enhanced for each loop iteration control >>> >>> (re-sent with correct subject line) >>> >>> This proposal extends the for each loop to allow access to meta data >>> including the index and the remove method. >>> >>> (This proposal doesn't really go into enough detail - with JSR-310 my >>> time here is limited. I'd hope that there is just about enough >>> though....) >>> >>> ----------------------------------------------------------------------------------- >>> Enhanced for each loop iteration control >>> >>> AUTHOR(S): >>> Stephen Colebourne >>> >>> *OVERVIEW* >>> >>> FEATURE SUMMARY: >>> Extends the Java 5 for-each loop to allow access to the loop index, >>> whether this is the first or last iteration, and to remove the current >>> item. >>> >>> MAJOR ADVANTAGE: >>> The for-each loop is almost certainly the most new popular feature from >>> Java 5. It works because it increases the abstraction level - instead of >>> having to express the low-level details of how to loop around a list or >>> array (with an index or iterator), the developer simply states that they >>> want to loop and the language takes care of the rest. However, all the >>> benefit is lost as soon as the developer needs to access the index or to >>> remove an item. >>> >>> The original Java 5 for each work took a relatively conservative stance >>> on a number of issues aiming to tackle the 80% case. However, loops are >>> such a common form in coding that the remaining 20% that was not tackled >>> represents a significant body of code. >>> >>> The process of converting the loop back from the for each to be index or >>> iterator based is painful. This is because the old loop style if >>> significantly lower-level, more verbose and less clear. It is also >>> painful as most IDEs don't support this kind of 'de-refactoring'. >>> >>> MAJOR BENEFIT: >>> A common coding idiom is expressed at a higher abstraction than at >>> present. This aids readability and clarity. >>> >>> Accessing the index currently requires using an int based loop, or >>> placing a separate int counter outside the loop (which then remains in >>> scope after the loop). The proposed solution doesn't result in manual >>> manipulation of the index. >>> >>> Accessing the iterator remove requires using an iterator based loop. >>> With generics this is remarkably verbose. The proposed solution is >>> significantly shorter and cleaner. >>> >>> MAJOR DISADVANTAGE: >>> The enhanced for each loop is complicated with additional functionality. >>> (This is mitigated by being easy and obvious to use) >>> >>> More code is generated magically by the compiler. (This is mitigated by >>> a simple desugaring) >>> >>> ALTERNATIVES: >>> Use the existing language constructs, typically the standard for loop. >>> >>> Use BGGA/JCA style closures, with control statements. It should be noted >>> that these are consistently the most controversial parts of the closure >>> debate, making the 'let's wait for closures' argument against this >>> proposal weaker (as any final closures implementation may not include >>> control statements). >>> >>> >>> *EXAMPLES* >>> >>> SIMPLE EXAMPLE: >>> >>> StringBuilder buf = new StringBuilder(); >>> for (String str : list : it) { >>> if (str == null) { >>> it.remove(); >>> } >>> } >>> >>> whereas, today we write: >>> >>> StringBuilder buf = new StringBuilder(); >>> for (Iterator it = list.iterator(); it.hasNext();) { >>> String str = it.next(); >>> if (str == null) { >>> it.remove(); >>> } >>> } >>> >>> ADVANCED EXAMPLE: >>> >>> Example1: >>> >>> for (String str : list : it) { >>> System.out.println("Row " + it.index() + " has the value " + str); >>> } >>> >>> whereas, today we might write: >>> >>> int index = 0; >>> for (String str : list) { >>> System.out.println("Row " + index + " has the value " + str); >>> index++; >>> } >>> >>> or >>> >>> for (int i = 0; i < list.size(); i++) { >>> String str = list.get(i); >>> System.out.println("Row " + index + " has the value " + str); >>> } >>> >>> Example 2: >>> >>> StringBuilder buf = new StringBuilder(); >>> for (String str : list : it) { >>> if (it.isFirst()) { >>> buf.append(str); >>> } else { >>> buf.append(", ").append(str); >>> } >>> } >>> >>> StringBuilder buf = new StringBuilder(); >>> for (String str : list : it) { >>> if (it.isLast()) { >>> buf.append(str); >>> } else { >>> buf.append(str).append(", "); >>> } >>> } >>> >>> >>> *DETAILS* >>> >>> SPECIFICATION: >>> >>> Lexical: >>> No new tokens are added. The colon token is reused in the extended >>> enhanced for each statement. >>> >>> Syntax: >>> >>> EnhancedForStatement: >>> for ( VariableModifiersopt Type Identifier : Expression) Statement >>> for ( VariableModifiersopt Type Identifier : Expression : Ident) >>> Statement >>> >>> Semantics: >>> >>> The first enhanced for each statement (the current form) will compile as >>> it does today. >>> >>> The extended enhanced for each statement will operate as follows. >>> The iterator control variable is a standard variable declared to be >>> final. It will never be null. The type is dependent on whether the >>> expression is an array or an Iterable. It will either be >>> ArrayIterationControl or IterableIterationControl. The type is not >>> specified as it is redundent information, ie. the type is inferred. It >>> is scoped for the life of the loop. >>> >>> public final class IterableIterationControlIterator { >>> public IterableIterationControlIterator(Iterable iterable) { >>> this.control = new IterableIterationControl(iterable.iterator()); >>> } >>> public boolean hasNext() { return control.hasNext() } >>> public T next() { return control.next() } >>> public IterableIterationControl control() { return control } >>> } >>> public final class IterableIterationControl { >>> public IterableIterationControl(Iterator iteratorToWrap) { >>> this.it = iteratorToWrap; >>> } >>> boolean hasNext() { return it.hasNext() } >>> T next() { originalIndex++; if (lastWasRemoved) { lastWasRemoved = >>> false } else { index++ } return it.next() } >>> public T remove() { removed++; lastWasRemoved = true; return >>> it.remove() } >>> public int index() { return index } >>> public int originalIndex() { return originalIndex } >>> public boolean isFirst() { return index == 1 } >>> public boolean isLast() { return it.hasNext() == false } >>> } >>> >>> public final class ArrayIterationControlIterator { >>> public ArrayIterationControlIterator(T[] array) { >>> this.control = new ArrayIterationControl(array); >>> } >>> public boolean hasNext() { return control.hasNext() } >>> public T next() { return control.next() } >>> public ArrayIterationControl control() { return control } >>> } >>> public final class ArrayIterationControl { >>> public ArrayIterationControl(T[] array) { this.array = array; } >>> boolean hasNext() { return index < array.length; } >>> T next() { return array[++index]; } >>> public int index() { return index - 1; } >>> public boolean isFirst() { return index == 1; } >>> public boolean isLast() { return index == array.length; } >>> } >>> >>> Exception analysis: >>> The method remove() on the iteration control variable can throw an >>> UnsuportedOperationException. However, this is no different from any >>> other method call. >>> >>> Definite assignment: >>> The new variable iteration control variable is a final variable that is >>> definitely assigned from creation. >>> >>> COMPILATION: >>> The extended enhanced for each loop is implemented by wrapping the two >>> control classes around the Iterable or the array. >>> >>> The Iterable design is desugared from: >>> >>> for (T item : iterable : control) { ... } >>> >>> to: >>> { >>> IterableIterationControlIterator $it = new >>> IterableIterationControlIterator(iterable); >>> IterableIterationControl control = $it.control(); >>> while ($it.hasNext()) { >>> T item = $it.next(); >>> ... >>> } >>> } >>> >>> The array design is desugared similarly: >>> >>> { >>> ArrayIterationControlIterator $it = new >>> ArrayIterationControlIterator(iterable); >>> ArrayIterationControl control = $it.control(); >>> while ($it.hasNext()) { >>> T item = $it.next(); >>> ... >>> } >>> } >>> >>> There is the option to optimise this if the iteration control variable >>> is not assigned to any other variable or passed to any other method. >>> However, that is out of scope for now. >>> >>> TESTING: >>> Testing will be similar to the enhanced for loop. Arrays and Iterables >>> of various types and sizes will be used. The null expression will also >>> be tested. >>> >>> LIBRARY SUPPORT: >>> Yes, as detailed above. >>> >>> REFLECTIVE APIS: >>> No. >>> >>> OTHER CHANGES: >>> The javac tree API would need to be updated to model the change. >>> >>> MIGRATION: >>> Migration is not required. However, an IDE refactoring could now convert >>> more int and Iterator based for loops than it does at present. >>> >>> >>> *COMPATIBILITY* >>> >>> BREAKING CHANGES: >>> No breaking changes are known using this conversion scheme. >>> >>> EXISTING PROGRAMS: >>> This conversion is pure syntax sugar, so there are no known interactions >>> with existing programs. >>> >>> >>> *REFERENCES* >>> >>> EXISTING BUGS: >>> I searched the bug database, but nothing came up (which is surprising). >>> >>> URL FOR PROTOTYPE: >>> None >>> >>> DOCUMENTS: >>> [1] Stephen Colebourne's blog: >>> http://www.jroller.com/scolebourne/entry/java_7_for_each_loop >>> [2] Stephen Colebourne's original writeup: >>> http://docs.google.com/Edit?docID=dfn5297z_15ck7x5ghr >>> >>> >>> *DESIGN ISSUES* >>> There are numerous alternative ways in which this feature can be added. >>> These include: >>> - using the keyword: >>> for (String str : list) { >>> for.remove(); // problem is nested for loops >>> } >>> - using a label as a psuedo-variable: >>> it: for (String str : list) { >>> it:remove(); // note colon and not dot >>> } >>> - using an additional clause before the for each colon: >>> for (String str, int index : list) { >>> // no access to remove, and conflicts for for each for maps >>> } >>> >>> The chosen solution involves simple Java classes, and a simple desugar. >>> The downside of the chosen solution is performance, as it involves >>> creating two wrapping objects and routing hasNext() and next() via >>> additional layers of method calls. A possible extension would be for the >>> compiler to identify if the iteration control variable is not passed to >>> another method. If so, then the code could be all be generated inline. >>> >>> >>> >>> >>> >>> >> >> >> > > > From vapor1 at teleport.com Fri May 1 00:09:20 2009 From: vapor1 at teleport.com (Derek Foster) Date: Fri, 1 May 2009 03:09:20 -0400 (EDT) Subject: Submission: switch (...) instanceof feature Message-ID: <21950339.1241161760435.JavaMail.root@elwamui-hound.atl.sa.earthlink.net> I notice that the example you gave is actually an argument for an "if" that respects instanceOf, rather than a 'switch' that does. It seems to me like an abuse of notation to use a 'switch' in a case like this where only one decision (it is or it isn't a subtype of a given type) is being made. Although I am skeptical of the 'switch instanceof' feature, for the reasons I outlined below, I would very much like to see Java implement the 'if instanceof' feature that is implied in the proposal, and which various people have been suggesting, so that this very common coding pattern: if (foo instanceof Bar) { Bar bar = (Bar)foo; doSomethingWith(bar); } could be simplified to: if (foo instanceof Bar) { doSomethingWith(foo); } with no loss of type safety. It seems to me that your example would be more readable with such a construct than it is with the 'switch instanceof' feature. I had intended to submit a proposal along these lines myself, but simply ran out of time to put it together. Still, it seems to me that there's been widespread agreement on the list that the 'if instanceof' sub-proposal is a good idea. Derek -----Original Message----- >From: Ulf Zibis >Sent: Apr 22, 2009 5:17 AM >To: Derek Foster >Cc: Gabriel Belingueres , Jeroen van Maanen , coin-dev at openjdk.java.net >Subject: Re: Submission: switch (...) instanceof feature > >Am 22.04.2009 06:55, Derek Foster schrieb: >> Like Gabriel, I have severe reservations about this proposal. I am concerned that it will encourage people to avoid the common OOP "best practice" of using virtual method dispatch in favor of doing an explicit "switch" on each subtype of a type, in cases where doing so is not necessary. >> >> I concede that there are a few (FEW!) places where doing the equivalent of a switch on instances of a type is necessary (for instance, if the type is in a library you don't have the ability to change). I can see some value in this proposal for that purpose. However, I would very much not like to see use of this construct become commonplace. I already see too many instances of people doing the equivalent of "if (object.type == FOO) {doThis(); } else if (object.type == BAR) { doThat(); }" instead of writing "object.doSomething();" >> >> > >I like to provide an example where > > "object.doSomething();" > > doesn't work: > > synchronized Charset lookup(String lowCanonical) { > // cache is initialized with available Charset classes names > Object o = cache.get(lowCanonical); > // Check cache first > if (o instanceof String) { > // Instantiate new charset > Charset cs = newCharset((String)o, lowCanonical); > // Cache it > if (cs != null) > cache.put(lowCanonical, cs); > return cs; > } > return (Charset)o; > } > > > This would look much nicer, as it avoids casting: > > synchronized Charset lookup(String lowCanonical) { > // cache is initialized with available Charset classes names > switch (Object o = cache.get(lowCanonical) instanceof ?) { > case String : > // Instantiate new charset > Charset cs = newCharset(o, lowCanonical); > // Cache it > if (cs != null) > cache.put(lowCanonical, cs); > return cs; > case Charset : > return o; > } > } > > >Refer: >https://java-nio-charset-enhanced.dev.java.net/source/browse/java-nio-charset-enhanced/tags/milestone4/src/sun/nio/cs/FastCharsetProvider.java?rev=684&view=markup >http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6790402 >http://mail.openjdk.java.net/pipermail/coin-dev/2009-March/001182.html >http://mail.openjdk.java.net/pipermail/coin-dev/2009-April/001328.html > >- My example could also be smartly coded without switch..case statement, >if we would enhance if statement accordingly >- I also would like to have possibility to declare variables in if >clause, like it's possible in for clause: > > if ((Object o = cache.get(lowCanonical)) instanceof String) > ... ; > else if (o instanceof Charset) > ... ; > > >-Ulf > > >> Derek >> >> -----Original Message----- >> >>> From: Gabriel Belingueres >>> Sent: Mar 30, 2009 7:31 AM >>> To: Jeroen van Maanen >>> Cc: coin-dev at openjdk.java.net >>> Subject: Re: Submission: switch (...) instanceof feature >>> >>> IMO I'm against this. >>> >>> First, it is against current best practices for the design of >>> object-oriented software to make easier to code something with a case >>> statement on types/classes. >>> >>> Second: >>> void log(Object object) { >>> switch (object) instanceof { >>> case String: >>> logger.debug("'" + object + "'"); >>> case Date: >>> logger.debug(object.getTime()); >>> case void: >>> logger.debug("null"); >>> default: >>> logger.debug("<" + object.toString() + ">"); >>> } >>> } >>> >>> It think it is clearer (when possible) writing it with several >>> overloaded methods and double dispatching. >>> >>> .... >>> > From vapor1 at teleport.com Fri May 1 00:22:12 2009 From: vapor1 at teleport.com (Derek Foster) Date: Fri, 1 May 2009 03:22:12 -0400 (EDT) Subject: PROPOSAL: Auto-assignment Parameters Message-ID: <23954837.1241162532944.JavaMail.root@elwamui-hound.atl.sa.earthlink.net> For the record, I like James's proposal below, and I wish someone had submitted a more formal proposal for it. I would probably use this a lot if it existed. Derek -----Original Message----- >From: james lowden >Sent: Mar 25, 2009 3:04 PM >To: coin-dev at openjdk.java.net >Subject: Re: PROPOSAL: Auto-assignment Parameters > > >I don't like the multiple annotations approach as it removes the convenience of being able to easily get the default magic behaviors via one modifier. There's certainly precedent for this in the language; applying the "synchronized" keyword to a method or block of code gives you a default set of "magic" concurrency behaviors which under the hood are in fact somewhat complex. > >My only concern with it as stands is that "data" in class declarations is a keyword, and presumably is a valid identifier everywhere else; I'd rather see something that wasn't a valid Java identifier used to denote this behavior. I wouldn't mind seeing "default" used this way (to imply desirable "default" behavior), as in: > >default public class Foo { > > private int x; > private String blah; > >} > >generates all the default getters/setters/equals/hashcode/constructor. > >-JL- > > >--- On Wed, 3/25/09, Lawrence Kesteloot wrote: > >> From: Lawrence Kesteloot >> Subject: Re: PROPOSAL: Auto-assignment Parameters >> To: coin-dev at openjdk.java.net >> Date: Wednesday, March 25, 2009, 1:25 PM >> Reinier, >> >> The idea of adding a context-sensitive keyword creeps me >> out. Also >> this is doing a lot of magic based on a single keyword. Can >> you tell, >> at a glance, what the keyword is doing? How much is >> generated? What >> are the (complex) rules for auto-generating a constructor? >> >> I would prefer a more explicit approach, driven by >> annotations. If we >> feel like boilerplate is annoying to write and bug-prone, >> then we >> could have a java.lang.gen package with various annotations >> for >> automatically generating code. Something like: >> >> @GenerateFullConstructor >> @GenerateEqualsAndHashCode >> @GenerateToString(JsonToStringGenerator.class) >> public class Foo { >> @GenerateGetter >> private final int x; >> @GenerateGetter >> private final int y; >> @GenerateGetter >> private final String foo; >> } >> >> Then it's explicit, each annotation can have parameters >> to modify its >> behavior, and people can pick and choose what they need. >> There's no >> magic about skipping the generation of toString if >> you've implemented >> it. >> >> Here's an example of useful parameters for such >> annotations: many >> people (myself included) like to prefix fields with >> something. I use >> "m" (mFoo), but others use an underscore, and >> some both (m_foo). You'd >> want the GenerateGetter annotation to be flexible about >> that. My code >> would look like this: >> >> @GenerateGetter(prefix = "m") >> private final String mFoo; >> >> Your "data" keyword would preclude this, forcing >> me to either drop my >> (company-mandated) coding standard for data classes, or >> have getters >> like "getMFoo()". >> >> With GenerateEqualsAndHashCode you might want to skip some >> fields. You >> might want to skip fields for GenerateToString also (e.g., >> password >> fields, or super long strings). >> >> Lawrence >> >> >> On Wed, Mar 25, 2009 at 9:59 AM, Reinier Zwitserloot >> wrote: >> > There's no reference for auto-POJOs anywhere, but >> this should allow >> > you to write up all you need: >> > >> > 1. 'data' is a context sensitive keyword that >> is legal on classes. The >> > 'data' keyword will add a number of members to >> the class. >> > >> > 2. For each field, a getter is generated, according to >> the beanspec >> > (getFoo() or isFoo()). if the field is not final, a >> setter is >> > generated, according to beanspec (setFoo()), and the >> field is >> > considered a property of the data class, unless it is >> transient. If >> > the field is public, the getter (and, if not final, >> the setter), is >> > not generated. For all generated getters/setters, if >> the getter/setter >> > is already in the class, or already defined (that is; >> not abstract) in >> > any supertype, then the getter/setter is not >> generated. protected and >> > visible package protected members from supertypes are >> also included >> > both for generating setters/getters and for >> hashCode/equals/toString/ >> > clone (upcoming). >> > >> > 3. hashCode() and equals(): Existence of the >> hashCode() or equals() >> > method in any supertype is not relevant (obviously; >> all objects have >> > them!) >> > >> > 3a. If only one of hashCode() or equals() is present, >> a warning is >> > generated and neither hashCode() or equals() is >> auto-generated. The >> > warning basically explains that overriding one but not >> the other is a >> > bug. >> > >> > 3b. If both hashCode() and equals() are present, >> nothing happens. >> > >> > 3c. If neither is present, a hashCode() and equals() >> method are >> > generated. These involve all properties (non-transient >> visible >> > fields). equals() is defined by: >> > >> > ?3c1: First check if the other object is of the exact >> same class as >> > ourselves; if not, false. If null, false. >> > ?3c2: For each primitive property, check via == if >> they are equal. If >> > any isn't, false. >> > ?3c3: For each object property, call its .equals(). >> If they aren't, >> > false. >> > ?3c4: return true. >> > >> > for hashCode(), do whatever eclipse does out of the >> box to auto- >> > generate hashCode() methods. It basically looks like: >> > >> > final int PRIME = 31; >> > int result = 1; >> > for ( each field ) result = result*31 + >> field.hashCode(); >> > return result; >> > >> > Where hashCode() is generated in obvious fashion for >> all primitives >> > (xor the upper and lower bits of longs together, >> convert floats and >> > doubles to long/intbits and use that, >> chars/bytes/ints/shorts's >> > hashCode is their own value, booleans are translated >> to 11/17. 'null' >> > becomes 3. >> > >> > 4. *IF* all fields are private, and *IF* all fields >> are final, *AND* >> > the class does not contain any explicit constructors, >> *AND* the class >> > has a no-args super constructor, then a constructor is >> generated that >> > includes all fields, in order of definition, which >> simply assigns them >> > to the fields. visible properties from supertypes >> aren't included. >> > >> > 5. A toString() method is generated, if not already >> present in the >> > type, which produces a string like so: >> "MyClassName [field1=value, >> > field2=value]", for all properties. (so, >> non-visible fields from >> > supertypes and transient fields are skipped). >> > >> > 6 (optional). Each generated member gets a @Generated >> annotation, >> > which is a new annotation ( >> java.lang.annotations.Generated ). These >> > are @Documented and @Retention.RUNTIME. >> > >> > >> > Is it viable for coin? I'll write it up if so. >> > >> > ?--Reinier Zwitserloot >> > >> > >> > >> > On Mar 25, 2009, at 14:41, james lowden wrote: >> > >> >> >> >> I'd like to see both. >> ?Auto-getters/setters/equals/etc. would be >> >> really, really nice, but it would also be valuable >> to have a way of >> >> specifying a variety of different constructors to >> generate, which >> >> Mark's proposal would allow for. ?Example: >> >> >> >> public data class Foo { >> >> ? ? ?private final int x; >> >> ? ? ?private final int y; >> >> ? ? ?private final String foo; >> >> >> >> ? ? ?public Foo (this.x) {} >> >> >> >> ? ? ?public Foo (this.foo, this.y) {} >> >> } >> >> >> >> >> >> (I eliminated the types from the automagical >> constructors, as they >> >> can be inferred by the compiler.) >> >> >> >> This would generate all three getters and setters, >> equals (), >> >> hashcode (), a general constructor taking in all 3 >> fields, and two >> >> additional constructors, one taking in just int x, >> and one taking in >> >> both String foo and int y. >> >> >> >> Reinier--is there a copy of your original proposal >> for auto-POJOs >> >> somewhere? >> >> >> >> -JL- >> >> >> >> >> >>> From: Reinier Zwitserloot >> >> >>> Subject: Re: PROPOSAL: Auto-assignment >> Parameters >> >>> To: "Mark Mahieu" >> >> >>> Cc: coin-dev at openjdk.java.net >> >>> Date: Tuesday, March 24, 2009, 8:34 PM >> >>> I like where this is going, but I'd rather >> see a bigger >> >>> setup for auto- >> >>> POJO classes. I proposed this before and in >> most java >> >>> circles (outside >> >>> of coin-dev!), this idea was considered very >> useful: >> >>> >> >>> public data class Foo { >> >>> ? ? private final int x; >> >>> ? ? private final int y; >> >>> ? ? private final String foo; >> >>> } >> >>> >> >>> >> >>> The above class would auto-generate the >> getters, a >> >>> constructor, >> >>> hashCode, equals, and toString. You can add >> methods to it >> >>> if you want, >> >>> and if you define a method that would usually >> be >> >>> auto-generated, it >> >>> isn't auto-generated. So, if you need to >> do some extra >> >>> processing >> >>> before returning 'foo' via the getter, >> go right >> >>> ahead. You can even >> >>> add this later without breaking your API's >> >>> compatibility. >> >>> >> >>> ?--Reinier Zwitserloot >> >>> >> >>> >> >>> >> >>> On Mar 25, 2009, at 02:07, Mark Mahieu wrote: >> >>> >> >>>> HTML version + prototype available at >> >>> http://slm888.com/javac >> >>>> >> >>>> >> >>>> >> >>>> Auto-assignment Parameters v0.1 >> >>>> >> >>>> >> >>>> AUTHOR(S): >> >>>> >> >>>> Mark Mahieu >> >>>> >> >>>> >> >>>> OVERVIEW >> >>>> >> >>>> FEATURE SUMMARY: Should be suitable as a >> summary in a >> >>> language >> >>>> tutorial. >> >>>> >> >>>> An additional form of constructor >> parameter which >> >>> provides automatic >> >>>> assignment of the parameter's value to >> an instance >> >>> field. ?These >> >>>> parameters >> >>>> are implicitly declared as final to >> prevent >> >>> unintentional >> >>>> assignments to the >> >>>> wrong variable in the constructor body. >> >>>> >> >>>> >> >>>> MAJOR ADVANTAGE: What makes the proposal a >> favorable >> >>> change? >> >>>> >> >>>> Reduces the likelihood of some common >> coding errors >> >>> relating to >> >>>> assignment >> >>>> of fields in a constructor, including >> those where: >> >>>> >> >>>> ? * a field is assigned to itself >> >>>> ? * the parameter is assigned instead of >> the field >> >>>> ? * the assignment to the field is >> missing entirely >> >>>> >> >>>> These and other errors are often caused by >> typos or >> >>> code refactoring. >> >>>> >> >>>> >> >>>> MAJOR BENEFIT: Why is the platform better >> if the >> >>> proposal is adopted? >> >>>> >> >>>> A programmer's intent is more clearly >> expressed >> >>> for the extremely >> >>>> common >> >>>> case of assigning a constructor parameter >> directly to >> >>> an instance >> >>>> field with >> >>>> the same name. >> >>>> >> >>>> >> >>>> MAJOR DISADVANTAGE: There is always a >> cost. >> >>>> >> >>>> As with any sugar which enables a more >> concise way of >> >>> expressing an >> >>>> existing >> >>>> idiom, programmers may be tempted to use >> it even when >> >>> the original >> >>>> form >> >>>> would be more appropriate. >> >>>> >> >>>> >> >>>> ALTERNATIVES: Can the benefits and >> advantages be had >> >>> some way >> >>>> without a >> >>>> language change? >> >>>> >> >>>> IDEs and tools such as FindBugs are good >> at warning >> >>> about the kind >> >>>> of errors >> >>>> mentioned above, however since the code in >> question is >> >>> usually still >> >>>> valid >> >>>> to the compiler, they are limited in what >> action they >> >>> can take by >> >>>> default. >> >>>> >> >>>> A language change can combine the ability >> to avoid >> >>> these errors >> >>>> entirely >> >>>> with a more expressive idiom, resulting in >> an >> >>> increased signal to >> >>>> noise >> >>>> ratio for readers of that code. >> >>>> >> >>>> >> >>>> >> >>>> EXAMPLES >> >>>> >> >>>> SIMPLE EXAMPLE: Show the simplest possible >> program >> >>> utilizing the new >> >>>> feature. >> >>>> >> >>>> ? class C { >> >>>> ? ? ? int i; >> >>>> ? ? ? C(int this.i) {} >> >>>> ? } >> >>>> >> >>>> >> >>>> ADVANCED EXAMPLE: Show advanced usage(s) >> of the >> >>> feature. >> >>>> >> >>>> >> >>>> ? class Proposal { >> >>>> >> >>>> ? ? ? private final String name; >> >>>> ? ? ? private final String author; >> >>>> ? ? ? private boolean suitableForCoin; >> >>>> ? ? ? private Integer score; >> >>>> >> >>>> ? ? ? public Proposal(String this.name, >> >>>> ? ? ? ? ? ? ? ? ? ? ? String >> this.author, >> >>>> ? ? ? ? ? ? ? ? ? ? ? boolean >> this.suitableForCoin, >> >>>> ? ? ? ? ? ? ? ? ? ? ? int >> this.score) { >> >>>> >> >>>> ? ? ? ? ? if >> (name.equals(?Auto-assignment >> >>> Parameters?)) { >> >>>> ? ? ? ? ? ? ?suitableForCoin = >> true; // final so >> >>> compile-time error >> >>>> ? ? ? ? ? } >> >>>> ? ? ? } >> >>>> >> >>>> ? ? ? // rest of class ... >> >>>> ? } >> >>>> >> >>>> >> >>>> >> >>>> DETAILS >> >>>> >> >>>> >> >>>> SPECIFICATION: Describe how the proposal >> affects the >> >>> grammar, type >> >>>> system, >> >>>> and meaning of expressions and statements >> in the Java >> >>> Programming >> >>>> Language >> >>>> as well as any other known impacts. >> >>>> >> >>>> The syntactic grammar is modified to >> include >> >>> auto-assignment >> >>>> parameters for >> >>>> constructors: >> >>>> >> >>>> ? ? ? ConstructorDeclaratorRest: >> >>>> ? ? ? ? ? ? ? >> ?ConstructorParameters [throws >> >>> QualifiedIdentifierList] >> >>>> MethodBody >> >>>> >> >>>> ? ? ? ConstructorParameters: >> >>>> ? ? ? ? ? ? ? ?( >> [ConstructorParameterDecls] ) >> >>>> >> >>>> ? ? ? ConstructorParameterDecls: >> >>>> ? ? ? ? ? ? ? ?[final] >> [Annotations] Type >> >>>> ConstructorParameterDeclsRest >> >>>> >> >>>> ? ? ? ConstructorParameterDeclsRest: >> >>>> ? ? ? ? ? ? ? >> ?ConstructorParameterId [ , >> >>> ConstructorParameterDecls] >> >>>> ? ? ? ? ? ? ? ?... >> ConstructorParameterId >> >>>> >> >>>> ? ? ? ConstructorParameterId: >> >>>> ? ? ? ? ? ? ? >> ?VariableDeclaratorId >> >>>> ? ? ? ? ? ? ? ?this . >> VariableDeclaratorId >> >>>> ? ? ? ? ? ? ? ?super . >> VariableDeclaratorId >> >>>> >> >>>> An auto-assignment parameter is a formal >> parameter >> >>> (JLSv3 ?8.4.1) >> >>>> which >> >>>> specifies an instance field instead of an >> identifier. >> >>> Its value is >> >>>> automatically assigned to the specified >> field. ?It may >> >>> only be used >> >>>> in a >> >>>> constructor. >> >>>> >> >>>> The automatic assignment takes place after >> any >> >>> explicit or implicit >> >>>> invocation of another constructor, and >> before any >> >>> statements in the >> >>>> body of >> >>>> the constructor. ?A constructor which >> declares n >> >>> auto-assignment >> >>>> parameters >> >>>> will perform n such automatic assignments, >> in the >> >>> order that the >> >>>> parameters >> >>>> are declared. >> >>>> >> >>>> The parameter has the same name (JLSv3 >> ?6.2) as the >> >>> field to which >> >>>> it is >> >>>> assigned; replacing each auto-assignment >> parameter >> >>> with a normal >> >>>> formal >> >>>> parameter with the same name would yield a >> constructor >> >>> with an >> >>>> identical >> >>>> signature. ?As with a normal parameter, >> the >> >>> parameter's name is >> >>>> entered into >> >>>> the scope of the constructor body (JLSv3 >> ?6.3), and >> >>> therefore >> >>>> shadows the >> >>>> field (JLSv3 ?6.3.1) within that scope. >> >>>> >> >>>> It is a compile-time error if the field is >> not >> >>> accessible from the >> >>>> constructor in which the parameter >> appears. >> >>>> >> >>>> It is a compile-time error if the declared >> type of the >> >>> parameter is >> >>>> not >> >>>> assignment compatible (JLSv3 ?5.2) with >> the field to >> >>> which it is >> >>>> automatically assigned. >> >>>> >> >>>> If an unboxing conversion is required by >> an automatic >> >>> assignment, any >> >>>> NullPointerException thrown as a result >> (JLSv3 >> >>> ?5.1.8) will contain >> >>>> the name >> >>>> of the field on which the conversion >> failed, which may >> >>> be retrieved by >> >>>> calling getMessage() on the exception. >> >>>> >> >>>> Auto-assignment parameters are implicitly >> final, and >> >>> follow the >> >>>> standard >> >>>> rules for final variables (JLSv3 >> ?4.12.4). >> >>> Explicitly declaring an >> >>>> auto-assignment parameter as final has no >> effect, and >> >>> does not cause a >> >>>> compilation error. >> >>>> >> >>>> Auto-assignment parameters follow the >> standard >> >>> definite assignment >> >>>> rules for >> >>>> formal parameters (JLSv3 ?16.3). >> >>>> >> >>>> An auto-assignment parameter may be >> annotated. >> >>>> >> >>>> If an auto-assignment parameter is the >> last parameter >> >>> in the list, and >> >>>> refers to a field of array type, it may be >> a variable >> >>> arity parameter. >> >>>> >> >>>> >> >>>> >> >>>> COMPILATION: How would the feature be >> compiled to >> >>> class files? Show >> >>>> how the >> >>>> simple and advanced examples would be >> compiled. >> >>> Compilation can be >> >>>> expressed >> >>>> as at least one of a desugaring to >> existing source >> >>> constructs and a >> >>>> translation down to bytecode. If a new >> bytecode is >> >>> used or the >> >>>> semantics of >> >>>> an existing bytecode are changed, describe >> those >> >>> changes, including >> >>>> how they >> >>>> impact verification. Also discuss any new >> class file >> >>> attributes that >> >>>> are >> >>>> introduced. Note that there are many >> downstream tools >> >>> that consume >> >>>> class >> >>>> files and that they may to be updated to >> support the >> >>> proposal! >> >>>> >> >>>> Desugaring of the following class: >> >>>> >> >>>> ? class Foo { >> >>>> ? ? ? int value; >> >>>> ? ? ? Foo(Integer this.value) { >> >>>> ? ? ? ? ? System.out.println(value); >> >>>> ? ? ? } >> >>>> ? } >> >>>> >> >>>> would result in (unboxing desugaring >> omitted): >> >>>> >> >>>> ? class Foo { >> >>>> ? ? ? int value; >> >>>> ? ? ? Foo(final Integer value) { >> >>>> ? ? ? ? ? super(); >> >>>> ? ? ? ? ? if (value == null) >> >>>> ? ? ? ? ? ? ? throw new >> >>> NullPointerException("value"); >> >>>> ? ? ? ? ? this.value = value; >> >>>> ? ? ? ? ? System.out.println(value); >> >>>> ? ? ? } >> >>>> ? } >> >>>> >> >>>> No changes to the classfile format are >> required. >> >>> Tools which >> >>>> consume class >> >>>> files see the constructor signature as >> though it had >> >>> been written >> >>>> using >> >>>> normal formal parameters. >> >>>> >> >>>> >> >>>> TESTING: How can the feature be tested? >> >>>> >> >>>> An initial set of jtreg tests is included >> in the >> >>> prototype. >> >>>> >> >>>> >> >>>> LIBRARY SUPPORT: Are any supporting >> libraries needed >> >>> for the feature? >> >>>> >> >>>> No >> >>>> >> >>>> >> >>>> REFLECTIVE APIS: Do any of the various and >> sundry >> >>> reflection APIs >> >>>> need to be >> >>>> updated? This list of reflective APIs >> includes but is >> >>> not limited to >> >>>> core >> >>>> reflection (java.lang.Class and >> java.lang.reflect.*), >> >>> >> >>>> javax.lang.model.*, >> >>>> the doclet API, and JPDA. >> >>>> >> >>>> com.sun.source.tree.VariableTree would >> require an >> >>> additional method >> >>>> which >> >>>> returns the auto-assigned field. >> >>>> >> >>>> >> >>>> OTHER CHANGES: Do any other parts of the >> platform need >> >>> be updated too? >> >>>> Possibilities include but are not limited >> to JNI, >> >>> serialization, and >> >>>> output >> >>>> of the javadoc tool. >> >>>> >> >>>> No >> >>>> >> >>>> >> >>>> MIGRATION: Sketch how a code base could be >> converted, >> >>> manually or >> >>>> automatically, to use the new feature. >> >>>> >> >>>> Assignment statements in constructors for >> which all of >> >>> the following >> >>>> are >> >>>> true can be considered suitable for >> conversion: >> >>>> ? ?* the lhs of the assignment is a >> non-static field >> >>>> ? ?* the rhs is a parameter with the >> same name as the >> >>> field >> >>>> ? ?* there are no other assignments to >> the parameter >> >>> anywhere in the >> >>>> constructor >> >>>> ? ?* there are no assignments to, or >> other uses of >> >>> the field before >> >>>> the >> >>>> assignment statement in question >> (including invoked >> >>> constructors) >> >>>> >> >>>> Such statements can be converted by: >> >>>> ? 1) replacing the parameter with an >> auto-assignment >> >>> parameter >> >>>> (prefixing >> >>>> the existing parameter's identifier >> with >> >>> 'this.'), and >> >>>> ? 2) removing the assignment statement >> >>>> >> >>>> >> >>>> >> >>>> COMPATIBILITY >> >>>> >> >>>> BREAKING CHANGES: Are any previously valid >> programs >> >>> now invalid? If >> >>>> so, list >> >>>> one. >> >>>> >> >>>> No >> >>>> >> >>>> >> >>>> EXISTING PROGRAMS: How do source and class >> files of >> >>> earlier platform >> >>>> versions interact with the feature? Can >> any new >> >>> overloadings occur? >> >>>> Can any >> >>>> new overriding occur? >> >>>> >> >>>> The semantics of existing class files and >> legal source >> >>> files are >> >>>> unchanged >> >>>> by this feature. >> >>>> >> >>>> >> >>>> >> >>>> REFERENCES >> >>>> >> >>>> EXISTING BUGS: Please include a list of >> any existing >> >>> Sun bug ids >> >>>> related to >> >>>> this proposal. >> >>>> >> >>>> >> >>> >> http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6582394 >> >>>> (uses a 'setter' method rather >> than a >> >>> constructor in its example) >> >>>> >> >>>> FindBugs bug patterns - >> >>> >> http://findbugs.sourceforge.net/bugDescriptions.html >> >>>> * Self assignment of field >> (SA_FIELD_SELF_ASSIGNMENT) >> >>>> * Self comparison of field with itself >> >>> (SA_FIELD_SELF_COMPARISON) >> >>>> * Nonsensical self computation involving a >> field >> >>> (e.g., x & x) >> >>>> (SA_FIELD_SELF_COMPUTATION) >> >>>> * Self assignment of local variable >> >>> (SA_LOCAL_SELF_ASSIGNMENT) >> >>>> * Nonsensical self computation involving a >> variable >> >>> (e.g., x & x) >> >>>> (SA_LOCAL_SELF_COMPUTATION) >> >>>> * Uninitialized read of field in >> constructor >> >>> (UR_UNINIT_READ) >> >>>> * Unwritten field (UWF_UNWRITTEN_FIELD) >> >>>> * Dead store to local variable >> (DLS_DEAD_LOCAL_STORE) >> >>>> * Dead store of null to local variable >> >>> (DLS_DEAD_LOCAL_STORE_OF_NULL) >> >>>> >> >>>> >> >>>> >> >>>> URL FOR PROTOTYPE (optional): >> >>>> >> >>>> http://slm888.com/javac >> >>>> >> >>>> >> >>>> >> >>>> DESIGN ALTERNATIVES: >> >>>> >> >>>> The following variations have been >> explored and are >> >>> worth mentioning: >> >>>> >> >>>> * Allow auto-assignment parameters on all >> non-abstract >> >>> methods. >> >>>> ? This may be especially useful on the >> extremely >> >>> common 'setter' >> >>>> methods >> >>>> in 'value object' classes. >> >>>> >> >>>> * Remove the requirement for (or even >> disallow) the >> >>> type to be >> >>>> specified on >> >>>> auto-assignment parameters. >> >>>> ? Experimentation with this idea suggests >> that it may >> >>> work quite >> >>>> well for >> >>>> constructors, further emphasising the >> difference in >> >>> intent and >> >>>> semantics >> >>>> from those of normal parameters. However, >> it may not >> >>> work so well in >> >>>> combination with auto-assignment >> parameters on all >> >>> non-abstract >> >>>> methods, and >> >>>> requires a change to the order in which >> javac compiles >> >>> classes (can >> >>>> still >> >>>> pass jtreg tests). >> >>>> >> >>>> * Allow an alternative name to be >> specified. >> >>>> ? This adds additional complexity to >> support a >> >>> fractional >> >>>> percentage of >> >>>> cases, which could continue to use the >> existing coding >> >>> pattern. >> >>>> >> >> >> >> >> >> >> >> >> > >> > >> > > > > > From vapor1 at teleport.com Fri May 1 00:31:42 2009 From: vapor1 at teleport.com (Derek Foster) Date: Fri, 1 May 2009 03:31:42 -0400 (EDT) Subject: PROPOSAL: Auto-assignment Parameters Message-ID: <1286638.1241163102612.JavaMail.root@elwamui-hound.atl.sa.earthlink.net> -----Original Message----- >From: Mark Mahieu >Sent: Mar 29, 2009 6:18 AM >To: Derek Foster >Cc: coin-dev at openjdk.java.net >Subject: Re: PROPOSAL: Auto-assignment Parameters > >On 28 Mar 2009, at 21:31, Derek Foster wrote: > >> Just to add a few kudos and comments: >> >> I like the proposal a lot. Even in its current form, this would >> save me a lot of typing. Of the proposals so far put forth on >> Project Coin, this is the one I would probably end up using the >> most often. >... >In one of your other emails to this list, you mentioned that you use >a prefix on field names to prevent typographical mistakes. Given >that this proposal aims to avoid many of the situations in which >those mistakes can be made, would you continue to do so if it were >implemented? Sorry for taking so long to answer this... it took me a while to find this message again. Anyway, I might consider dropping the prefix, IF this proposal specified one thing that I'm not sure that it does, in it's current form. Specifically, what my prefix use is intended to protect against is name shadowing: cases where there is a local name (a parameter name) which is identical to the same name in an enclosing scope (a field name). This scenario has caused a great deal of grief to a great many people. Hence, I try to force my names in different scopes to be different, to avoid the possibility of shadowing. Whether this proposal improves this situation depends on whether this: void Foo(this.bar) { bar = whatever; } sets the field 'bar' to 'whatever', or whether it sets the parameter 'bar' to 'whatever'. If the latter is true, then there is still name shadowing going on, and I would still be inclined to use a prefix. If the former is true, which I would prefer (if 'this.bar' in a formal parameter list does not actually introduce a new named parameter instance into the local scope) then I would probably not feel a continued need for a prefix, at least in this case. Note, however, that there are still lots of cases that aren't covered by your proposal that might make a prefix desirable, such as: void setFoo(Thing foo) { lock(); try { _foo = foo; } finally { unlock(); } } I don't see an easy way to extend your proposal to cover such a case. Derek > > >> Also, autogeneration of Javadoc for the this. parameters, based on >> Javadoc for the class members they are initialized from would be >> nice. Currently, these often have to be maintained in parallel, >> which can be a significant annoyance. > >That's an interesting idea, though perhaps best suited to a language >feature directly supporting properties, if one is implemented. >Whether it could fit in here would depend on a number of factors, but >it's worth bearing in mind. > > >> 5) Being able to omit the type in all of these cases would be a big >> plus. When I have a variable of a type like >> "List>", it would >> be awfully nice to be able to omit having to specify that detail >> redundantly in the constructor, settter, and getter. > >When I tried that, I found that it worked reasonably well for simple >(ie. very small) classes, but didn't scale well; my ability to >comprehend the code decreased as the class increased in size. Also, >including the type in the parameter declaration makes it clear that a >local variable is being introduced into the scope of the constructor/ >method body, just like a normal formal parameter. Finally, omitting >the type places restrictions upon the order in which a tool such as >javac can choose to process Java source, which is something I'd >rather avoid if possible. > > >Thanks for all your comments! > > >Regards, > >Mark > From mthornton at optrak.co.uk Fri May 1 00:38:56 2009 From: mthornton at optrak.co.uk (Mark Thornton) Date: Fri, 01 May 2009 08:38:56 +0100 Subject: PROPOSAL: Sameness operators (version 2) In-Reply-To: <8792005.1241160341070.JavaMail.root@elwamui-hound.atl.sa.earthlink.net> References: <8792005.1241160341070.JavaMail.root@elwamui-hound.atl.sa.earthlink.net> Message-ID: <49FAA710.7020900@optrak.co.uk> Derek Foster wrote: > and adds additional overloadings to existing operators: > a < b a.compareTo(b) < 0, or a < b for primitive types. > a > b a.compareTo(b) > 0, or a > b for primitive types. > > 0f < Float.NaN is false Float.valueOf(0).compareTo(Float.valueOf(Float.NaN)) < 0 is true With Float objects, would the values be unboxed and then compared using the existing '<' operator or left boxed and compared using compareTo? If the former, then casting to Comparable would change the result, while the second alternative would change the current result (obtained via autounboxing). Mark Thornton From scolebourne at joda.org Fri May 1 01:16:25 2009 From: scolebourne at joda.org (Stephen Colebourne) Date: Fri, 1 May 2009 09:16:25 +0100 Subject: PROPOSAL: Enhanced for each loop iteration control In-Reply-To: <13546403.1241161317584.JavaMail.root@elwamui-hound.atl.sa.earthlink.net> References: <13546403.1241161317584.JavaMail.root@elwamui-hound.atl.sa.earthlink.net> Message-ID: <4b4f45e00905010116u196468a6s8649a73fd8c2d1b0@mail.gmail.com> 2009/5/1 Derek Foster : > Firstly, I have very rarely needed to call Iterator.delete() in a loop. (I can think of maybe four or five occasions.) As such, it has usually not been a great deal of trouble to just write the loop using an explicit iterator. Thanks for the numeric feedback. It may depend on coding style. 5% of the loops in the enterprise system I work on have remove(). > On the other hand, I much more frequently would like to be able to use an index. And very few have an index ;-) >However, the proposal seems to assume that if a user wants either an iterator or an index, that the user wants both. In practice, I usually want either one OR the other, but pretty much never both. (For instance, Iterators are good for iterating LinkedLists, and indices are good for ArrayLists, but using the wrong one on a list of any significant size will create a performance problem.) The existing enhanced for-each loop uses Iterators for ArrayList. > I would much prefer to have a simpler syntax that allowed me to work just with an index or just with an iterator... Actually, I'd be happy if just indices were supported. Something like: > > Thing[] fooCollection = ...whatever...; > String[] results = new String[fooCollection.length]; > for (Thing foo : fooCollection) { > ? ? results[#foo] = foo.toString(); > } > > where "#foo" was defined by the compiler as "the index of foo within the collection it is iterating over". #foo has a meaning in FCM as a field reference, and similar syntax was adopted by BGGA (unpublished as a document). It should also be noted that this approach breaks on nested loops (its brittle). Stephen From howard.lovatt at iee.org Fri May 1 01:01:18 2009 From: howard.lovatt at iee.org (Howard Lovatt) Date: Fri, 1 May 2009 18:01:18 +1000 Subject: PROPOSAL: Abstract enums (version 2) Message-ID: <3dd3f56a0905010101v7165f7d5naa89c1550064c24@mail.gmail.com> Derek, I have found also wanted to extend an abstract class when using enums. However I ideally didn't want to extend a special enum abstract class, e.g. abstract enum Super { ... } // Has enum enum extends Super { ... } But rather any old abstract class: abstract class Super { ... } // No enum enum extends Super { ... } What is the rational for only allowing abstract enum to be extended rather than a plain abstract class. -- Howard. From mthornton at optrak.co.uk Fri May 1 01:33:53 2009 From: mthornton at optrak.co.uk (Mark Thornton) Date: Fri, 01 May 2009 09:33:53 +0100 Subject: PROPOSAL: Sameness operators (version 2) In-Reply-To: <8792005.1241160341070.JavaMail.root@elwamui-hound.atl.sa.earthlink.net> References: <8792005.1241160341070.JavaMail.root@elwamui-hound.atl.sa.earthlink.net> Message-ID: <49FAB3F1.2020703@optrak.co.uk> Derek Foster wrote: > This would only happen in generated code (the only place a $ character is supposed to be used, according to the JLS), and is expected to be an extremely rare phenomenon, since generated code rarely starts identifiers with dollar signs, and also usually generates code with spaces around operators for readability. This problem can be easily fixed when upgrading to Java 7 by altering the code generator to put a space in front of any such identifiers, either globally or only when they follow a < or > character. Note that internal synthetic variables generated by a compiler in a class file would be immune from this problem since they would never appear in source code form. > I use a code generator to automatically generate a test class when a bug occurs. The test class includes all the data necessary to reproduce the bug automatically under JUnit. It isn't possible in this case to rerun the code generator --- hopefully I will have fixed the bug, and in many cases the code which gives rise to the bug uses random numbers. Fortunately I use very few variables in this code and none containing $, but other people may have written similar generators which have used $ (after all the JLS could be read as an invitation to use $ in generated names). As it happens I will have to introduce more variables as the current code is giving rise to stack overflow in the compiler (long chains of methods, where long is ~ 50 in a statement). Mark Thornton From mthornton at optrak.co.uk Fri May 1 01:35:49 2009 From: mthornton at optrak.co.uk (Mark Thornton) Date: Fri, 01 May 2009 09:35:49 +0100 Subject: PROPOSAL: Abstract enums (version 2) In-Reply-To: <3dd3f56a0905010101v7165f7d5naa89c1550064c24@mail.gmail.com> References: <3dd3f56a0905010101v7165f7d5naa89c1550064c24@mail.gmail.com> Message-ID: <49FAB465.8000305@optrak.co.uk> Howard Lovatt wrote: > Derek, > > I have found also wanted to extend an abstract class when using enums. > However I ideally didn't want to extend a special enum abstract class, e.g. > > abstract enum Super { ... } // Has enum > > enum extends Super { ... } > > But rather any old abstract class: > > abstract class Super { ... } // No enum > > enum extends Super { ... } > > What is the rational for only allowing abstract enum to be extended rather > than a plain abstract class. > > -- Howard. > Because Enum isn't a trait as in Scala and existing enums are all subclasses of Enum? Mark From howard.lovatt at iee.org Fri May 1 02:16:48 2009 From: howard.lovatt at iee.org (Howard Lovatt) Date: Fri, 1 May 2009 19:16:48 +1000 Subject: PROPOSAL: language support for JSR 292 Message-ID: <3dd3f56a0905010216j69d36ab5q551b2a17480a9082@mail.gmail.com> Hi John, Great work on the proposal. There appears to be four controversial points about the proposal: 1. The use of Void as a bottom type; this seems most natural to me and I would like to see this throughout Java (in fact I have suggested this before on I think Alex Buckley's blog). 2. Making InvokeDynamic a normal uninstantiatable type (like Collections); again this seems fine to me, no need for the compiler to issue a warning it doesn't for T extends Collections and that isn't a problem 3. The use of primatives in angle brackets for return types; if people don't like that you could use a cast to indicate return type (like you would for a null argument for example when disambiguating overloaded methods) 4. The throwing of checked exceptions; probably OK, the top level data loggers that I have seen have caught Exception or above so I don't think this will be a problem in practice At a higher level, rather than details of the proposal, it would be a nice addition to have a convenience interface, lets for the sake of argument call it Dynamic, that behaved like a top level class in a dynamic language and you implicitly had to define a private static missingMethod method in any class that implemented Dynamic. Then a class that implemented Dynamic or any class that used an object of type Dynamic would be converted automatically be the compiler to use InvokeDynamic, e.g. your simple example would become: public class Hello implements Dynamic { public void greet( final String... av ) { if ( av.length == 0 ) av = new String[] { "world" }; for ( final String whom : av ) { hail( whom ); // transtated to InvokeDynamic.hail( whom ) by compiler - instance method and this is a Dynamic } } void greeter( final String x ) { System.out.println( "Hello, " + x ); } private static final MethodHandle missingMethod( final CallSite site, final Object... args ) { return ... } // Following two constructs added automatically by the compiler static { Linkage.registerBootstrapMethod("bootstrapInvokeDynamic"); } private static Object bootstrapInvokeDynamic( final CallSite site, final Object... args ) { final MethodHandle target = missingMethod( site, args ); site.setTarget( target ); return MethodHandles.invoke( target, args ); } } Keep up the good work, ?-- Howard. From brucechapman at paradise.net.nz Fri May 1 03:07:17 2009 From: brucechapman at paradise.net.nz (Bruce Chapman) Date: Fri, 01 May 2009 22:07:17 +1200 Subject: PROPOSAL: language support for JSR 292 In-Reply-To: <24E47781-3822-49BE-B147-AA231B1FBA82@sun.com> References: <80FFB064-577D-4CEA-A93A-73C424AAE21B@sun.com> <15e8b9d20903290055p399a724al786f34b8188a62d2@mail.gmail.com> <49D013A3.60505@univ-mlv.fr> <8D7F16CE-69EB-4742-97E4-2B1E88A222BF@Sun.COM> <24E47781-3822-49BE-B147-AA231B1FBA82@sun.com> Message-ID: <49FAC9D5.3060805@paradise.net.nz> resent - didn't make the coin list first/2nd/3rd time. - maybe it was html only? resending as plain text. John Rose wrote: > I have factored out the Dynamic type from the proposal, leaving a > static-only type called InvokeDynamic in its place. Here is the > updated spec (also enclosed FTR): > http://wikis.sun.com/display/mlvm/ProjectCoinProposal John, Do you think you could find someone with more intimate JLS knowledge to help you write this. You seem to be out of your area of (undoubted) expertise here. For example, section 1.2 says " The type name InvokeDynamic may be qualified with any method name whatever, and invoked on any number and type of arguments." which is wrong on the following counts. 1. Type names are qualified by either enclosing types, or package names.(not by method names) 2. Type names are not invoked, methods are. Being a bear of very little brain myself, by the time I have worked out what your words are trying to say, I have completely exhausted my ability to comprehend the proposal. For example I can't decide whether int y = InvokeDynamic.myHashCode(x); // type (Object) -> int returns a MethodHandle of type (Object) -> int, or indirectly invokes a method of unknown name but of that signature on some unspecified class or instance. If the former, then how can it be assigned to an int, and if the latter, I can't see how the target class/object is determined, or the method's name, is determined neither at compile time nor runtime, nor any combination of cooperation between the two? And no, I don't really want you to answer that in a reply, I would like the proposal to be written so that it was obvious. I have found your descriptions of what happens in the JVM to be very lucid - It would be wonderful if this proposal was at least half as such. completely confuzzled. Bruce > > The type java.dyn.InvokeDynamic is a uninstatiable class (like > Collections or Arrays) with no apparent methods. However, the compiler > treats it has if it had an infinite supply of static methods of all > names and signatures, for which it generates invokedynamic > instructions instead of invokestatic instructions. > > By removing the value type Dynamic from the base proposal, we serve > the immediate need for system programming on top of JSR 292, while > deferring the question (a truly absorbing and important question) of > integrating dynamic values with Java's type system. > > -- John > > P.S. The factored-out parts, about interface Dynamic and its > interesting rules for conversion and method invocation, are placed here: > http://wikis.sun.com/display/mlvm/InterfaceDynamic > > And, should you have an appetite for even more of the same, some rough > notes a fuller integration of Java with dynamic types is here: > http://wikis.sun.com/display/mlvm/DynamicJava > > P.P.S. Here is a text-only copy of the basic proposal: > > > ------------------------------------------------------------------------ > > > From brucechapman at paradise.net.nz Fri May 1 03:25:44 2009 From: brucechapman at paradise.net.nz (Bruce Chapman) Date: Fri, 01 May 2009 22:25:44 +1200 Subject: PROPOSAL: Abstract enums (version 2) In-Reply-To: <3dd3f56a0905010101v7165f7d5naa89c1550064c24@mail.gmail.com> References: <3dd3f56a0905010101v7165f7d5naa89c1550064c24@mail.gmail.com> Message-ID: <49FACE28.4030402@paradise.net.nz> Howard Lovatt wrote: > Derek, > > I have found also wanted to extend an abstract class when using enums. > However I ideally didn't want to extend a special enum abstract class, e.g. > > abstract enum Super { ... } // Has enum > > enum extends Super { ... } > > But rather any old abstract class: > > abstract class Super { ... } // No enum > > enum extends Super { ... } > > What is the rational for only allowing abstract enum to be extended rather > than a plain abstract class. > Because if an enum could extend any abstract class, then it wouldn't always be possible to also extend java.lang.Enum>, and the language spec says (currently) "The direct superclass of an enum type named /E/ is |Enum"|, and Enum's class apidoc says "This is the common base class of all Java language enumeration types." Bruce > -- Howard. > > From Ulf.Zibis at gmx.de Fri May 1 04:05:03 2009 From: Ulf.Zibis at gmx.de (Ulf Zibis) Date: Fri, 01 May 2009 13:05:03 +0200 Subject: Submission: switch (...) instanceof feature In-Reply-To: <21950339.1241161760435.JavaMail.root@elwamui-hound.atl.sa.earthlink.net> References: <21950339.1241161760435.JavaMail.root@elwamui-hound.atl.sa.earthlink.net> Message-ID: <49FAD75F.2080503@gmx.de> Am 01.05.2009 09:09, Derek Foster schrieb: > I notice that the example you gave is actually an argument for an "if" that respects instanceOf, rather than a 'switch' that does. It seems to me like an abuse of notation to use a 'switch' in a case like this where only one decision (it is or it isn't a subtype of a given type) is being made. > Yes, in this simple example you are potentially right, if you ignore the 3rd case, when Object o is nor String nor Charset type AND accept the casting in the "else branch". But keep in mind, that there potentially could be more types to switch from. In other words, please provide code sample using 'if instanceof' syntax which would fulfil the needs of given method "Charset lookup(String lowCanonical)", which completely omits casting. > Although I am skeptical of the 'switch instanceof' feature, for the reasons I outlined below, Where ??? -Ulf > I would very much like to see Java implement the 'if instanceof' feature that is implied in the proposal, and which various people have been suggesting, so that this very common coding pattern: > > if (foo instanceof Bar) { > Bar bar = (Bar)foo; > doSomethingWith(bar); > } > > could be simplified to: > > if (foo instanceof Bar) { > doSomethingWith(foo); > } > > with no loss of type safety. It seems to me that your example would be more readable with such a construct than it is with the 'switch instanceof' feature. > > I had intended to submit a proposal along these lines myself, but simply ran out of time to put it together. Still, it seems to me that there's been widespread agreement on the list that the 'if instanceof' sub-proposal is a good idea. > > Derek > > > From brucechapman at paradise.net.nz Fri May 1 04:06:35 2009 From: brucechapman at paradise.net.nz (Bruce Chapman) Date: Fri, 01 May 2009 23:06:35 +1200 Subject: PROPOSAL: Abstract enums (version 2) In-Reply-To: <24400889.1241158807692.JavaMail.root@elwamui-hound.atl.sa.earthlink.net> References: <24400889.1241158807692.JavaMail.root@elwamui-hound.atl.sa.earthlink.net> Message-ID: <49FAD7BB.8090200@paradise.net.nz> snip > shall be modified to read: > > "A non-abstract enum type named E has a superclass (either direct or indirect via one or more abstract enums) of Enum." > > > If a non abstract enum E extends an abstract one, and E has a superclass of Enum (as opposed to Enum) , then the abstract one MUST have a type parameter to make that all happen. abstract enum Super> { ... } enum E extends Super { ... } Should this type parameter be explicit or implicit? - guess since enums have an explicit extends, abstract ones could have an explicit type parameter. your compilation section chooses implicit and says abstract enum Foo { ,,, } shall be desugared to code resembling: @AbstractEnum abstract class Foo> extends Enum { But I think it should be abstract class Foo> extends Enum { re @AbstractAnnotation I think you are confusing annotations in source files, with byte code annotations which are different. I don't think you'd need a new annotation (of either sort) because the bytecode for an abstract enum could have both the normal abstract annotation/modifier, and the existing enum one, allowing the compiler to correctly determine that it was in fact an abstract enum. lastly, Could the abstract enum have type parameters, such that declared methods were type polymorphic? (You enum for database table columns comes to mind here) and if so, could the methods be abstract thereby forcing the concrete enum to implement it? The basic argument here is that if you are fixing enums to be consistent with the rest of the language in terms of inheritance, then maybe you should be in terms of type polymorphism as well. If you did, it would put a different slant on the implicit/explicit type parameter issue discussed above. Other than those issues, this proposal is looking good by me. Bruce From forax at univ-mlv.fr Fri May 1 05:57:54 2009 From: forax at univ-mlv.fr (=?ISO-8859-1?Q?R=E9mi_Forax?=) Date: Fri, 01 May 2009 14:57:54 +0200 Subject: Points about language support for 292 In-Reply-To: <49FA2C4F.7060800@sun.com> References: <49FA22EC.6070208@sun.com> <15e8b9d20904301523y7c381671oba6328fcd5c91893@mail.gmail.com> <49FA2C4F.7060800@sun.com> Message-ID: <49FAF1D2.10604@univ-mlv.fr> Alex Buckley a ?crit : > Neal Gafter wrote: > >> On Thu, Apr 30, 2009 at 3:15 PM, Alex Buckley > > wrote: >> >> Neal: InvokeDynamic IS now a reference type. Regarding <..> to indicate >> return type for a dynamic call site, how does C# denote that? >> >> It doesn't. A dynamic invocation, from the point of view of C#, returns >> a value of type dynamic. The hoped-for return type isn't encoded into >> the invocation. >> > > The utility of a Dynamic type is high. The utility of values of Dynamic > type is not high, in my view. Coin's support for 292 is limited, and > does not include general manipulation of non-Java objects in the Java > language. I respect that you believe the time has come for general > manipulation of non-C# objects in the C# language. > > Alex > > Agree even if I think that language developers should eat their own dog food. Question: why do we need to use a type InvokeDynamic ? The invokedynamic instruction is a function call, so I propose to use a syntax more close to a function call, something like: $aDynamicFunction(arg1, arg2) Now, the problem of the return type. I propose the following rules: - if the dynamic call is the righ part of an assignation, the return type is the type of the lhs. int value = $aDynamicFunction(param1, param2) // -> int - if the dynamic call is prefixed by a cast, the return type is the type of the cast (note that this rule doesn't exist for generics) (double)$aDynamicFunction(param1, param2) // -> double - else the return type is Object. R?mi From Alex.Buckley at Sun.COM Fri May 1 10:57:00 2009 From: Alex.Buckley at Sun.COM (Alex Buckley) Date: Fri, 01 May 2009 10:57:00 -0700 Subject: Points about language support for 292 In-Reply-To: <49FAF1D2.10604@univ-mlv.fr> References: <49FA22EC.6070208@sun.com> <15e8b9d20904301523y7c381671oba6328fcd5c91893@mail.gmail.com> <49FA2C4F.7060800@sun.com> <49FAF1D2.10604@univ-mlv.fr> Message-ID: <49FB37EC.7090202@sun.com> R?mi Forax wrote: > Question: why do we need to use a type InvokeDynamic ? > > The invokedynamic instruction is a function call, > so I propose to use a syntax more close to a function call, > something like: > > $aDynamicFunction(arg1, arg2) There are so many implications of blindly inventing this new syntax, I don't know where to start. Java doesn't have the concept of a function or a function call, so you need to define it. If the answer is "Function call just translates to an invokedynamic instruction", then you've introduced a new kind of expression where an existing one - method invocation - would do. > Now, the problem of the return type. > I propose the following rules: > - if the dynamic call is the righ part of an assignation, the return type > is the type of the lhs. > int value = $aDynamicFunction(param1, param2) // -> int > > - if the dynamic call is prefixed by a cast, the return type is the > type of the cast (note that this rule doesn't exist for generics) > (double)$aDynamicFunction(param1, param2) // -> double > > - else the return type is Object. You know I am suspicious of inference :-) The cast idea is appealing at first but it breaks our old friend, Tennent's Correspondence Principle. You cannot write: int x = (int)InvokeDynamic.foo(..); and later decide to introduce some abstraction: int x = (int)m(); ... Object m() { return InvokeDynamic.foo(..); } because Object doesn't cast to int very well. Your method would have to be: InvokeDynamic m() { return (InvokeDynamic)InvokeDynamic.foo(...); } which might be, well, alright, OK, it's not the end of the world. A default return type of Object is well established, of course. Alex From John.Rose at Sun.COM Fri May 1 12:06:51 2009 From: John.Rose at Sun.COM (John Rose) Date: Fri, 01 May 2009 12:06:51 -0700 Subject: Points about language support for 292 In-Reply-To: <49FA22EC.6070208@sun.com> References: <49FA22EC.6070208@sun.com> Message-ID: <63FB0915-72C2-4BA6-B86F-2D473C7BAF94@sun.com> On Apr 30, 2009, at 3:15 PM, Alex Buckley wrote: > Hi John, > > 1.1: "The complete lack of supertypes makes it an unusual type, on a > par > with Object." > > But InvokeDynamic is defined as a class with a superclass of Object a > few lines earlier. The text in () looks redundant. My bad; I missed the edit; fixed now in the wiki. I replaced that parenthesis by: > (Note that InvokeDynamic is not useful as a reference type. Like > java.util.Collections, it is a non-instantiated class.) Some other comments about InvokeDynamic are also cleaned up, as replacing "abstract" by "non-instantiated". > 1.5: As the JVM executes, checked exceptions may be produced by any > invokedynamic call. > > Please don't put "JVM" and "checked exceptions" in the same sentence! > More importantly, I don't agree with "the possibility of a missed > catch > of a checked exception is not considered to be a hazard." An exception > handler further up the stack that catches unchecked exceptions will > miss > it, and the program will in all likelihood stop. I'll reformulate; of course it's a hazard, but the point is that dynamically checked languages do not have statically checked exceptions, and (therefore) neither does InvokeDynamic. Dynamic languages rely on programmer foresight (that estimable faculty) to put the right catches around potentially throwing code. So must the loophole into Java. > In other words, this is a relaxation too far of static exception > checking. One option is to have InvokeDynamic.foo() claim to throw all > possible checked exceptions. If one actually leaks back to the call > site > from a dynamic language's runtime, it should be caught right there. Should be; and the programmer who is using InvokeDynamic will doubtless do so, or bear the consequences of buggy code. Neal's suggestion (based on his experience with closure types) is more feasible. The return type parameter (for both MethodHandle and InvokeDynamic) should be able to express the checked exceptions thrown by the call. I wish we had something like optional throws clauses for type variables but we don't. As grody hack, more optional type parameters could express, to the surrounding Java code, the checked exceptions emanating from an invokedynamic: InvokeDynamic.foo(bar, baz); But this seems pointless to me. Since it's a dynamic call, the quality of this additional information cannot be determined mechanically. (The Java compiler could decorate the call site with elaborate runtime checks. See below for details. I this would be wasted effort.) The design as it stands lets the exceptions flow out of the call site, without attempting to document them there. It allows the programmer to write catches for the relevant ones, and assumes that the programmer will write all the necessary ones, without help from static exception checking: try { InvokeDynamic.foo(bar, baz); } } catch (IOException x) { /* programmer-written logic here*/ } } catch (AnotherBadException x) { /* more logic here*/ } That's status quo for dynamic languages! > Another option, and perhaps a better one since it partitions > InvokeDynamic off from checked exceptions entirely, is to specify that > its infinite static methods can throw only unchecked exceptions (or > one > in particular, if you like). An implementation would have to wrap > checked exceptions. Sorry, wrapping checked exceptions is a non-starter for 292. Wrapping of all sorts is one of the reasons reflection is unusably slow for dynamic language implementation. -- John P.S. Here's what checked exception verification would look like: try { InvokeDynamic.foo(bar, baz); // the following catches could be invisibly added to every invokedynamic instruction generated by javac: } catch (IOException x) { throw x; } } catch (AnotherBadException x) { throw x; } } catch (RuntimeException x) { throw x; } } catch (Exception x) { throw new InternalError("didn't you forget something?", x); } From John.Rose at Sun.COM Fri May 1 12:10:25 2009 From: John.Rose at Sun.COM (John Rose) Date: Fri, 01 May 2009 12:10:25 -0700 Subject: PROPOSAL: language support for JSR 292 In-Reply-To: <0a78e808aead077cd9f7cb5c7934fdd9.squirrel@wmail.gradsoft.ua> References: <80FFB064-577D-4CEA-A93A-73C424AAE21B@sun.com> <15e8b9d20903290055p399a724al786f34b8188a62d2@mail.gmail.com> <49D013A3.60505@univ-mlv.fr> <8D7F16CE-69EB-4742-97E4-2B1E88A222BF@Sun.COM> <24E47781-3822-49BE-B147-AA231B1FBA82@sun.com> <0a78e808aead077cd9f7cb5c7934fdd9.squirrel@wmail.gradsoft.ua> Message-ID: <2C286F19-A905-4D6C-9DA6-C7296FC4A919@Sun.COM> On Apr 29, 2009, at 11:39 PM, Ruslan Shevchenko wrote: > Why not make MethodHandle final ? So it can be subclassed. -- John From rssh at gradsoft.com.ua Fri May 1 12:22:12 2009 From: rssh at gradsoft.com.ua (Ruslan Shevchenko) Date: Fri, 1 May 2009 22:22:12 +0300 (EEST) Subject: PROPOSAL: language support for JSR 292 In-Reply-To: <2C286F19-A905-4D6C-9DA6-C7296FC4A919@Sun.COM> References: <80FFB064-577D-4CEA-A93A-73C424AAE21B@sun.com> <15e8b9d20903290055p399a724al786f34b8188a62d2@mail.gmail.com> <49D013A3.60505@univ-mlv.fr> <8D7F16CE-69EB-4742-97E4-2B1E88A222BF@Sun.COM> <24E47781-3822-49BE-B147-AA231B1FBA82@sun.com> <0a78e808aead077cd9f7cb5c7934fdd9.squirrel@wmail.gradsoft.ua> <2C286F19-A905-4D6C-9DA6-C7296FC4A919@Sun.COM> Message-ID: > On Apr 29, 2009, at 11:39 PM, Ruslan Shevchenko wrote: >> Why not make MethodHandle final ? > > So it can be subclassed. > And what possibility to subclassing MethodHandle give us ? Are received capabilities so big, that we can break usual inheritance rules for this ? > -- John > From Alex.Buckley at Sun.COM Fri May 1 12:38:37 2009 From: Alex.Buckley at Sun.COM (Alex Buckley) Date: Fri, 01 May 2009 12:38:37 -0700 Subject: Points about language support for 292 In-Reply-To: <63FB0915-72C2-4BA6-B86F-2D473C7BAF94@sun.com> References: <49FA22EC.6070208@sun.com> <63FB0915-72C2-4BA6-B86F-2D473C7BAF94@sun.com> Message-ID: <49FB4FBD.8020904@sun.com> John Rose wrote: > The design as it stands lets the exceptions flow out of the call site, > without attempting to document them there. It allows the programmer to > write catches for the relevant ones, and assumes that the programmer > will write all the necessary ones, without help from static exception > checking: > > try { InvokeDynamic.foo(bar, baz); } > } catch (IOException x) { /* programmer-written logic here*/ } > } catch (AnotherBadException x) { /* more logic here*/ } > > That's status quo for dynamic languages! I'm really after a mandatory catch(Exception) block for any try block that contains InvokeDynamic. An ignored checked exception is THAT dangerous. If the programmer catches more specific checked exceptions first, that's great. If the programmer wraps Exception in RuntimeException always, or some of the time, or never, that's great too, but let them document it locally. Alex From jeroen at lexau.org Fri May 1 12:44:19 2009 From: jeroen at lexau.org (Jeroen van Maanen) Date: Fri, 01 May 2009 21:44:19 +0200 Subject: Submission: switch (...) instanceof feature In-Reply-To: <21950339.1241161760435.JavaMail.root@elwamui-hound.atl.sa.earthlink.net> References: <21950339.1241161760435.JavaMail.root@elwamui-hound.atl.sa.earthlink.net> Message-ID: <49FB5113.3050107@lexau.org> I agree that "if (... instanceof ...)" is more readable than the extension of "switch" that I proposed originally. I believe that this feature that avoids an unnecessary new name and cast would be of great benefit to the Java language. Jeroen Derek Foster schreef: > I notice that the example you gave is actually an argument for an "if" that respects instanceOf, rather than a 'switch' that does. It seems to me like an abuse of notation to use a 'switch' in a case like this where only one decision (it is or it isn't a subtype of a given type) is being made. > > Although I am skeptical of the 'switch instanceof' feature, for the reasons I outlined below, I would very much like to see Java implement the 'if instanceof' feature that is implied in the proposal, and which various people have been suggesting, so that this very common coding pattern: > > if (foo instanceof Bar) { > Bar bar = (Bar)foo; > doSomethingWith(bar); > } > > could be simplified to: > > if (foo instanceof Bar) { > doSomethingWith(foo); > } > > with no loss of type safety. It seems to me that your example would be more readable with such a construct than it is with the 'switch instanceof' feature. > > I had intended to submit a proposal along these lines myself, but simply ran out of time to put it together. Still, it seems to me that there's been widespread agreement on the list that the 'if instanceof' sub-proposal is a good idea. > > Derek > > > > > > -----Original Message----- >> From: Ulf Zibis >> Sent: Apr 22, 2009 5:17 AM >> To: Derek Foster >> Cc: Gabriel Belingueres , Jeroen van Maanen , coin-dev at openjdk.java.net >> Subject: Re: Submission: switch (...) instanceof feature >> >> Am 22.04.2009 06:55, Derek Foster schrieb: >>> Like Gabriel, I have severe reservations about this proposal. I am concerned that it will encourage people to avoid the common OOP "best practice" of using virtual method dispatch in favor of doing an explicit "switch" on each subtype of a type, in cases where doing so is not necessary. >>> >>> I concede that there are a few (FEW!) places where doing the equivalent of a switch on instances of a type is necessary (for instance, if the type is in a library you don't have the ability to change). I can see some value in this proposal for that purpose. However, I would very much not like to see use of this construct become commonplace. I already see too many instances of people doing the equivalent of "if (object.type == FOO) {doThis(); } else if (object.type == BAR) { doThat(); }" instead of writing "object.doSomething();" >>> >>> >> I like to provide an example where >> >> "object.doSomething();" >> >> doesn't work: >> >> synchronized Charset lookup(String lowCanonical) { >> // cache is initialized with available Charset classes names >> Object o = cache.get(lowCanonical); >> // Check cache first >> if (o instanceof String) { >> // Instantiate new charset >> Charset cs = newCharset((String)o, lowCanonical); >> // Cache it >> if (cs != null) >> cache.put(lowCanonical, cs); >> return cs; >> } >> return (Charset)o; >> } >> >> >> This would look much nicer, as it avoids casting: >> >> synchronized Charset lookup(String lowCanonical) { >> // cache is initialized with available Charset classes names >> switch (Object o = cache.get(lowCanonical) instanceof ?) { >> case String : >> // Instantiate new charset >> Charset cs = newCharset(o, lowCanonical); >> // Cache it >> if (cs != null) >> cache.put(lowCanonical, cs); >> return cs; >> case Charset : >> return o; >> } >> } >> >> >> Refer: >> https://java-nio-charset-enhanced.dev.java.net/source/browse/java-nio-charset-enhanced/tags/milestone4/src/sun/nio/cs/FastCharsetProvider.java?rev=684&view=markup >> http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6790402 >> http://mail.openjdk.java.net/pipermail/coin-dev/2009-March/001182.html >> http://mail.openjdk.java.net/pipermail/coin-dev/2009-April/001328.html >> >> - My example could also be smartly coded without switch..case statement, >> if we would enhance if statement accordingly >> - I also would like to have possibility to declare variables in if >> clause, like it's possible in for clause: >> >> if ((Object o = cache.get(lowCanonical)) instanceof String) >> ... ; >> else if (o instanceof Charset) >> ... ; >> >> >> -Ulf >> >> >>> Derek >>> >>> -----Original Message----- >>> >>>> From: Gabriel Belingueres >>>> Sent: Mar 30, 2009 7:31 AM >>>> To: Jeroen van Maanen >>>> Cc: coin-dev at openjdk.java.net >>>> Subject: Re: Submission: switch (...) instanceof feature >>>> >>>> IMO I'm against this. >>>> >>>> First, it is against current best practices for the design of >>>> object-oriented software to make easier to code something with a case >>>> statement on types/classes. >>>> >>>> Second: >>>> void log(Object object) { >>>> switch (object) instanceof { >>>> case String: >>>> logger.debug("'" + object + "'"); >>>> case Date: >>>> logger.debug(object.getTime()); >>>> case void: >>>> logger.debug("null"); >>>> default: >>>> logger.debug("<" + object.toString() + ">"); >>>> } >>>> } >>>> >>>> It think it is clearer (when possible) writing it with several >>>> overloaded methods and double dispatching. >>>> >>>> .... >>>> > From John.Rose at Sun.COM Fri May 1 13:02:45 2009 From: John.Rose at Sun.COM (John Rose) Date: Fri, 01 May 2009 13:02:45 -0700 Subject: PROPOSAL: language support for JSR 292 In-Reply-To: <49F976B2.6020800@paradise.net.nz> References: <80FFB064-577D-4CEA-A93A-73C424AAE21B@sun.com> <15e8b9d20903290055p399a724al786f34b8188a62d2@mail.gmail.com> <49D013A3.60505@univ-mlv.fr> <8D7F16CE-69EB-4742-97E4-2B1E88A222BF@Sun.COM> <24E47781-3822-49BE-B147-AA231B1FBA82@sun.com> <49F976B2.6020800@paradise.net.nz> Message-ID: On Apr 30, 2009, at 3:00 AM, Bruce Chapman wrote: > John Rose wrote: >> >> I have factored out the Dynamic type from the proposal, leaving a >> static-only type called InvokeDynamic in its place. Here is the >> updated spec (also enclosed FTR): >> http://wikis.sun.com/display/mlvm/ProjectCoinProposal > John, > > Do you think you could find someone with more intimate JLS knowledge > to help you write this. You seem to be out of your area of > (undoubted) expertise here. I am indeed working with Alex et al on this. > For example, section 1.2 says > " The type name InvokeDynamic may be qualified with any method name > whatever, and invoked on any number and type of arguments." > > which is wrong on the following counts. > 1. Type names are qualified by either enclosing types, or package > names.(not by method names) > 2. Type names are not invoked, methods are. "Qualified with" != "Qualified by", but the former phrase may indeed not have a precise the meaning w.r.t. the JLS. Static methods are invoked via qualified names; that's how invokedynamic call sites will appear in Java code. Sorry to leave you guessing as to who's the qualifier and who's the qualified. We will work to align the language better with JLS. -- John From John.Rose at Sun.COM Fri May 1 13:09:36 2009 From: John.Rose at Sun.COM (John Rose) Date: Fri, 01 May 2009 13:09:36 -0700 Subject: PROPOSAL: language support for JSR 292 In-Reply-To: <49F9F706.3030909@univ-mlv.fr> References: <80FFB064-577D-4CEA-A93A-73C424AAE21B@sun.com> <6F835C91-A2F2-4050-BD03-DB1B462C2B4F@sun.com> <49D5C7E3.50801@sun.com> <2B41E202-273B-4876-BEB4-2C1BADA1A22E@Sun.COM> <49F97577.4090002@sun.com> <49F9F706.3030909@univ-mlv.fr> Message-ID: <63F92CB0-1A9F-49AC-92C6-D74AC6036010@Sun.COM> On Apr 30, 2009, at 12:07 PM, R?mi Forax wrote: > The first question is what is the goal of such construct. The goal is preserving the utility of Java as a system programming language for the JVM, given changes in the bytecode architecture. > > If the goal is to be able to call any dynamic languages from Java, > this is in my opinion a nice dream but that means > mixing different language semantics. > > If the goal is to help dynamic language developers, > the question is why a language developer code in Java > and not in its own language. Very few languages are completely self-hosting. Most have lots of systems-level code in them (C or assembly, in the non-Java world.) It's reasonable to ask the systems programming language to provide some access to the capabilities of the underlying machine. Note how useful asm statements are in C for system building. (The present proposal is a much smaller and better-structured loophole than asm, of course.) > If the goal is to simplify reflection or dynamic invocation > in Java, the dynamic type of C# is what we want. I agree, but let's do one thing at a time. This is support for the system programmers, not language mixing for application programmers. For example, I am using polymorphic method handle invocation all the time in the JSR 292 system support code. Having Java support me there saves me from having to drop down into bytecode weaving or (worse) changing the C++ code of the JVM. -- John From John.Rose at Sun.COM Fri May 1 13:10:08 2009 From: John.Rose at Sun.COM (John Rose) Date: Fri, 01 May 2009 13:10:08 -0700 Subject: PROPOSAL: language support for JSR 292 In-Reply-To: References: <80FFB064-577D-4CEA-A93A-73C424AAE21B@sun.com> <6F835C91-A2F2-4050-BD03-DB1B462C2B4F@sun.com> <49D5C7E3.50801@sun.com> <2B41E202-273B-4876-BEB4-2C1BADA1A22E@Sun.COM> <49F97577.4090002@sun.com> <49F9F706.3030909@univ-mlv.fr> Message-ID: On Apr 30, 2009, at 12:56 PM, Ruslan Shevchenko wrote: > This is for language developers, which want translate their language > expressions to bytecode via java as first set (as cfront compiler, > which > translate C++ programs to C, not to native code). I. e. Java in such > case is 'C' for JVM. Yes, thanks. From Joe.Darcy at Sun.COM Fri May 1 13:13:28 2009 From: Joe.Darcy at Sun.COM (Joe Darcy) Date: Fri, 01 May 2009 13:13:28 -0700 Subject: Points about language support for 292 In-Reply-To: <49FB4FBD.8020904@sun.com> References: <49FA22EC.6070208@sun.com> <63FB0915-72C2-4BA6-B86F-2D473C7BAF94@sun.com> <49FB4FBD.8020904@sun.com> Message-ID: <49FB57E8.8020808@sun.com> On 05/01/09 12:38 PM, Alex Buckley wrote: > John Rose wrote: > >> The design as it stands lets the exceptions flow out of the call site, >> without attempting to document them there. It allows the programmer to >> write catches for the relevant ones, and assumes that the programmer >> will write all the necessary ones, without help from static exception >> checking: >> >> try { InvokeDynamic.foo(bar, baz); } >> } catch (IOException x) { /* programmer-written logic here*/ } >> } catch (AnotherBadException x) { /* more logic here*/ } >> >> That's status quo for dynamic languages! >> > > I'm really after a mandatory catch(Exception) block for any try block > that contains InvokeDynamic. An ignored checked exception is THAT > dangerous. If the programmer catches more specific checked exceptions > first, that's great. If the programmer wraps Exception in > RuntimeException always, or some of the time, or never, that's great > too, but let them document it locally. > > Yes, for better or worse the Java source language includes checked exceptions and InvokeDynamic call sites should not be exempt from participating in that rule. (The existing holes/bugs in this area, like Constructor.newInstance should not be expanded.) -Joe From John.Rose at Sun.COM Fri May 1 13:24:46 2009 From: John.Rose at Sun.COM (John Rose) Date: Fri, 01 May 2009 13:24:46 -0700 Subject: PROPOSAL: language support for JSR 292 In-Reply-To: <3dd3f56a0905010216j69d36ab5q551b2a17480a9082@mail.gmail.com> References: <3dd3f56a0905010216j69d36ab5q551b2a17480a9082@mail.gmail.com> Message-ID: <7CF65842-67BF-490F-ADE4-86F8912C1A42@Sun.COM> On May 1, 2009, at 2:16 AM, Howard Lovatt wrote: > Great work on the proposal. Thanks. > There appears to be four controversial points about the proposal: > > 1. The use of Void as a bottom type; this seems most natural to me and > I would like to see this throughout Java (in fact I have suggested > this before on I think Alex Buckley's blog). I really don't want to get into the middle of the Void vs. Null debate; I just want one to win so I can use it! :-) > 2. Making InvokeDynamic a normal uninstantiatable type (like > Collections); again this seems fine to me, no need for the compiler to > issue a warning it doesn't for T extends Collections and that isn't a > problem I think that's settling down. Some leftovers from the Dynamic type proposal complicated the discussion (to an extent that surprised me!). > 3. The use of primatives in angle brackets for return types; if people > don't like that you could use a cast to indicate return type (like you > would for a null argument for example when disambiguating overloaded > methods) Yes. There are several ways to do it: Faux type parameter, target typing (via cast or more generally), an extra reified type argument, a whole new syntax (the very first prototype used backquote: yech). Although the faux type parameter impinges on true type parameters (as Neal objected), I think it's the least irregular way to express what's needed, and one of the more intuitive (to those who already know Java generics). > 4. The throwing of checked exceptions; probably OK, the top level data > loggers that I have seen have caught Exception or above so I don't > think this will be a problem in practice Yes, we're thrashing that one out now. Good recap; thanks. > At a higher level, rather than details of the proposal, it would be a > nice addition to have a convenience interface, lets for the sake of > argument call it Dynamic, that behaved like a top level class in a > dynamic language and you implicitly had to define a private static > missingMethod method in any class that implemented Dynamic. Interesting. There are lots of degrees of freedom in integrating static Java with dynamic languages. The present proposal is intended to be minimal, but there is lots to dream about here for the future. > Then a > class that implemented Dynamic or any class that used an object of > type Dynamic would be converted automatically be the compiler to use > InvokeDynamic, e.g. your simple example would become: So Main would inherit the ability to form invokedynamic calls from Dynamic. I think that would make many (not all) Java programmers feel very insecure about the meaning of the code in such a scope. My hope right now is to lay down a good enough foundation to enable us to play with such things in Java 7. -- John From John.Rose at Sun.COM Fri May 1 13:35:09 2009 From: John.Rose at Sun.COM (John Rose) Date: Fri, 01 May 2009 13:35:09 -0700 Subject: PROPOSAL: language support for JSR 292 In-Reply-To: <49F97577.4090002@sun.com> References: <80FFB064-577D-4CEA-A93A-73C424AAE21B@sun.com> <6F835C91-A2F2-4050-BD03-DB1B462C2B4F@sun.com> <49D5C7E3.50801@sun.com> <2B41E202-273B-4876-BEB4-2C1BADA1A22E@Sun.COM> <49F97577.4090002@sun.com> Message-ID: <6AD57455-555C-48A8-A01C-4A737BBF0B71@Sun.COM> On Apr 30, 2009, at 2:55 AM, Maurizio Cimadamore wrote: > 1) I'd strongly recommend to forbid usage of InvokeDynamic type in the > following contexts: > > (i) extends clause (e.g. class MyDynamic extends InvokeDynamic) > (ii) type-parameter bound (e.g. class Foo Comparable>) > (iii) wildcard type-argument (e.g. Foo 2) I agree with Neal that the usage of Void feels a bit hacky. If you > need null values to be typed differently then I agree that probably > adding java.lang.Null would be the best thing to do, rather than > overriding the semantics of Void. Yes, it's hacky. I'd be happy to fold null support into the proposal (though not this month). Since there seems to be support for adding java.lang.Null, I'll retract the Void feature from the spec: 1.4 For the purposes of determining the descriptor of the invokedynamic instruction, null arguments (unless casted to some other type) are deemed to be of reference type java.lang.Null, if this type exists. The type Null will appear only to the bootstrap method, and will serve notice that the call site contains an untyped null reference, rather than an explicitly typed reference. InvokeDynamic.myPrintLine(null); // type (Null) -> Object InvokeDynamic.foo((String)null, null); // type (String, Null) -> void > 3) InvokeDynamic and type-inference. It seems like you can optionally > provide a type-parameter denoting the dynamic call's expected return > type. This is fine, as long as it is consistent with JLS 15.12.2.7 and > 15.12.2.8. Thanks for the citations. There's no interaction with these sections because there is no test for applicability, and none of the implicit methods of InvokeDynamic have type parameters. Both 1.2 and 2.2 should say more clearly that the type of an implicit method is derived from the erasure of the arguments, and 1.3/2.3 should say that the return type of the method is derived from the erasure of the declared return type (or Object by default). If you use generic types around a dynamic call site, you'll get lots of unchecked warnings, and this is a feature not a bug. > In your examples it seems like the usage of such type > argument is completely optional. If specified, it provides additional > info about the dynamic call site such that, e.g. the following code > will > be rejected: > > int i = InvokeDynamic.myDynMethod("Hello!"); // type > (String) -> > String > > Can this optional type argument be inferred so that the following > method > call will behave identically? I'd rather have the return type of a dynamic call site be clearly marked, or default to a fixed type. (I would prefer Dynamic, but since that doesn't exist now, Object will do fine.) That provides a clearer demarcation between the statically typed surrounding code and the dynamic call site. > int i = InvokeDynamic.myDynMethod("Hello!"); // type (String) -> > String (Comment should be type (String) -> Object, of course.) > > > [I did some testing and it seems like inference is not supported - the > above line will give an incompatible types error, found Object, > expecetd > int] Yes. Such things will work automagically for receiver calls to dynamic, but not in the present proposal: Dynamic d = ...; int i = d.myDynMethod("Hello!"); // type (Dynamic, String) -> Dynamic ~> int // http://wikis.sun.com/display/mlvm/InterfaceDynamic > If so, you are mimicking an under-constrained type-variable (a method > type variable that cannot be inferred from actual arguments passed to > the method). This raises a question: what happens when the dynamic > call > site does not appear within an assignment context, e.g. > > InvokeDynamic.myDynMethod("Hello!"); > > or > > int i = (Integer)InvokeDynamic.myDynMethod("Hello!"); 1.3 and 2.3 state that the default return type is Object, which serves in that role as a universal dynamic type. > An alternative would be to pass to InvokeDynamic the return type Class > object corresponding the to expected return type as the first > parameter > of the dynamic call: > > InvokeDynamic.myDynMethod(int.class, "Hello!"); // type (String) -> > int > > This has the advantage of not requiring a separate language > extension in > order to allow primitive type (and void) to be specified as > parameter types. The type of int.class is not Class but Class, which means it doesn't really say what it appears to say. Plus, having an extra leading argument, but not passing it as a real argument, would be a highly confusing variation on the normal meaning of method argument lists. As I said to Howard Lovatt, I think a faux type parameter, while not perfect, is the best of the known choices. -- John From forax at univ-mlv.fr Fri May 1 13:46:03 2009 From: forax at univ-mlv.fr (=?ISO-8859-1?Q?R=E9mi_Forax?=) Date: Fri, 01 May 2009 22:46:03 +0200 Subject: Points about language support for 292 In-Reply-To: <49FB57E8.8020808@sun.com> References: <49FA22EC.6070208@sun.com> <63FB0915-72C2-4BA6-B86F-2D473C7BAF94@sun.com> <49FB4FBD.8020904@sun.com> <49FB57E8.8020808@sun.com> Message-ID: <49FB5F8B.2020805@univ-mlv.fr> Joe Darcy a ?crit : > On 05/01/09 12:38 PM, Alex Buckley wrote: > >> John Rose wrote: >> >> >>> The design as it stands lets the exceptions flow out of the call site, >>> without attempting to document them there. It allows the programmer to >>> write catches for the relevant ones, and assumes that the programmer >>> will write all the necessary ones, without help from static exception >>> checking: >>> >>> try { InvokeDynamic.foo(bar, baz); } >>> } catch (IOException x) { /* programmer-written logic here*/ } >>> } catch (AnotherBadException x) { /* more logic here*/ } >>> >>> That's status quo for dynamic languages! >>> >>> >> I'm really after a mandatory catch(Exception) block for any try block >> that contains InvokeDynamic. An ignored checked exception is THAT >> dangerous. If the programmer catches more specific checked exceptions >> first, that's great. If the programmer wraps Exception in >> RuntimeException always, or some of the time, or never, that's great >> too, but let them document it locally. >> >> >> > > Yes, for better or worse the Java source language includes checked > exceptions and InvokeDynamic call sites should not be exempt from > participating in that rule. > > (The existing holes/bugs in this area, like Constructor.newInstance > should not be expanded.) > > -Joe > I don't agree. You can already fool the compiler, by example, using generics. In that case, the compiler emit an unsafe cast warning. public class ExceptionTest { interface I { void m() throws E; } static class A implements I { public void m() throws IOException { new FileInputStream("hello"); } } public static void main(String[] args) { I i=(I)new A(); i.m(); } } Why not raise a warning saying that InvokeDynamic creates a hole because exceptions are not managed ? R?mi From John.Rose at Sun.COM Fri May 1 14:46:29 2009 From: John.Rose at Sun.COM (John Rose) Date: Fri, 01 May 2009 14:46:29 -0700 Subject: PROPOSAL: language support for JSR 292 In-Reply-To: <15e8b9d20904292014r39b881f2r993bca0d62f8c377@mail.gmail.com> References: <80FFB064-577D-4CEA-A93A-73C424AAE21B@sun.com> <15e8b9d20903290055p399a724al786f34b8188a62d2@mail.gmail.com> <49D013A3.60505@univ-mlv.fr> <8D7F16CE-69EB-4742-97E4-2B1E88A222BF@Sun.COM> <24E47781-3822-49BE-B147-AA231B1FBA82@sun.com> <15e8b9d20904292014r39b881f2r993bca0d62f8c377@mail.gmail.com> Message-ID: <2E5DD45B-7622-4406-A967-C9D9203B914E@Sun.COM> On Apr 29, 2009, at 8:14 PM, Neal Gafter wrote: > These proposals appears to allow primitives and "void" to be used as > generic > type arguments for this special class. This use of the syntax has > nothing > to do with generics. Therefore, I believe it is an abuse of syntax. It's an extension of the syntax, surely. Let me try to unpack "abusive". 1. Is it so ugly as to make it hard for programmers to learn? I think not. And I think the alternatives are more objectionable on that score. 2. It is a bad extension if it interferes with existing or reasonable future uses of that syntax. Will it interfere? It does not now interfere since the JVM knows nothing about generics. It might interfere if in some future Java world generics were to be reified (as in C#), and there were some notation for naming an implicit method (from within magic InvokeDynamic) equipped with type parameters. To call such a method, we would need to give type arguments, and then we'd be embarrassed, since there is already a faux type parameter, the return type. But, shaking those sorts of future scenarios around in my head, I can't come up with one that doesn't have a simple workaround, such as retaining InvokeDynamic in its limited capacity, and adding another more feature-ful source of implicit methods. 3. Is it not self-consistent? In the current design a dynamic call with a type argument appears to the caller as if the referenced implicit method is parameterized by one type parameter, the return type. (The JVM sees something different, naturally.) The ability to specify , and also to drop the type argument altogether, may be viewed as a sugar that means "the implicit method doesn't have a type parameter, instead it has int or Object as a fixed return type". That looks consistent to me. If in some future world we allow primitives somehow to be type arguments, then could stop being sugar, but there would be no change of meaning. Maybe there's some other objection (or meaning to "abusive") that still needs to be pointed out? > If you're going to extend the language to support this special > InvokeDynamic > class, you might as well just define language support for dynamic > invocations directly without the magic class and generic > extensions. I > don't think the current spec for Dynamic fits with the current type > system. > If you are adding special types like InvokeDynamic, I think they > must be > reference types (i.e. a subtype of Object). You should try to get > some > information about what C# has done in this area for "dynamic", as I > believe > it could be applied to Java and result in a clean solution. The magic class, which really functions as an importable keyword, is the simplest way I know to allow the creation of invokedynamic sites. A dynamic type, as in C#, would be another more useful way to create invokedynamic sites, but it would be several orders of magnitude more complex, because of its interactions with static typing, expressions, and the runtime support. > By the way, now is a good time to add the boxed "Null" type, which > has no > instances, referring to the type of null. I don't think this > purpose is > well served by using java.lang.Void. Thanks for that push. I hope that is possible, although touching java.lang.* is difficult. I've thrown my lot in with Null; see the wiki. If the planets do not align for the creation of java.lang.Void in JDK 7, I suppose programmers can decide among themselves to use Void, along with an explicit cast, as (Void)null. If that happens, we'll encourage MOP writers to recognize both Void and anything named "java.lang.Null" as interchangeable names for the null type. -- John From neal at gafter.com Fri May 1 15:38:22 2009 From: neal at gafter.com (Neal Gafter) Date: Fri, 1 May 2009 15:38:22 -0700 Subject: Points about language support for 292 In-Reply-To: <63FB0915-72C2-4BA6-B86F-2D473C7BAF94@sun.com> References: <49FA22EC.6070208@sun.com> <63FB0915-72C2-4BA6-B86F-2D473C7BAF94@sun.com> Message-ID: <15e8b9d20905011538j7ee375b7l2bc6d7be0c84b18c@mail.gmail.com> On Fri, May 1, 2009 at 12:06 PM, John Rose wrote: > Dynamic languages rely on programmer foresight (that estimable > faculty) to put the right catches around potentially throwing code. > So must the loophole into Java. That would be fine if the problem (an uncaught and undeclared checked exception) had no way to leak into otherwise statically typed code, but this proposal does allow such leaks. Java's invariants should be preserved outside of and around (but not necessarily inside) dynamic code. > The design as it stands lets the exceptions flow out of the call site, > without attempting to document them there. It allows the programmer > to write catches for the relevant ones, and assumes that the > programmer will write all the necessary ones, without help from static > exception checking: > > try { InvokeDynamic.foo(bar, baz); } > } catch (IOException x) { /* programmer-written logic here*/ } > } catch (AnotherBadException x) { /* more logic here*/ } > > That's status quo for dynamic languages! Java isn't a dynamic language. It is not legal to put catch (IOException ex) on a try block that can't throw that checked exception (in the JLS sense), so further language changes would be required to allow this. Your spec says "Therefore, it is valid both to catch and not to catch checked exceptions at any dynamic call site." That is not precise enough; you'd need a complete overhaul of JLS section 11.2at the very least, and I suspect the required changes would be quite messy. I think it's better to just say that a dynamic call site throws Throwable (just saying that it throws Exception isn't enough). From forax at univ-mlv.fr Fri May 1 16:04:16 2009 From: forax at univ-mlv.fr (=?ISO-8859-1?Q?R=E9mi_Forax?=) Date: Sat, 02 May 2009 01:04:16 +0200 Subject: PROPOSAL: language support for JSR 292 In-Reply-To: <2E5DD45B-7622-4406-A967-C9D9203B914E@Sun.COM> References: <80FFB064-577D-4CEA-A93A-73C424AAE21B@sun.com> <15e8b9d20903290055p399a724al786f34b8188a62d2@mail.gmail.com> <49D013A3.60505@univ-mlv.fr> <8D7F16CE-69EB-4742-97E4-2B1E88A222BF@Sun.COM> <24E47781-3822-49BE-B147-AA231B1FBA82@sun.com> <15e8b9d20904292014r39b881f2r993bca0d62f8c377@mail.gmail.com> <2E5DD45B-7622-4406-A967-C9D9203B914E@Sun.COM> Message-ID: <49FB7FF0.3030700@univ-mlv.fr> I wonder what import static java.dyn.InvokeDynamic.*; means ? R?mi From Joe.Darcy at Sun.COM Fri May 1 17:30:38 2009 From: Joe.Darcy at Sun.COM (Joseph D. Darcy) Date: Fri, 01 May 2009 17:30:38 -0700 Subject: PROPOSAL: language support for JSR 292 In-Reply-To: <49FB7FF0.3030700@univ-mlv.fr> References: <80FFB064-577D-4CEA-A93A-73C424AAE21B@sun.com> <15e8b9d20903290055p399a724al786f34b8188a62d2@mail.gmail.com> <49D013A3.60505@univ-mlv.fr> <8D7F16CE-69EB-4742-97E4-2B1E88A222BF@Sun.COM> <24E47781-3822-49BE-B147-AA231B1FBA82@sun.com> <15e8b9d20904292014r39b881f2r993bca0d62f8c377@mail.gmail.com> <2E5DD45B-7622-4406-A967-C9D9203B914E@Sun.COM> <49FB7FF0.3030700@univ-mlv.fr> Message-ID: <49FB942E.4070103@sun.com> R?mi Forax wrote: > I wonder what > import static java.dyn.InvokeDynamic.*; > means ? > > R?mi > > It means you shouldn't be able to statically import InvokeDynamic ;-) -Joe From vapor1 at teleport.com Fri May 1 19:41:20 2009 From: vapor1 at teleport.com (Derek Foster) Date: Fri, 1 May 2009 22:41:20 -0400 (EDT) Subject: Points about language support for 292 Message-ID: <6745948.1241232080547.JavaMail.root@elwamui-hound.atl.sa.earthlink.net> -----Original Message----- >From: R?mi Forax >Sent: May 1, 2009 4:46 PM >To: Joe Darcy >Cc: Alex Buckley , John Rose , coin-dev at openjdk.java.net >Subject: Re: Points about language support for 292 > >Joe Darcy a ?crit : >> Yes, for better or worse the Java source language includes checked >> exceptions and InvokeDynamic call sites should not be exempt from >> participating in that rule. >> >> (The existing holes/bugs in this area, like Constructor.newInstance >> should not be expanded.) >> >> -Joe >> > >I don't agree. >You can already fool the compiler, by example, >using generics. In that case, the compiler emit an unsafe cast warning. > >public class ExceptionTest { > interface I { > void m() throws E; > } > static class A implements I { > public void m() throws IOException { > new FileInputStream("hello"); > } > } > public static void main(String[] args) { > I i=(I)new A(); > i.m(); > } >} > >Why not raise a warning saying that InvokeDynamic creates a hole because >exceptions are not managed ? > >R?mi Why not do what's done in other similar circumstances (e.g. Method.invoke()), and have a method called via InvokeDynamic be implicitly declared with a "throws InvocationTargetException" throws specifier, with any exceptions it throws wrapped in an InvocationTargetException instance? That way, the caller will be forced to add a catch clause for InvocationTargetException, but there will be no chance of confusing an exception due to failure to call the method (NoSuchMethodException, etc.) with an exception thrown by the body of the method itself. Derek From rssh at gradsoft.com.ua Sat May 2 09:02:24 2009 From: rssh at gradsoft.com.ua (Ruslan Shevchenko) Date: Sat, 2 May 2009 19:02:24 +0300 (EEST) Subject: how many traditional for loops, for which indexed loop proposal applicable, can be converted to foreach Message-ID: <440d0e27a99a1dea2aa76f752a6b4b8b.squirrel@wmail.gradsoft.ua> Good day, community, In last statistic data about applicability for indexed loop proposal (see http://mail.openjdk.java.net/pipermail/coin-dev/2009-April/001614.html) one question was unanswered: We have some big percentage of all for traditional loops are loops from 0 to size() [or length]. Question is: are all of them use indexes (other then in access expressions), or may be some of them can be converted to JDK foreach loop, but not converted yet for some reason ? Here is summary data for packages, which was in previous statistics: jetty hibernate Gwt-users Openjdk-jdk all traditional fors 315 708 271 11530 convertable to foreach 79 194 29 1515 index other then access 21 191 42 1622 >From 0 to size all 100 385 71 3137 percent of uncovertedd loops 25.08 27.4 10.7 13.14 percent of can-be converted loops with indexes 6.67 26.98 15.5 14.07 So, from 6 to 26 percent of all traditional for loops applicable for loop-for-each proposal and can't be converted to foreach loops without one. Forom 25 to 13 percents of traditional loops can be converted to JDK5 foreach loop. Or by counts: jetty: all traditional fors : 315 for loop (length),convertable to foreach : 63 for loop (size),convertable to foreach : 16 for loop from 0 to size or length : 100 hibernate: all traditional fors : 708 for loop (length),convertable to foreach : 177 for loop (size),convertable to foreach : 17 for loop from 0 to size or length : 385 gwt-user: all traditional fors : 271 for loop (length),convertable to foreach : 24 for loop (size),convertable to foreach : 5 for loop from 0 to size or length : 71 openjdk: all traditional fors : 11530 for loop (length),convertable to foreach : 1515 for loop (size),convertable to foreach : 0 for loop from 0 to size or length : 3137 Patterns for review available in etc/checkers_coin_loop.def http://redmine.gradsoft.ua/repositories/changes/javachecker/trunk/JavaChecker/etc/checkers_coin_loops.def If you want run tool on you code, download 2.5.0p4 http://datacenter.gradsoft.ua/public.repository/ua.gradsoft/javachecker/installations/JavaCheckerSourceInstaller-2.5.0p4.jar Regards ! From pbenedict at apache.org Sat May 2 18:00:16 2009 From: pbenedict at apache.org (Paul Benedict) Date: Sat, 2 May 2009 20:00:16 -0500 Subject: Points about language support for 292 Message-ID: >> Sorry, wrapping checked exceptions is a non-starter for 292. Wrapping >> of all sorts is one of the reasons reflection is unusably slow for >> dynamic language implementation. Good point. But I think it is a bad idea to alter the JLS to catch undeclared checked exceptions -- if that is really being considered. Neal appears to be correct in requiring that a dynamic call site throws Throwable. Dynamic languages can ingnore the exceptions if they want, but the Java code shouldn't. -- Paul From howard.lovatt at gmail.com Sun May 3 22:18:04 2009 From: howard.lovatt at gmail.com (howard.lovatt at gmail.com) Date: Mon, 04 May 2009 05:18:04 +0000 Subject: PROPOSAL: Abstract enums (version 2) In-Reply-To: <49FAB515.2090605@paradise.net.nz> Message-ID: <0016e64f68207471df04690f49f0@google.com> I probably worded my question badly, sorry. I was aware that Enum was the base class for enums. What I was asking is why does it have to be the base class. Why can't Enum be turned into an interface and the methods added by the compiler automatically. This would be a smaller change than adding a new type, abstract enum, to the type system and would be more useful? On May 1, 2009 6:38pm, Bruce Chapman wrote: > Howard Lovatt wrote: > Derek, > I have found also wanted to extend an abstract class when using enums. > However I ideally didn't want to extend a special enum abstract class, eg > abstract enum Super { ... } // Has enum > enum extends Super { ... } > But rather any old abstract class: > abstract class Super { ... } // No enum > enum extends Super { ... } > What is the rational for only allowing abstract enum to be extended rather > than a plain abstract class. > Because if an enum could extend any abstract class, then it wouldn't > always be possible to also extend java.lang.Enum Enum>, and the language > spec says (currently) "The direct > superclass of an enum type named E is Enum", > and Enum's class apidoc says "This is the common base class of all Java > language enumeration types." > Bruce > -- Howard. > ______________________________________________________________________ > This email has been scanned by the MessageLabs Email Security System. > For more information please visit http://www.messagelabs.com/email > ______________________________________________________________________ From howard.lovatt at gmail.com Sun May 3 22:36:58 2009 From: howard.lovatt at gmail.com (howard.lovatt at gmail.com) Date: Mon, 04 May 2009 05:36:58 +0000 Subject: Submission: switch (...) instanceof feature Message-ID: <001485f3be6206130904690f8da1@google.com> I agree with the comments that if ( bar instanceof Foo ) { ... } with bar treated as a Foo inside the braces would be very useful, eg equals methods. Similarly if ( bar.getClass() == Foo ) { ... }. -- Howard. From howard.lovatt at iee.org Sun May 3 22:53:08 2009 From: howard.lovatt at iee.org (Howard Lovatt) Date: Mon, 4 May 2009 15:53:08 +1000 Subject: PROPOSAL: language support for JSR 292 In-Reply-To: <7CF65842-67BF-490F-ADE4-86F8912C1A42@Sun.COM> References: <3dd3f56a0905010216j69d36ab5q551b2a17480a9082@mail.gmail.com> <7CF65842-67BF-490F-ADE4-86F8912C1A42@Sun.COM> Message-ID: <3dd3f56a0905032253h44f44b38te0b9f1edc3a94c2c@mail.gmail.com> Hi John, 2009/5/2 John Rose : [snip] >> At a higher level, rather than details of the proposal, it would be a >> nice addition to have a convenience interface, lets for the sake of >> argument call it Dynamic, that behaved like a top level class in a >> dynamic language and you implicitly had to define a private static >> missingMethod method in any class that implemented Dynamic. > > Interesting. ?There are lots of degrees of freedom in integrating static > Java with dynamic languages. ?The present proposal is intended to be > minimal, but there is lots to dream about here for the future. > >> Then a >> class that implemented Dynamic or any class that used an object of >> type Dynamic would be converted automatically be the compiler to use >> InvokeDynamic, e.g. your simple example would become: > > > > So Main would inherit the ability to form invokedynamic calls from Dynamic. > ?I think that would make many (not all) Java programmers feel very insecure > about the meaning of the code in such a scope. To me it would be great to have a mixture of static typing and dynamic typing in the language. I would mainly use static typing, but at times dynamic typing is very useful (e.g. Rails makes methods on demand). Some languages have optional typing; Gilad Bracha proposed it for Newspeak (bracha.org/pluggable-types.pdf) and Fan (http://www.fandev.org/) does static and dynamic on the JVM. > > My hope right now is to lay down a good enough foundation to enable us to > play with such things in Java 7. I will be playing with your mlvm and will try a few of these things out. -- Howard. From jeroen at lexau.org Mon May 4 01:58:56 2009 From: jeroen at lexau.org (Jeroen van Maanen) Date: Mon, 04 May 2009 10:58:56 +0200 Subject: Submission: switch (...) instanceof feature In-Reply-To: <49FB5113.3050107@lexau.org> References: <21950339.1241161760435.JavaMail.root@elwamui-hound.atl.sa.earthlink.net> <49FB5113.3050107@lexau.org> Message-ID: <49FEAE50.8020900@lexau.org> A colleague of mine pointed out that "if (... instanceof ...)" is currently syntactically correct code. Suddenly the "if" statement would show kind of a meta side effect for a highly specific subset of tests. He suggested that the new "type narrowing if" would get a clearly distinguished syntax, for example: a concise syntax similar to the extended "for" statement: if (name : Type) { ... } or verbose: if instanceof (name : Type) { ... } or like a declaration rather that a test, which clearly emphasizes the side effect: if instanceof (Type name) { ... } Jeroen Jeroen van Maanen schreef: > I agree that "if (... instanceof ...)" is more readable than the > extension of "switch" that I proposed originally. I believe that this > feature that avoids an unnecessary new name and cast would be of great > benefit to the Java language. > > Jeroen > > Derek Foster schreef: >> I notice that the example you gave is actually an argument for an "if" >> that respects instanceOf, rather than a 'switch' that does. It seems >> to me like an abuse of notation to use a 'switch' in a case like this >> where only one decision (it is or it isn't a subtype of a given type) >> is being made. >> >> Although I am skeptical of the 'switch instanceof' feature, for the >> reasons I outlined below, I would very much like to see Java implement >> the 'if instanceof' feature that is implied in the proposal, and which >> various people have been suggesting, so that this very common coding >> pattern: >> >> if (foo instanceof Bar) { >> Bar bar = (Bar)foo; >> doSomethingWith(bar); >> } >> >> could be simplified to: >> >> if (foo instanceof Bar) { >> doSomethingWith(foo); >> } >> >> with no loss of type safety. It seems to me that your example would be >> more readable with such a construct than it is with the 'switch >> instanceof' feature. >> >> I had intended to submit a proposal along these lines myself, but >> simply ran out of time to put it together. Still, it seems to me that >> there's been widespread agreement on the list that the 'if instanceof' >> sub-proposal is a good idea. >> >> Derek >> >> >> >> >> >> -----Original Message----- >>> From: Ulf Zibis >>> Sent: Apr 22, 2009 5:17 AM >>> To: Derek Foster >>> Cc: Gabriel Belingueres , Jeroen van Maanen >>> , coin-dev at openjdk.java.net >>> Subject: Re: Submission: switch (...) instanceof feature >>> >>> Am 22.04.2009 06:55, Derek Foster schrieb: >>>> Like Gabriel, I have severe reservations about this proposal. I am >>>> concerned that it will encourage people to avoid the common OOP >>>> "best practice" of using virtual method dispatch in favor of doing >>>> an explicit "switch" on each subtype of a type, in cases where doing >>>> so is not necessary. >>>> >>>> I concede that there are a few (FEW!) places where doing the >>>> equivalent of a switch on instances of a type is necessary (for >>>> instance, if the type is in a library you don't have the ability to >>>> change). I can see some value in this proposal for that purpose. >>>> However, I would very much not like to see use of this construct >>>> become commonplace. I already see too many instances of people doing >>>> the equivalent of "if (object.type == FOO) {doThis(); } else if >>>> (object.type == BAR) { doThat(); }" instead of writing >>>> "object.doSomething();" >>>> >>>> >>> I like to provide an example where >>> >>> "object.doSomething();" >>> >>> doesn't work: >>> >>> synchronized Charset lookup(String lowCanonical) { >>> // cache is initialized with available Charset classes names >>> Object o = cache.get(lowCanonical); >>> // Check cache first >>> if (o instanceof String) { >>> // Instantiate new charset >>> Charset cs = newCharset((String)o, lowCanonical); >>> // Cache it >>> if (cs != null) >>> cache.put(lowCanonical, cs); >>> return cs; >>> } >>> return (Charset)o; >>> } >>> >>> >>> This would look much nicer, as it avoids casting: >>> >>> synchronized Charset lookup(String lowCanonical) { >>> // cache is initialized with available Charset classes names >>> switch (Object o = cache.get(lowCanonical) instanceof ?) { >>> case String : >>> // Instantiate new charset >>> Charset cs = newCharset(o, lowCanonical); >>> // Cache it >>> if (cs != null) >>> cache.put(lowCanonical, cs); >>> return cs; >>> case Charset : >>> return o; >>> } >>> } >>> >>> >>> Refer: >>> https://java-nio-charset-enhanced.dev.java.net/source/browse/java-nio-charset-enhanced/tags/milestone4/src/sun/nio/cs/FastCharsetProvider.java?rev=684&view=markup >>> >>> http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6790402 >>> http://mail.openjdk.java.net/pipermail/coin-dev/2009-March/001182.html >>> http://mail.openjdk.java.net/pipermail/coin-dev/2009-April/001328.html >>> >>> - My example could also be smartly coded without switch..case >>> statement, if we would enhance if statement accordingly >>> - I also would like to have possibility to declare variables in if >>> clause, like it's possible in for clause: >>> >>> if ((Object o = cache.get(lowCanonical)) instanceof String) >>> ... ; >>> else if (o instanceof Charset) >>> ... ; >>> >>> -Ulf >>> >>> >>>> Derek >>>> >>>> -----Original Message----- >>>> >>>>> From: Gabriel Belingueres >>>>> Sent: Mar 30, 2009 7:31 AM >>>>> To: Jeroen van Maanen >>>>> Cc: coin-dev at openjdk.java.net >>>>> Subject: Re: Submission: switch (...) instanceof feature >>>>> >>>>> IMO I'm against this. >>>>> >>>>> First, it is against current best practices for the design of >>>>> object-oriented software to make easier to code something with a case >>>>> statement on types/classes. >>>>> >>>>> Second: >>>>> void log(Object object) { >>>>> switch (object) instanceof { >>>>> case String: >>>>> logger.debug("'" + object + "'"); >>>>> case Date: >>>>> logger.debug(object.getTime()); >>>>> case void: >>>>> logger.debug("null"); >>>>> default: >>>>> logger.debug("<" + object.toString() + ">"); >>>>> } >>>>> } >>>>> >>>>> It think it is clearer (when possible) writing it with several >>>>> overloaded methods and double dispatching. >>>>> >>>>> .... >>>>> >> From reinier at zwitserloot.com Mon May 4 02:51:00 2009 From: reinier at zwitserloot.com (Reinier Zwitserloot) Date: Mon, 4 May 2009 11:51:00 +0200 Subject: Submission: switch (...) instanceof feature In-Reply-To: <49FEAE50.8020900@lexau.org> References: <21950339.1241161760435.JavaMail.root@elwamui-hound.atl.sa.earthlink.net> <49FB5113.3050107@lexau.org> <49FEAE50.8020900@lexau.org> Message-ID: <7F34F62D-B69D-41BE-840A-FA405DB1127F@zwitserloot.com> Why is this neccessary? We have a similar situation here as the inherited exception issue: Rare and definitely broken (at runtime) code will now break at compile time. This is technically 'backwards incompatible', insofar that code that used to compile no longer does. However, I believe the decision was made that this technical incompatibility was acceptable, because the code made no runtime sense in the first place. You have the same situation here: old code: Object x = foo(); if ( x instanceof String ) { Integer y = (Integer)x; } would compile, eventhough it's clearly bogus. With this change: if ( x instanceof String ) { //within this block, 'x' is considered to be both a String and whatever x's actual type is, if it's not a strict supertype of String. } the original clearly broken code would all of a sudden produce a compile error, because casting a String to an Integer is not allowed (at compile-time too, not just at runtime). You could make a rule to relax this restriction (and generate a warning instead). Personally I'd say that clearly broken code should generate compile-time exceptions, that's why we went with static typing in the first place, so there's no need to complicate the JLS with such a relaxation just to be backwards compatible. That's kind of like Windows Vista taking the trouble to be compatible with viruses written for XP, just so they can say "we're 100% compatible!". (That's a hypothetical, not a comment on Microsoft's programming division. I don't even use windows, I have no idea if Vista works like that). Why would we possibly want to introduce new syntax here? --Reinier Zwitserloot Like it? Tip it! http://tipit.to On May 4, 2009, at 10:58, Jeroen van Maanen wrote: > A colleague of mine pointed out that "if (... instanceof ...)" is > currently syntactically correct code. Suddenly the "if" statement > would show kind of a meta side effect for a highly specific subset > of tests. He suggested that the new "type narrowing if" would get a > clearly distinguished syntax, for example: > > a concise syntax similar to the extended "for" statement: > > if (name : Type) { ... } > > or verbose: > > if instanceof (name : Type) { ... } > > or like a declaration rather that a test, which clearly emphasizes > the side effect: > > if instanceof (Type name) { ... } > > Jeroen > > Jeroen van Maanen schreef: >> I agree that "if (... instanceof ...)" is more readable than the >> extension of "switch" that I proposed originally. I believe that >> this feature that avoids an unnecessary new name and cast would be >> of great benefit to the Java language. >> Jeroen >> Derek Foster schreef: >>> I notice that the example you gave is actually an argument for an >>> "if" that respects instanceOf, rather than a 'switch' that does. >>> It seems to me like an abuse of notation to use a 'switch' in a >>> case like this where only one decision (it is or it isn't a >>> subtype of a given type) is being made. >>> >>> Although I am skeptical of the 'switch instanceof' feature, for >>> the reasons I outlined below, I would very much like to see Java >>> implement the 'if instanceof' feature that is implied in the >>> proposal, and which various people have been suggesting, so that >>> this very common coding pattern: >>> >>> if (foo instanceof Bar) { >>> Bar bar = (Bar)foo; >>> doSomethingWith(bar); >>> } >>> >>> could be simplified to: >>> >>> if (foo instanceof Bar) { >>> doSomethingWith(foo); >>> } >>> >>> with no loss of type safety. It seems to me that your example >>> would be more readable with such a construct than it is with the >>> 'switch instanceof' feature. >>> >>> I had intended to submit a proposal along these lines myself, but >>> simply ran out of time to put it together. Still, it seems to me >>> that there's been widespread agreement on the list that the 'if >>> instanceof' sub-proposal is a good idea. >>> >>> Derek >>> >>> >>> >>> >>> >>> -----Original Message----- >>>> From: Ulf Zibis >>>> Sent: Apr 22, 2009 5:17 AM >>>> To: Derek Foster >>>> Cc: Gabriel Belingueres , Jeroen van >>>> Maanen , coin-dev at openjdk.java.net >>>> Subject: Re: Submission: switch (...) instanceof feature >>>> >>>> Am 22.04.2009 06:55, Derek Foster schrieb: >>>>> Like Gabriel, I have severe reservations about this proposal. I >>>>> am concerned that it will encourage people to avoid the common >>>>> OOP "best practice" of using virtual method dispatch in favor of >>>>> doing an explicit "switch" on each subtype of a type, in cases >>>>> where doing so is not necessary. >>>>> >>>>> I concede that there are a few (FEW!) places where doing the >>>>> equivalent of a switch on instances of a type is necessary (for >>>>> instance, if the type is in a library you don't have the ability >>>>> to change). I can see some value in this proposal for that >>>>> purpose. However, I would very much not like to see use of this >>>>> construct become commonplace. I already see too many instances >>>>> of people doing the equivalent of "if (object.type == FOO) >>>>> {doThis(); } else if (object.type == BAR) { doThat(); }" instead >>>>> of writing "object.doSomething();" >>>>> >>>>> >>>> I like to provide an example where >>>> >>>> "object.doSomething();" >>>> >>>> doesn't work: >>>> >>>> synchronized Charset lookup(String lowCanonical) { >>>> // cache is initialized with available Charset classes names >>>> Object o = cache.get(lowCanonical); >>>> // Check cache first >>>> if (o instanceof String) { >>>> // Instantiate new charset >>>> Charset cs = newCharset((String)o, lowCanonical); >>>> // Cache it >>>> if (cs != null) >>>> cache.put(lowCanonical, cs); >>>> return cs; >>>> } >>>> return (Charset)o; >>>> } >>>> >>>> >>>> This would look much nicer, as it avoids casting: >>>> >>>> synchronized Charset lookup(String lowCanonical) { >>>> // cache is initialized with available Charset classes names >>>> switch (Object o = cache.get(lowCanonical) instanceof ?) { >>>> case String : >>>> // Instantiate new charset >>>> Charset cs = newCharset(o, lowCanonical); >>>> // Cache it >>>> if (cs != null) >>>> cache.put(lowCanonical, cs); >>>> return cs; >>>> case Charset : >>>> return o; >>>> } >>>> } >>>> >>>> >>>> Refer: >>>> https://java-nio-charset-enhanced.dev.java.net/source/browse/java-nio-charset-enhanced/tags/milestone4/src/sun/nio/cs/FastCharsetProvider.java?rev=684&view=markup >>>> http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6790402 >>>> http://mail.openjdk.java.net/pipermail/coin-dev/2009-March/001182.html >>>> http://mail.openjdk.java.net/pipermail/coin-dev/2009-April/001328.html >>>> >>>> - My example could also be smartly coded without switch..case >>>> statement, if we would enhance if statement accordingly >>>> - I also would like to have possibility to declare variables in >>>> if clause, like it's possible in for clause: >>>> >>>> if ((Object o = cache.get(lowCanonical)) instanceof String) >>>> ... ; >>>> else if (o instanceof Charset) >>>> ... ; >>>> >>>> -Ulf >>>> >>>> >>>>> Derek >>>>> >>>>> -----Original Message----- >>>>> >>>>>> From: Gabriel Belingueres >>>>>> Sent: Mar 30, 2009 7:31 AM >>>>>> To: Jeroen van Maanen >>>>>> Cc: coin-dev at openjdk.java.net >>>>>> Subject: Re: Submission: switch (...) instanceof feature >>>>>> >>>>>> IMO I'm against this. >>>>>> >>>>>> First, it is against current best practices for the design of >>>>>> object-oriented software to make easier to code something with >>>>>> a case >>>>>> statement on types/classes. >>>>>> >>>>>> Second: >>>>>> void log(Object object) { >>>>>> switch (object) instanceof { >>>>>> case String: >>>>>> logger.debug("'" + object + "'"); >>>>>> case Date: >>>>>> logger.debug(object.getTime()); >>>>>> case void: >>>>>> logger.debug("null"); >>>>>> default: >>>>>> logger.debug("<" + object.toString() + ">"); >>>>>> } >>>>>> } >>>>>> >>>>>> It think it is clearer (when possible) writing it with several >>>>>> overloaded methods and double dispatching. >>>>>> >>>>>> .... >>>>>> >>> > From forax at univ-mlv.fr Mon May 4 03:18:54 2009 From: forax at univ-mlv.fr (=?ISO-8859-1?Q?R=E9mi_Forax?=) Date: Mon, 04 May 2009 12:18:54 +0200 Subject: Submission: switch (...) instanceof feature In-Reply-To: <7F34F62D-B69D-41BE-840A-FA405DB1127F@zwitserloot.com> References: <21950339.1241161760435.JavaMail.root@elwamui-hound.atl.sa.earthlink.net> <49FB5113.3050107@lexau.org> <49FEAE50.8020900@lexau.org> <7F34F62D-B69D-41BE-840A-FA405DB1127F@zwitserloot.com> Message-ID: <49FEC10E.7080705@univ-mlv.fr> Reinier Zwitserloot a ?crit : > Why is this neccessary? We have a similar situation here as the > inherited exception issue: Rare and definitely broken (at runtime) > code will now break at compile time. This is technically 'backwards > incompatible', insofar that code that used to compile no longer does. > However, I believe the decision was made that this technical > incompatibility was acceptable, because the code made no runtime sense > in the first place. You have the same situation here: > > > old code: > > Object x = foo(); > > if ( x instanceof String ) { > Integer y = (Integer)x; > } > > would compile, eventhough it's clearly bogus. With this change: > > if ( x instanceof String ) { > //within this block, 'x' is considered to be both a String and > whatever x's actual type is, if it's not a strict supertype of String. > } > This change is not backward compatible ... class A { void m(String) { ... } void m(Object o) { ... } void f() { Object x = foo(); if ( x instanceof String ) { m(x); <-- call m(Object), will call m(String) } } } [ ... ] > --Reinier Zwitserloot > Like it? Tip it! > http://tipit.to > R?mi From reinier at zwitserloot.com Mon May 4 03:29:47 2009 From: reinier at zwitserloot.com (Reinier Zwitserloot) Date: Mon, 4 May 2009 12:29:47 +0200 Subject: Submission: switch (...) instanceof feature In-Reply-To: <49FEC10E.7080705@univ-mlv.fr> References: <21950339.1241161760435.JavaMail.root@elwamui-hound.atl.sa.earthlink.net> <49FB5113.3050107@lexau.org> <49FEAE50.8020900@lexau.org> <7F34F62D-B69D-41BE-840A-FA405DB1127F@zwitserloot.com> <49FEC10E.7080705@univ-mlv.fr> Message-ID: overloading methods that have overlapping types is ugly code you should refactor, but, you're right. We've moved from 'clearly broken' code to merely 'ugly, at least by most standards'. Excellent find, Remi. How about changing to: The type of 'x' is both its original type and the type you've instanceof-ed on? This way, your example would produce a compiler error: Call ambiguous, with suggestions to cast the x to either String or Object explicitly, which I think is the proper response, because of the confusion around the non-dynamic nature of overloading with overlapping types. Is there a precedent for such a type concept in javac? This isn't quite the same as either the generics type in e.g. List (particularly because X & Y, where Y is a strict subtype of X, just reduces to Y), nor the typing produced by e.g. the expression (foo ? new A() : new B()) (the intersection of A and B), which also isn't what we're looking for. --Reinier Zwitserloot On May 4, 2009, at 12:18, R?mi Forax wrote: > Reinier Zwitserloot a ?crit : >> Why is this neccessary? We have a similar situation here as the >> inherited exception issue: Rare and definitely broken (at runtime) >> code will now break at compile time. This is technically >> 'backwards incompatible', insofar that code that used to compile >> no longer does. However, I believe the decision was made that this >> technical incompatibility was acceptable, because the code made no >> runtime sense in the first place. You have the same situation here: >> >> >> old code: >> >> Object x = foo(); >> >> if ( x instanceof String ) { >> Integer y = (Integer)x; >> } >> >> would compile, eventhough it's clearly bogus. With this change: >> >> if ( x instanceof String ) { >> //within this block, 'x' is considered to be both a String and >> whatever x's actual type is, if it's not a strict supertype of >> String. >> } >> > > This change is not backward compatible ... > > class A { > void m(String) { ... } > void m(Object o) { ... } > > void f() { > Object x = foo(); > if ( x instanceof String ) { > m(x); <-- call m(Object), will call m(String) > } > } > } > > [ ... ] > >> --Reinier Zwitserloot >> Like it? Tip it! >> http://tipit.to >> > > R?mi From jeroen at lexau.org Mon May 4 04:21:23 2009 From: jeroen at lexau.org (Jeroen van Maanen) Date: Mon, 04 May 2009 13:21:23 +0200 Subject: Submission: switch (...) instanceof feature In-Reply-To: <7F34F62D-B69D-41BE-840A-FA405DB1127F@zwitserloot.com> References: <21950339.1241161760435.JavaMail.root@elwamui-hound.atl.sa.earthlink.net> <49FB5113.3050107@lexau.org> <49FEAE50.8020900@lexau.org> <7F34F62D-B69D-41BE-840A-FA405DB1127F@zwitserloot.com> Message-ID: <49FECFB3.8060808@lexau.org> Reinier Zwitserloot wrote: > Why is this neccessary? We have a similar situation here as the > inherited exception issue: Rare and definitely broken (at runtime) code > will now break at compile time. This is technically 'backwards > incompatible', insofar that code that used to compile no longer does. It is not necessary, but I think it is highly desirable for readability to make this recognizable in the code. In all other cases the code between the parentheses behind the "if" is just an expression. It is easy to mistake the new form for a normal "if" if the extended syntax resembles the normal syntax too closely: Integer value; boolean isInteger; if (isInteger = (x instanceof Integer)) { value = x; // Compiler error? } else if (x instanceof String) { value = Integer.valueOf(x) } else if (x == null) { value = 0; } else { throw IllegalArgumentException("Can't convert to an Integer: [" + x + "]"); } I would say that the following code is much clearer: Integer value; boolean isInteger = false; if instanceof (Integer x) { isInteger = true; value = x; } else if instanceof (String x) { value = Integer.valueOf(x) } else if (x == null) { value = 0; } else { throw IllegalArgumentException("Can't convert to an Integer: [" + x + "]"); } The special syntax could also support multiple tests/redeclarations in the same if: if instanceof (Integer x, Integer y) { x += y; } whereas the alternative if (x instanceof Integer && y instanceof Integer) { x += y; } asks for a pretty complicated analysis of the test to see whether any subexpression of the test narrows the type of one of the variables involved. Beware of boolean negation and "or": if (!(x instanceof BigInteger) && y instanceof Integer) { // Doesn't narrow the type of "x" return add(x, y); } But sure, it would be possible to detect the form "if ( instanceof )" and magically narrow the type of for this specific kind of test only. Jeroen > However, I believe the decision was made that this technical > incompatibility was acceptable, because the code made no runtime sense > in the first place. You have the same situation here: > > > old code: > > Object x = foo(); > > if ( x instanceof String ) { > Integer y = (Integer)x; > } > > would compile, eventhough it's clearly bogus. With this change: > > if ( x instanceof String ) { > //within this block, 'x' is considered to be both a String and > whatever x's actual type is, if it's not a strict supertype of String. > } > > the original clearly broken code would all of a sudden produce a compile > error, because casting a String to an Integer is not allowed (at > compile-time too, not just at runtime). You could make a rule to relax > this restriction (and generate a warning instead). Personally I'd say > that clearly broken code should generate compile-time exceptions, that's > why we went with static typing in the first place, so there's no need to > complicate the JLS with such a relaxation just to be backwards > compatible. That's kind of like Windows Vista taking the trouble to be > compatible with viruses written for XP, just so they can say "we're 100% > compatible!". (That's a hypothetical, not a comment on Microsoft's > programming division. I don't even use windows, I have no idea if Vista > works like that). > > > Why would we possibly want to introduce new syntax here? > > > --Reinier Zwitserloot > Like it? Tip it! > http://tipit.to > > > > On May 4, 2009, at 10:58, Jeroen van Maanen wrote: > >> A colleague of mine pointed out that "if (... instanceof ...)" is >> currently syntactically correct code. Suddenly the "if" statement >> would show kind of a meta side effect for a highly specific subset of >> tests. He suggested that the new "type narrowing if" would get a >> clearly distinguished syntax, for example: >> >> a concise syntax similar to the extended "for" statement: >> >> if (name : Type) { ... } >> >> or verbose: >> >> if instanceof (name : Type) { ... } >> >> or like a declaration rather that a test, which clearly emphasizes the >> side effect: >> >> if instanceof (Type name) { ... } >> >> Jeroen >> >> Jeroen van Maanen schreef: >>> I agree that "if (... instanceof ...)" is more readable than the >>> extension of "switch" that I proposed originally. I believe that this >>> feature that avoids an unnecessary new name and cast would be of >>> great benefit to the Java language. >>> Jeroen >>> Derek Foster schreef: >>>> I notice that the example you gave is actually an argument for an >>>> "if" that respects instanceOf, rather than a 'switch' that does. It >>>> seems to me like an abuse of notation to use a 'switch' in a case >>>> like this where only one decision (it is or it isn't a subtype of a >>>> given type) is being made. >>>> >>>> Although I am skeptical of the 'switch instanceof' feature, for the >>>> reasons I outlined below, I would very much like to see Java >>>> implement the 'if instanceof' feature that is implied in the >>>> proposal, and which various people have been suggesting, so that >>>> this very common coding pattern: >>>> >>>> if (foo instanceof Bar) { >>>> Bar bar = (Bar)foo; >>>> doSomethingWith(bar); >>>> } >>>> >>>> could be simplified to: >>>> >>>> if (foo instanceof Bar) { >>>> doSomethingWith(foo); >>>> } >>>> >>>> with no loss of type safety. It seems to me that your example would >>>> be more readable with such a construct than it is with the 'switch >>>> instanceof' feature. >>>> >>>> I had intended to submit a proposal along these lines myself, but >>>> simply ran out of time to put it together. Still, it seems to me >>>> that there's been widespread agreement on the list that the 'if >>>> instanceof' sub-proposal is a good idea. >>>> >>>> Derek >>>> >>>> >>>> >>>> >>>> >>>> -----Original Message----- >>>>> From: Ulf Zibis > >>>>> Sent: Apr 22, 2009 5:17 AM >>>>> To: Derek Foster > >>>>> Cc: Gabriel Belingueres >>>> >, Jeroen van Maanen >>>>> >, >>>>> coin-dev at openjdk.java.net >>>>> Subject: Re: Submission: switch (...) instanceof feature >>>>> >>>>> Am 22.04.2009 06:55, Derek Foster schrieb: >>>>>> Like Gabriel, I have severe reservations about this proposal. I am >>>>>> concerned that it will encourage people to avoid the common OOP >>>>>> "best practice" of using virtual method dispatch in favor of doing >>>>>> an explicit "switch" on each subtype of a type, in cases where >>>>>> doing so is not necessary. >>>>>> >>>>>> I concede that there are a few (FEW!) places where doing the >>>>>> equivalent of a switch on instances of a type is necessary (for >>>>>> instance, if the type is in a library you don't have the ability >>>>>> to change). I can see some value in this proposal for that >>>>>> purpose. However, I would very much not like to see use of this >>>>>> construct become commonplace. I already see too many instances of >>>>>> people doing the equivalent of "if (object.type == FOO) {doThis(); >>>>>> } else if (object.type == BAR) { doThat(); }" instead of writing >>>>>> "object.doSomething();" >>>>>> >>>>>> >>>>> I like to provide an example where >>>>> >>>>> "object.doSomething();" >>>>> >>>>> doesn't work: >>>>> >>>>> synchronized Charset lookup(String lowCanonical) { >>>>> // cache is initialized with available Charset classes names >>>>> Object o = cache.get(lowCanonical); >>>>> // Check cache first >>>>> if (o instanceof String) { >>>>> // Instantiate new charset >>>>> Charset cs = newCharset((String)o, lowCanonical); >>>>> // Cache it >>>>> if (cs != null) >>>>> cache.put(lowCanonical, cs); >>>>> return cs; >>>>> } >>>>> return (Charset)o; >>>>> } >>>>> >>>>> >>>>> This would look much nicer, as it avoids casting: >>>>> >>>>> synchronized Charset lookup(String lowCanonical) { >>>>> // cache is initialized with available Charset classes names >>>>> switch (Object o = cache.get(lowCanonical) instanceof ?) { >>>>> case String : >>>>> // Instantiate new charset >>>>> Charset cs = newCharset(o, lowCanonical); >>>>> // Cache it >>>>> if (cs != null) >>>>> cache.put(lowCanonical, cs); >>>>> return cs; >>>>> case Charset : >>>>> return o; >>>>> } >>>>> } >>>>> >>>>> >>>>> Refer: >>>>> https://java-nio-charset-enhanced.dev.java.net/source/browse/java-nio-charset-enhanced/tags/milestone4/src/sun/nio/cs/FastCharsetProvider.java?rev=684&view=markup >>>>> >>>>> >>>>> http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6790402 >>>>> http://mail.openjdk.java.net/pipermail/coin-dev/2009-March/001182.html >>>>> http://mail.openjdk.java.net/pipermail/coin-dev/2009-April/001328.html >>>>> >>>>> - My example could also be smartly coded without switch..case >>>>> statement, if we would enhance if statement accordingly >>>>> - I also would like to have possibility to declare variables in if >>>>> clause, like it's possible in for clause: >>>>> >>>>> if ((Object o = cache.get(lowCanonical)) instanceof String) >>>>> ... ; >>>>> else if (o instanceof Charset) >>>>> ... ; >>>>> >>>>> -Ulf >>>>> >>>>> >>>>>> Derek >>>>>> >>>>>> -----Original Message----- >>>>>> >>>>>>> From: Gabriel Belingueres >>>>>> > >>>>>>> Sent: Mar 30, 2009 7:31 AM >>>>>>> To: Jeroen van Maanen >>>>>> > >>>>>>> Cc: coin-dev at openjdk.java.net >>>>>>> Subject: Re: Submission: switch (...) instanceof feature >>>>>>> >>>>>>> IMO I'm against this. >>>>>>> >>>>>>> First, it is against current best practices for the design of >>>>>>> object-oriented software to make easier to code something with a case >>>>>>> statement on types/classes. >>>>>>> >>>>>>> Second: >>>>>>> void log(Object object) { >>>>>>> switch (object) instanceof { >>>>>>> case String: >>>>>>> logger.debug("'" + object + "'"); >>>>>>> case Date: >>>>>>> logger.debug(object.getTime()); >>>>>>> case void: >>>>>>> logger.debug("null"); >>>>>>> default: >>>>>>> logger.debug("<" + object.toString() + ">"); >>>>>>> } >>>>>>> } >>>>>>> >>>>>>> It think it is clearer (when possible) writing it with several >>>>>>> overloaded methods and double dispatching. >>>>>>> >>>>>>> .... >>>>>>> >>>> >> > From neal at gafter.com Mon May 4 07:01:07 2009 From: neal at gafter.com (Neal Gafter) Date: Mon, 4 May 2009 07:01:07 -0700 Subject: Submission: switch (...) instanceof feature In-Reply-To: <49FEAE50.8020900@lexau.org> References: <21950339.1241161760435.JavaMail.root@elwamui-hound.atl.sa.earthlink.net> <49FB5113.3050107@lexau.org> <49FEAE50.8020900@lexau.org> Message-ID: <15e8b9d20905040701j7c41b138ra1dcd56f6be79cf6@mail.gmail.com> If we want a variable inside the switch statement with a different type than outside, then the programmer should introduce a new variable. That allows the new form of the switch statement to be used with general expressions instead of only a simply-named variable. Something like this: switch instanceof (expression) { case (String s): // code for when the expression is of type String, using variable s case (Integer i): // etc } There would have to be either an implicit 'break' between the cases, or the 'break' would be required. Regards, Neal On Mon, May 4, 2009 at 1:58 AM, Jeroen van Maanen wrote: > A colleague of mine pointed out that "if (... instanceof ...)" is currently > syntactically correct code. Suddenly the "if" statement would show kind of a > meta side effect for a highly specific subset of tests. He suggested that > the new "type narrowing if" would get a clearly distinguished syntax, for > example: > > a concise syntax similar to the extended "for" statement: > > if (name : Type) { ... } > > or verbose: > > if instanceof (name : Type) { ... } > > or like a declaration rather that a test, which clearly emphasizes the side > effect: > > if instanceof (Type name) { ... } > > Jeroen > > Jeroen van Maanen schreef: > > I agree that "if (... instanceof ...)" is more readable than the extension >> of "switch" that I proposed originally. I believe that this feature that >> avoids an unnecessary new name and cast would be of great benefit to the >> Java language. >> >> Jeroen >> >> Derek Foster schreef: >> >>> I notice that the example you gave is actually an argument for an "if" >>> that respects instanceOf, rather than a 'switch' that does. It seems to me >>> like an abuse of notation to use a 'switch' in a case like this where only >>> one decision (it is or it isn't a subtype of a given type) is being made. >>> >>> Although I am skeptical of the 'switch instanceof' feature, for the >>> reasons I outlined below, I would very much like to see Java implement the >>> 'if instanceof' feature that is implied in the proposal, and which various >>> people have been suggesting, so that this very common coding pattern: >>> >>> if (foo instanceof Bar) { >>> Bar bar = (Bar)foo; >>> doSomethingWith(bar); >>> } >>> >>> could be simplified to: >>> >>> if (foo instanceof Bar) { >>> doSomethingWith(foo); >>> } >>> >>> with no loss of type safety. It seems to me that your example would be >>> more readable with such a construct than it is with the 'switch instanceof' >>> feature. >>> >>> I had intended to submit a proposal along these lines myself, but simply >>> ran out of time to put it together. Still, it seems to me that there's been >>> widespread agreement on the list that the 'if instanceof' sub-proposal is a >>> good idea. >>> >>> Derek >>> >>> >>> >>> >>> >>> -----Original Message----- >>> >>>> From: Ulf Zibis >>>> Sent: Apr 22, 2009 5:17 AM >>>> To: Derek Foster >>>> Cc: Gabriel Belingueres , Jeroen van Maanen < >>>> jeroen at entreact.com>, coin-dev at openjdk.java.net >>>> Subject: Re: Submission: switch (...) instanceof feature >>>> >>>> Am 22.04.2009 06:55, Derek Foster schrieb: >>>> >>>>> Like Gabriel, I have severe reservations about this proposal. I am >>>>> concerned that it will encourage people to avoid the common OOP "best >>>>> practice" of using virtual method dispatch in favor of doing an explicit >>>>> "switch" on each subtype of a type, in cases where doing so is not >>>>> necessary. >>>>> >>>>> I concede that there are a few (FEW!) places where doing the equivalent >>>>> of a switch on instances of a type is necessary (for instance, if the type >>>>> is in a library you don't have the ability to change). I can see some value >>>>> in this proposal for that purpose. However, I would very much not like to >>>>> see use of this construct become commonplace. I already see too many >>>>> instances of people doing the equivalent of "if (object.type == FOO) >>>>> {doThis(); } else if (object.type == BAR) { doThat(); }" instead of writing >>>>> "object.doSomething();" >>>>> >>>>> >>>>> >>>> I like to provide an example where >>>> >>>> "object.doSomething();" >>>> >>>> doesn't work: >>>> >>>> synchronized Charset lookup(String lowCanonical) { >>>> // cache is initialized with available Charset classes names >>>> Object o = cache.get(lowCanonical); >>>> // Check cache first >>>> if (o instanceof String) { >>>> // Instantiate new charset >>>> Charset cs = newCharset((String)o, lowCanonical); >>>> // Cache it >>>> if (cs != null) >>>> cache.put(lowCanonical, cs); >>>> return cs; >>>> } >>>> return (Charset)o; >>>> } >>>> >>>> >>>> This would look much nicer, as it avoids casting: >>>> >>>> synchronized Charset lookup(String lowCanonical) { >>>> // cache is initialized with available Charset classes names >>>> switch (Object o = cache.get(lowCanonical) instanceof ?) { >>>> case String : >>>> // Instantiate new charset >>>> Charset cs = newCharset(o, lowCanonical); >>>> // Cache it >>>> if (cs != null) >>>> cache.put(lowCanonical, cs); >>>> return cs; >>>> case Charset : >>>> return o; >>>> } >>>> } >>>> >>>> >>>> Refer: >>>> >>>> https://java-nio-charset-enhanced.dev.java.net/source/browse/java-nio-charset-enhanced/tags/milestone4/src/sun/nio/cs/FastCharsetProvider.java?rev=684&view=markup >>>> http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6790402 >>>> http://mail.openjdk.java.net/pipermail/coin-dev/2009-March/001182.html >>>> http://mail.openjdk.java.net/pipermail/coin-dev/2009-April/001328.html >>>> >>>> - My example could also be smartly coded without switch..case statement, >>>> if we would enhance if statement accordingly >>>> - I also would like to have possibility to declare variables in if >>>> clause, like it's possible in for clause: >>>> >>>> if ((Object o = cache.get(lowCanonical)) instanceof String) >>>> ... ; >>>> else if (o instanceof Charset) >>>> ... ; >>>> >>>> -Ulf >>>> >>>> >>>> Derek >>>>> >>>>> -----Original Message----- >>>>> >>>>> >>>>>> From: Gabriel Belingueres >>>>>> Sent: Mar 30, 2009 7:31 AM >>>>>> To: Jeroen van Maanen >>>>>> Cc: coin-dev at openjdk.java.net >>>>>> Subject: Re: Submission: switch (...) instanceof feature >>>>>> >>>>>> IMO I'm against this. >>>>>> >>>>>> First, it is against current best practices for the design of >>>>>> object-oriented software to make easier to code something with a case >>>>>> statement on types/classes. >>>>>> >>>>>> Second: >>>>>> void log(Object object) { >>>>>> switch (object) instanceof { >>>>>> case String: >>>>>> logger.debug("'" + object + "'"); >>>>>> case Date: >>>>>> logger.debug(object.getTime()); >>>>>> case void: >>>>>> logger.debug("null"); >>>>>> default: >>>>>> logger.debug("<" + object.toString() + ">"); >>>>>> } >>>>>> } >>>>>> >>>>>> It think it is clearer (when possible) writing it with several >>>>>> overloaded methods and double dispatching. >>>>>> >>>>>> .... >>>>>> >>>>>> >>>>> >>> > > > From belingueres at gmail.com Mon May 4 07:27:54 2009 From: belingueres at gmail.com (Gabriel Belingueres) Date: Mon, 4 May 2009 11:27:54 -0300 Subject: Submission: switch (...) instanceof feature In-Reply-To: <49FEC10E.7080705@univ-mlv.fr> References: <21950339.1241161760435.JavaMail.root@elwamui-hound.atl.sa.earthlink.net> <49FB5113.3050107@lexau.org> <49FEAE50.8020900@lexau.org> <7F34F62D-B69D-41BE-840A-FA405DB1127F@zwitserloot.com> <49FEC10E.7080705@univ-mlv.fr> Message-ID: touch?! Maybe it is time to consider an idiom like C++'s dynamic_cast? void f() { Object x = foo(); String s = dynamic_cast(x); if (s != null) { m(s); // call m(String) m(x); // call m(Object); } } 2009/5/4 R?mi Forax : > Reinier Zwitserloot a ?crit : >> Why is this neccessary? We have a similar situation here as the >> inherited exception issue: Rare and definitely broken (at runtime) >> code will now break at compile time. This is technically 'backwards >> incompatible', insofar that code that used to compile no longer does. >> However, I believe the decision was made that this technical >> incompatibility was acceptable, because the code made no runtime sense >> in the first place. You have the same situation here: >> >> >> old code: >> >> Object x = foo(); >> >> if ( x instanceof String ) { >> ? ?Integer y = (Integer)x; >> } >> >> would compile, eventhough it's clearly bogus. With this change: >> >> if ( x instanceof String ) { >> ? ? //within this block, 'x' is considered to be both a String and >> whatever x's actual type is, if it's not a strict supertype of String. >> } >> > > This change is not backward compatible ... > > class A { > ?void m(String) { ... } > ?void m(Object o) { ... } > > ?void f() { > ? ?Object x = foo(); > ? ?if ( x instanceof String ) { > ? ? ?m(x); ? ? ?<-- ?call m(Object), will call m(String) > ? } > ?} > } > > [ ... ] > >> ? --Reinier Zwitserloot >> Like it? Tip it! >> http://tipit.to >> > > R?mi > > From jeroen at lexau.org Mon May 4 14:06:08 2009 From: jeroen at lexau.org (Jeroen van Maanen) Date: Mon, 04 May 2009 23:06:08 +0200 Subject: Submission: switch (...) instanceof feature In-Reply-To: <15e8b9d20905040701j7c41b138ra1dcd56f6be79cf6@mail.gmail.com> References: <21950339.1241161760435.JavaMail.root@elwamui-hound.atl.sa.earthlink.net> <49FB5113.3050107@lexau.org> <49FEAE50.8020900@lexau.org> <15e8b9d20905040701j7c41b138ra1dcd56f6be79cf6@mail.gmail.com> Message-ID: <49FF58C0.6070103@lexau.org> Neal Gafter schreef: > If we want a variable inside the switch statement with a different type > than outside, then the programmer should introduce a new variable. That > allows the new form of the switch statement to be used with general > expressions instead of only a simply-named variable. Something like this: I disagree. The proposal was meant to deal with the case where a method gets an object of an unknown (or not completely known) type and where part of the method needs to perform specific actions based on the specific type. Currently, this situation needs a cast and a new name. I would like to do away with both of them, if possible. So I would like to see a scope where the same name is used for the same object but with a narrower type. Is can see the problems with getting the "switch" statement to accommodate this, so I'm happy very happy with the suggestion that an extension of the "if" statement would be more straight forward. > switch instanceof (expression) { > case (String s): > // code for when the expression is of type String, using variable s > case (Integer i): > // etc > } I got lots of remarks about special cases of the switch statement that would be hard to handle. It would be hard to come up with a design that would behave similar to the old switch statement for integers, because the inheritance hierarchy prevents a jump table approach. For readability, I persist in thinking that it is better to give the expression result a proper name and use that name throughout the method / class, than introducing a new name for each case: Object var = expression; if instanceof (String var) { // code for when the expression is of type String, using var } else if instanceof (Integer var) { // etc. } > There would have to be either an implicit 'break' between the cases, or > the 'break' would be required. > > Regards, > Neal > > On Mon, May 4, 2009 at 1:58 AM, Jeroen van Maanen > wrote: > > A colleague of mine pointed out that "if (... instanceof ...)" is > currently syntactically correct code. Suddenly the "if" statement > would show kind of a meta side effect for a highly specific subset > of tests. He suggested that the new "type narrowing if" would get a > clearly distinguished syntax, for example: > > a concise syntax similar to the extended "for" statement: > > if (name : Type) { ... } > > or verbose: > > if instanceof (name : Type) { ... } > > or like a declaration rather that a test, which clearly emphasizes > the side effect: > > if instanceof (Type name) { ... } > > Jeroen > > Jeroen van Maanen schreef: > > I agree that "if (... instanceof ...)" is more readable than the > extension of "switch" that I proposed originally. I believe that > this feature that avoids an unnecessary new name and cast would > be of great benefit to the Java language. > > Jeroen > > Derek Foster schreef: > > I notice that the example you gave is actually an argument > for an "if" that respects instanceOf, rather than a 'switch' > that does. It seems to me like an abuse of notation to use a > 'switch' in a case like this where only one decision (it is > or it isn't a subtype of a given type) is being made. > > Although I am skeptical of the 'switch instanceof' feature, > for the reasons I outlined below, I would very much like to > see Java implement the 'if instanceof' feature that is > implied in the proposal, and which various people have been > suggesting, so that this very common coding pattern: > > if (foo instanceof Bar) { > Bar bar = (Bar)foo; > doSomethingWith(bar); > } > > could be simplified to: > > if (foo instanceof Bar) { > doSomethingWith(foo); > } > > with no loss of type safety. It seems to me that your > example would be more readable with such a construct than it > is with the 'switch instanceof' feature. > > I had intended to submit a proposal along these lines > myself, but simply ran out of time to put it together. > Still, it seems to me that there's been widespread agreement > on the list that the 'if instanceof' sub-proposal is a good > idea. > > Derek > > > > > > -----Original Message----- > > From: Ulf Zibis > > Sent: Apr 22, 2009 5:17 AM > To: Derek Foster > > Cc: Gabriel Belingueres >, Jeroen van Maanen > >, > coin-dev at openjdk.java.net > Subject: Re: Submission: switch (...) instanceof feature > > Am 22.04.2009 06:55, Derek Foster schrieb: > > Like Gabriel, I have severe reservations about this > proposal. I am concerned that it will encourage > people to avoid the common OOP "best practice" of > using virtual method dispatch in favor of doing an > explicit "switch" on each subtype of a type, in > cases where doing so is not necessary. > > I concede that there are a few (FEW!) places where > doing the equivalent of a switch on instances of a > type is necessary (for instance, if the type is in a > library you don't have the ability to change). I can > see some value in this proposal for that purpose. > However, I would very much not like to see use of > this construct become commonplace. I already see too > many instances of people doing the equivalent of "if > (object.type == FOO) {doThis(); } else if > (object.type == BAR) { doThat(); }" instead of > writing "object.doSomething();" > > > > I like to provide an example where > > "object.doSomething();" > > doesn't work: > > synchronized Charset lookup(String lowCanonical) { > // cache is initialized with available Charset > classes names > Object o = cache.get(lowCanonical); > // Check cache first > if (o instanceof String) { > // Instantiate new charset > Charset cs = newCharset((String)o, lowCanonical); > // Cache it > if (cs != null) > cache.put(lowCanonical, cs); > return cs; > } > return (Charset)o; > } > > > This would look much nicer, as it avoids casting: > > synchronized Charset lookup(String lowCanonical) { > // cache is initialized with available Charset > classes names > switch (Object o = cache.get(lowCanonical) > instanceof ?) { > case String : > // Instantiate new charset > Charset cs = newCharset(o, lowCanonical); > // Cache it > if (cs != null) > cache.put(lowCanonical, cs); > return cs; > case Charset : > return o; > } > } > > > Refer: > https://java-nio-charset-enhanced.dev.java.net/source/browse/java-nio-charset-enhanced/tags/milestone4/src/sun/nio/cs/FastCharsetProvider.java?rev=684&view=markup > > > http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6790402 > http://mail.openjdk.java.net/pipermail/coin-dev/2009-March/001182.html > http://mail.openjdk.java.net/pipermail/coin-dev/2009-April/001328.html > > - My example could also be smartly coded without > switch..case statement, if we would enhance if statement > accordingly > - I also would like to have possibility to declare > variables in if clause, like it's possible in for clause: > > if ((Object o = cache.get(lowCanonical)) > instanceof String) > ... ; > else if (o instanceof Charset) > ... ; > > -Ulf > > > Derek > > -----Original Message----- > > > From: Gabriel Belingueres > > Sent: Mar 30, 2009 7:31 AM > To: Jeroen van Maanen > > Cc: coin-dev at openjdk.java.net > > Subject: Re: Submission: switch (...) instanceof > feature > > IMO I'm against this. > > First, it is against current best practices for > the design of > object-oriented software to make easier to code > something with a case > statement on types/classes. > > Second: > void log(Object object) { > switch (object) instanceof { > case String: > logger.debug("'" + object + "'"); > case Date: > logger.debug(object.getTime()); > case void: > logger.debug("null"); > default: > logger.debug("<" + object.toString() + ">"); > } > } > > It think it is clearer (when possible) writing > it with several > overloaded methods and double dispatching. > > .... > > > > > > > From ali.ebrahimi1781 at gmail.com Mon May 4 14:07:07 2009 From: ali.ebrahimi1781 at gmail.com (Ali Ebrahimi) Date: Tue, 5 May 2009 01:37:07 +0430 Subject: Submission: switch (...) instanceof feature Message-ID: <5ab441490905041407q1a0f218cv69a05a7135b52063@mail.gmail.com> My suggestion for switch on objects was as below: switch(obj){ case String str: println("obj instance of String and str is (String)obj"); break; // instanceof case case obj2 : println("obj equals obj2"); break; // equals case .... } see url for more details: My wishlist and Ideas for java 7 as java developer Best Regards Ali Ebrahimi From neal at gafter.com Mon May 4 14:30:46 2009 From: neal at gafter.com (Neal Gafter) Date: Mon, 4 May 2009 14:30:46 -0700 Subject: Submission: switch (...) instanceof feature In-Reply-To: <49FF58C0.6070103@lexau.org> References: <21950339.1241161760435.JavaMail.root@elwamui-hound.atl.sa.earthlink.net> <49FB5113.3050107@lexau.org> <49FEAE50.8020900@lexau.org> <15e8b9d20905040701j7c41b138ra1dcd56f6be79cf6@mail.gmail.com> <49FF58C0.6070103@lexau.org> Message-ID: <15e8b9d20905041430k72ccc87y64226a92f51e6cbc@mail.gmail.com> 2009/5/4 Jeroen van Maanen > Neal Gafter schreef: > >> If we want a variable inside the switch statement with a different type >> than outside, then the programmer should introduce a new variable. That >> allows the new form of the switch statement to be used with general >> expressions instead of only a simply-named variable. Something like this: >> > > I disagree. The proposal was meant to deal with the case where a method > gets an object of an unknown (or not completely known) type and where part > of the method needs to perform specific actions based on the specific type. > Currently, this situation needs a cast and a new name. I would like to do > away with both of them, if possible. So I would like to see a scope where > the same name is used for the same object but with a narrower type. Is can > see the problems with getting the "switch" statement to accommodate this, so > I'm happy very happy with the suggestion that an extension of the "if" > statement would be more straight forward. Any proposal that changes the type of an existing variable in a particular scope is less straightforward, as is any proposal that works with an expression that is a variable but not any other kind of expression, or that treats parameters differently from other variables. Language constructs that are not designed to be orthogonal are likely not well designed. From Weijun.Wang at Sun.COM Tue May 5 02:07:51 2009 From: Weijun.Wang at Sun.COM (Weijun Wang) Date: Tue, 05 May 2009 17:07:51 +0800 Subject: On PROPOSAL Narrow Hexadecimal and Binary Integer Literals Message-ID: <4A0001E7.1020506@sun.com> Hi All I'm reading this proposal, which recommends: byte[] stuff = { 0x00, 0x7F, (byte)0x80, (byte)0xFF}; can be recoded as byte[] ufum7 = { 0h00, 0h7F, 0h80, 0hFF}; How about using the C style? byte[] bs = '\x00\x7f\x80\xff'; This should work since multiple bytes in '' is illegal now. When you want to create a byte[] with only one element, you still have to write byte[] bs = { 0x00 }; BTW, if the VM can be enhanced to support byte[] in constant pool, that will be even better. Of course, if the VM is already able to view bytecodes from the statement above as a single byte block reference, that's enough. Thanks Max From vapor1 at teleport.com Wed May 6 01:08:02 2009 From: vapor1 at teleport.com (Derek Foster) Date: Wed, 6 May 2009 04:08:02 -0400 (EDT) Subject: PROPOSAL: Abstract enums (version 2) Message-ID: <15925395.1241597282248.JavaMail.root@mswamui-andean.atl.sa.earthlink.net> Howard, Bruce pretty much has it right. Extending an arbitrary Java class pretty much wouldn't work, for the reasons he describes. I considered writing my proposal in such a way as to allow an enum to extend certain kinds of classes (those which were generified in just the right way, and which ultimately had Enum at the top of the inheritance hierarchy), but it seemed to me that forcing the user to repeat all of that boilerplate code, exactly right ("abstract class Foo> extends Enum { whatever } and so forth) was an unreasonable burden to expect a programmer to have to put up with. The "abstract enum" syntax allows the compiler to generate that boilerplate code without the user having to know it exists, in a similar fashion to how the normal "enum" keyword allows the user to not have to deal with the "Enum>" nastiness of the Enum superclass. Derek -----Original Message----- >From: Bruce Chapman >Sent: May 1, 2009 3:25 AM >To: >Cc: coin-dev at openjdk.java.net >Subject: Re: PROPOSAL: Abstract enums (version 2) > >Howard Lovatt wrote: >> Derek, >> >> I have found also wanted to extend an abstract class when using enums. >> However I ideally didn't want to extend a special enum abstract class, e.g. >> >> abstract enum Super { ... } // Has enum >> >> enum extends Super { ... } >> >> But rather any old abstract class: >> >> abstract class Super { ... } // No enum >> >> enum extends Super { ... } >> >> What is the rational for only allowing abstract enum to be extended rather >> than a plain abstract class. >> >Because if an enum could extend any abstract class, then it wouldn't >always be possible to also extend java.lang.Enum>, and >the language spec says (currently) "The direct superclass of an enum >type named /E/ is |Enum"|, and Enum's class apidoc says "This is the >common base class of all Java language enumeration types." > >Bruce >> -- Howard. >> >> > > From vapor1 at teleport.com Wed May 6 01:46:01 2009 From: vapor1 at teleport.com (Derek Foster) Date: Wed, 6 May 2009 04:46:01 -0400 (EDT) Subject: PROPOSAL: Enhanced for each loop iteration control Message-ID: <32096145.1241599561308.JavaMail.root@mswamui-andean.atl.sa.earthlink.net> -----Original Message----- >From: Stephen Colebourne >Sent: May 1, 2009 4:16 AM >To: coin-dev at openjdk.java.net >Subject: Re: PROPOSAL: Enhanced for each loop iteration control > >2009/5/1 Derek Foster : >> Firstly, I have very rarely needed to call Iterator.delete() in a loop. (I can think of maybe four or five occasions.) As such, it has usually not been a great deal of trouble to just write the loop using an explicit iterator. > >Thanks for the numeric feedback. It may depend on coding style. 5% of >the loops in the enterprise system I work on have remove(). It probably does depend on coding style to some degree. In my coding, I very much tend to prefer immutable data structures and "functional-like" algorithms with no external side-effects when possible. Thus, I would usually rather copy a list, creating a new list that is a filtered version of the original, than to modify the original list by removing the elements that I don't want. >> I would much prefer to have a simpler syntax that allowed me to work just with an index or just with an iterator... Actually, I'd be happy if just indices were supported. Something like: >> >> Thing[] fooCollection = ...whatever...; >> String[] results = new String[fooCollection.length]; >> for (Thing foo : fooCollection) { >> ? ? results[#foo] = foo.toString(); >> } >> >> where "#foo" was defined by the compiler as "the index of foo within the collection it is iterating over". > >#foo has a meaning in FCM as a field reference, and similar syntax was >adopted by BGGA (unpublished as a document). I was just using the leading # as an example. Other syntaxes ("indexof(foo)", "foo..index", "##foo", "$@@!#$@foo" or whatever else comes to mind could be candidates. Basically, all we need is a unary operator, unary function, or other way to indicate that in certain references, we want the index associated with the loop variable and not the variable itself.) >It should also be noted that this approach breaks on nested loops (its brittle). I don't understand what you mean by "breaking on nested loops". Support for nested loops is why I suggested "#foo" instead of just "#"... the specification use of the loop variable indicates the nesting level. For instance, you could do something like: for (Thing foo : whatever) { for (Thing bar : whateverElse) { doSomethingWith(foo, bar, #foo, #bar); } } Derek From brucechapman at paradise.net.nz Wed May 6 02:45:30 2009 From: brucechapman at paradise.net.nz (Bruce Chapman) Date: Wed, 06 May 2009 21:45:30 +1200 Subject: PROPOSAL: Enhanced for each loop iteration control In-Reply-To: <32096145.1241599561308.JavaMail.root@mswamui-andean.atl.sa.earthlink.net> References: <32096145.1241599561308.JavaMail.root@mswamui-andean.atl.sa.earthlink.net> Message-ID: <4A015C3A.5020406@paradise.net.nz> > I don't understand what you mean by "breaking on nested loops". Support for nested loops is why I suggested "#foo" instead of just "#"... the specification use of the loop variable indicates the nesting level. For instance, you could do something like: > > for (Thing foo : whatever) { > for (Thing bar : whateverElse) { > doSomethingWith(foo, bar, #foo, #bar); > } > } > > Derek > > > I am not really excited about this proposal, but I just had this thought for a possible syntax. The idea is to hybridize the for-each and conventional for syntax, but you don't need the (stopping) expression from conventional syntax (foreach does that), but you could include the initializing portion and updating portion like this HybridForStatement for ( /VariableModifiers_opt Type Identifier /: Expression ; /ForInit_/opt/ / //; /ForUpdate_/opt/ / ) /Statement Then to do an indexed loop you could write / for (Thing foo : whatever; int i=0; i++) { for (Thing bar : whateverElse; int j=0; j++ ) { doSomethingWith(foo, bar, i, j); } } but it's not that much different than what you can do (irrespective of the exotic formatting) already int i=-1; for (Thing foo : whatever) { i++; int j=-1; for (Thing bar : whateverElse ) { j++; doSomethingWith(foo, bar, i, j); } } Bruce From reinier at zwitserloot.com Wed May 6 03:03:50 2009 From: reinier at zwitserloot.com (Reinier Zwitserloot) Date: Wed, 6 May 2009 12:03:50 +0200 Subject: PROPOSAL: Enhanced for each loop iteration control In-Reply-To: <4A015C3A.5020406@paradise.net.nz> References: <32096145.1241599561308.JavaMail.root@mswamui-andean.atl.sa.earthlink.net> <4A015C3A.5020406@paradise.net.nz> Message-ID: <5241B403-AA02-4A41-89A7-84B47B5254AB@zwitserloot.com> The nicety of the original proposal was the added utility methods, such as .first(). Getting the index of the loop? Don't care. Don't want. Or at least, not often enough to make this a language change. This is true for every method in the utility set, but add them together, and you have something useful enough to consider adding to the language. I find this hijacking of the #, or the 4-sub-statement for statement, both far higher inpact resp. far more complicated, for far less value, than the original 3-way colon-separated for proposal that was not even shortlisted by Joe Darcy. Why are we talking about this again? --Reinier Zwitserloot On May 6, 2009, at 11:45, Bruce Chapman wrote: > > >> I don't understand what you mean by "breaking on nested loops". >> Support for nested loops is why I suggested "#foo" instead of just >> "#"... the specification use of the loop variable indicates the >> nesting level. For instance, you could do something like: >> >> for (Thing foo : whatever) { >> for (Thing bar : whateverElse) { >> doSomethingWith(foo, bar, #foo, #bar); >> } >> } >> >> Derek >> >> >> > I am not really excited about this proposal, but I just had this > thought > for a possible syntax. > > The idea is to hybridize the for-each and conventional for syntax, but > you don't need the (stopping) expression from conventional syntax > (foreach does that), but you could include the initializing portion > and > updating portion like this > > HybridForStatement > > for ( /VariableModifiers_opt Type Identifier /: Expression ; / > ForInit_/opt/ / //; /ForUpdate_/opt/ / ) /Statement > > Then to do an indexed loop you could write > / > > for (Thing foo : whatever; int i=0; i++) { > for (Thing bar : whateverElse; int j=0; j++ ) { > doSomethingWith(foo, bar, i, j); > } > } > > but it's not that much different than what you can do (irrespective > of the exotic formatting) already > > int i=-1; for (Thing foo : whatever) { i++; > int j=-1; for (Thing bar : whateverElse ) { j++; > doSomethingWith(foo, bar, i, j); > } > } > > > Bruce > > From scolebourne at joda.org Wed May 6 05:38:59 2009 From: scolebourne at joda.org (Stephen Colebourne) Date: Wed, 6 May 2009 13:38:59 +0100 Subject: PROPOSAL: Enhanced for each loop iteration control In-Reply-To: <5241B403-AA02-4A41-89A7-84B47B5254AB@zwitserloot.com> References: <32096145.1241599561308.JavaMail.root@mswamui-andean.atl.sa.earthlink.net> <4A015C3A.5020406@paradise.net.nz> <5241B403-AA02-4A41-89A7-84B47B5254AB@zwitserloot.com> Message-ID: <4b4f45e00905060538p1405e893w1782373dbeb198b0@mail.gmail.com> 2009/5/6 Reinier Zwitserloot : > the original 3-way colon-separated for proposal that was not even > shortlisted by Joe Darcy. Why are we talking about this again? The shortlist occurred before the end of Coin's submission period. IIRC, this proposal was added after that shortlist was published. I suspect that Joe is due to publish a more final shortlist soon. Stephen From Joe.Darcy at Sun.COM Wed May 6 12:06:39 2009 From: Joe.Darcy at Sun.COM (Joe Darcy) Date: Wed, 06 May 2009 12:06:39 -0700 Subject: PROPOSAL: Enhanced for each loop iteration control In-Reply-To: <4b4f45e00905060538p1405e893w1782373dbeb198b0@mail.gmail.com> References: <32096145.1241599561308.JavaMail.root@mswamui-andean.atl.sa.earthlink.net> <4A015C3A.5020406@paradise.net.nz> <5241B403-AA02-4A41-89A7-84B47B5254AB@zwitserloot.com> <4b4f45e00905060538p1405e893w1782373dbeb198b0@mail.gmail.com> Message-ID: <4A01DFBF.70902@sun.com> On 05/06/09 05:38 AM, Stephen Colebourne wrote: > 2009/5/6 Reinier Zwitserloot : > >> the original 3-way colon-separated for proposal that was not even >> shortlisted by Joe Darcy. Why are we talking about this again? >> > > The shortlist occurred before the end of Coin's submission period. > IIRC, this proposal was added after that shortlist was published. I > suspect that Joe is due to publish a more final shortlist soon. > > Stephen > > Yes, I'm busy working on the short list and other coin matters :-) -Joe From reinier at zwitserloot.com Wed May 6 13:49:31 2009 From: reinier at zwitserloot.com (Reinier Zwitserloot) Date: Wed, 6 May 2009 22:49:31 +0200 Subject: PROPOSAL: Enhanced for each loop iteration control In-Reply-To: <4A01DFBF.70902@sun.com> References: <32096145.1241599561308.JavaMail.root@mswamui-andean.atl.sa.earthlink.net> <4A015C3A.5020406@paradise.net.nz> <5241B403-AA02-4A41-89A7-84B47B5254AB@zwitserloot.com> <4b4f45e00905060538p1405e893w1782373dbeb198b0@mail.gmail.com> <4A01DFBF.70902@sun.com> Message-ID: <1E6A673A-C521-4768-A02F-91019EA6CB8D@zwitserloot.com> Ah, that's my mistake. In that case, I know this isn't a democracy, but, for what it's worth, I'll toss my hat into the ring for the original 3-way colon separated proposal: for ( String foo : someStringList : anyName ) { } where anyName's type becomes a class created for java 1.7, which includes index(), isFirst(), remove(), and other useful utilities, all based off of the iterator. I believe Stephen Colebourne made a formal proposal for this one. --Reinier Zwitserloot Like it? Tip it! http://tipit.to On May 6, 2009, at 21:06, Joe Darcy wrote: > On 05/06/09 05:38 AM, Stephen Colebourne wrote: >> 2009/5/6 Reinier Zwitserloot : >> >>> the original 3-way colon-separated for proposal that was not even >>> shortlisted by Joe Darcy. Why are we talking about this again? >>> >> >> The shortlist occurred before the end of Coin's submission period. >> IIRC, this proposal was added after that shortlist was published. I >> suspect that Joe is due to publish a more final shortlist soon. >> >> Stephen >> >> > > Yes, I'm busy working on the short list and other coin matters :-) > > -Joe > > From Joe.Darcy at Sun.COM Wed May 6 14:55:05 2009 From: Joe.Darcy at Sun.COM (Joe Darcy) Date: Wed, 06 May 2009 14:55:05 -0700 Subject: PROPOSAL: Abstract enums (version 2) In-Reply-To: <24400889.1241158807692.JavaMail.root@elwamui-hound.atl.sa.earthlink.net> References: <24400889.1241158807692.JavaMail.root@elwamui-hound.atl.sa.earthlink.net> Message-ID: <4A020739.4000607@sun.com> Hello. A few general comments and then some specifics. My general limited sympathy for this approach continues. For example, in the motivating example, the real enum types and enum constants could be defined to return TableEnumGuts objects (perhaps with type parameters) rather than delegating internally. For correctness, the TableEnumGuts objects should be immutable, etc. On the the specifics, as Bruce has pointed out, there is no "@AbstractEnum" annotation or class file attributes to mark enum types. There is an ACC_ENUM class modifier bit used for that purpose. However, today there are situations where the class file is marked with ACC_ENUM and the class file is marked abstract; this occurs when an enum type declares an abstract method and each enum constant is implemented with a specialized enum constant class that implements the method. The compiler checks that these structural correctness conditions are satisfied and that "abstract" is *not* applied in source to the enum type even though an abstract class results. Enum types have strong instance control; instances can only be created in the class itself (currently all constructors are implicitly private) and there are safeguards in the platform to prevent rogue enum instances being created via core reflection (setting accessible and calling a private enum constructor), cloning, and serialization. For example, core reflection checks the ACC_ENUM bit to prevent both constructors on enum types and the constructor of an anonymous classes implementing a specialized enum constant from being called reflectively. See java.lang.reflect.Constructor: 536 if ((clazz.getModifiers() & Modifier.ENUM) != 0) 537 throw new IllegalArgumentException("Cannot reflectively create enum objects"); 538 if (constructorAccessor == null) acquireConstructorAccessor(); 539 return (T) constructorAccessor.newInstance(initargs); http://hg.openjdk.java.net/jdk7/jdk7/jdk/file/6c7c0bccab55/src/share/classes/java/lang/reflect/Constructor.java This proposal would complicate making sure those instance control checks were still being enforced in all locations. -Joe On 04/30/09 11:20 PM, Derek Foster wrote: > Per feedback on the Project Coin mailing list, this proposal has been revised to provide more detail about how abstract enums affect serialization, class file format, the 'switch' statement, and 'Class.isEnum()', as well as additional text making more explicit the fact that this proposal is substantially different in both intent and implementation from various "extensible enums" proposals that have been considered and rejected in the past by the enum working group. > > AUTHOR: Derek Foster > > OVERVIEW > > The Java Enumerated type feature is unlike similar features in any other language which preceded it. In prior languages, an enumerated type was simply a collection of integer constants. In contrast, Java's enumerated type is a rich datatype that has more in common with classes than it has with a simple constants. Enumerated types can contain complex data, as well as methods to operate on that data. Individual enumerators may be subclasses of the enumeration class that contains them, and may override methods to provide enumerator-specific behavior. > > Unfortunately, there is one striking difference between Java's enumerations and classes that can become a significant inconvenience: While classes allow use of a superclass to hold data and methods which are shared between a variety of subclasses, Java enumerations have no such feature. In particular, every Java enumerated type must explicitly specify all of its data and methods that are not inherited from the base class Enum. If there are a number of enumerations that share related behavior, each enumeration must specify it redundantly. The only way to share behavior between these enumerations is to manually implement use delegation. > > Note that the term "abstract enum" is somewhat imprecise, and has historically been interpreted (in particular, by the team responsible for defining how to add enumerated types to Java) to refer to a different concept than the one that is specified by this proposal. Specifically, the "extendable enums" approach, in which an abstract enumerated type which declares enumeration constants could be extended by another enumerated type which declares additional constants. Since there seems to have been some confusion on this point, I wish to specifically point out that the interpretation of the phrase "abstract enum" as it is used in this proposal is quite different from that assumed by the "extensible enums" feature that has been considered (and rejected) in the past. The extensible enums proposal was an attempt to define behavior of concrete subtypes of concrete enumerated types. This proposal, on the other hand, attempts to define the behavior of abstract uninstantiable supertypes of enumerated types. The focus of this proposal is not on adding "interface"-related features to enums -- it is on implementation sharing. As such, it is specifically designed to avoid the implementation and specification problems (difficulty with serialization, switch statements, etc.) that have given the phrase "abstract enums" a bad name in the past. > > For instance, imagine a system in which enumerations are used to access columns of tables in a relational database. There might be one enumeration for each table, and the enumerators of each type might represent the columns in that table. Presumably, each enumerator would contain the name of the table, as well as the name of a specific column, and perhaps other metadata, such as access privileges. > > It would seem natural to model such a system like this: > > enum Access { PUBLIC, PRIVATE }; > > /** > * This holds the shared definition of what it means > * to be a database table column identifier > */ > abstract enum TableColumnDef { > // Note: No enum constants are declared here! > // This is just a supertype! > private String tableName; > private String columnName; > private Access access; > protected TableColumnDef(String tablename, String columnName, Access access) { > this.tableName = tableName; > this.columnName = columnName; > this.access = access; > } > public String getTableName() { > return tableName; > } > public String getColumnName() { > return columnName; > } > public Access getAccess() { > return access; > } > @Override > final String toString() { > return tableName + "." + columnName; > } > } > > /** A specific table */ > enum PersonTable extends TableColumnDef { > NAME_COLUMN("Name", Access.PUBLIC), > AGE_COLUMN("Age", Access.PRIVATE), > WEIGHT_COLUMN("Weight", ACCESS.PUBLIC); > private PersonTable(String columnName, Access access) { > super("PersonTable", columnName, access); > } > } > > /** Another specific table */ > enum PetTable extends TableColumnDef { > PETNAME_COLUMN("PetName", Access.PUBLIC), > SPECIES_COLUMN("Species", Access.PUBLIC); > private PersonTable(String columnName, Access access) { > super("PetTable", columnName, access); > } > } > > However, this cannot be done in Java, because inheritance from user-specified abstract types is not supported for enumerated types. (The only abstract type that is considered legal to inherit from is Enum). The closest equivalent in Java as it currently exists is to model the desired system is something like this, using delegation instead of inheritance: > > class TableEnumGuts { > private String tableName; > private String columnName; > private Access access; > protected DatabaseEnum(String tablename, String columnName, Access access) { > this.tableName = tableName; > this.columnName = columnName; > this.access = access; > } > public String getTableName() { > return tableName; > } > public String getColumnName() { > return columnName; > } > public Access getAccess() { > return access; > } > @Override > final String toString() { > return tableName + "." + columnName; > } > } > > enum PersonTable { > NAME_COLUMN("Name"), > AGE_COLUMN("Age"), > WEIGHT_COLUMN("Weight"); > private TableEnumGuts guts; > private PersonTable(String columnName, Access access) { > guts = new TableEnumGuts("PersonTable", columnName, access); > } > public String getTableName() { > return guts.getTableName(); > } > public String getColumnName() { > return guts.getColumnName(); > } > public Access getAccess() { > return guts.getAccess(); > } > @Override > final String toString() { > return guts.toString(); > } > } > > enum PetTable extends TableEnum { > PETNAME_COLUMN("PetName"), > SPECIES_COLUMN("Species"); > private TableEnumGuts guts; > private PersonTable(String columnName) { > guts = new TableEnumGuts("PersonTable", columnName, access); > } > public String getTableName() { > return guts.getTableName(); > } > public String getColumnName() { > return guts.getColumnName(); > } > public Access getAccess() { > return guts.getAccess(); > } > @Override > final String toString() { > return guts.toString(); > } > } > > Note how much more code (and worst of all, boilerplate duplicate code) is required in the second example, since each enumerated type must provide forwarding methods for each method in the 'TableEnumGuts' class. > > In one example that the author of this proposal was forced to deal with, there were 30 such enumerated types which conceptually extended the same base class, each of which had to implement that conceptual inheritance by delegating four or so methods to an internal "guts" object. This meant that any time time the signature of any of those four methods had to be changed, the change had to take place in 30 different forwarding methods as well. In another case (working for a different company) there were 10 such methods, duplicated over four conceptual subclasses, with similar problems. > > This proposal attempts to solve the above problem by defining the semantics of abstract enumerated types, and what it means for an enumerated type to have an abstract supertype, so as to allow code similar to the first example to work as expected in a Java compiler. > > > FEATURE SUMMARY: > > Defines the meaning of inheritance from abstract supertypes for enumerated types. > > Note that this proposal specifically does not allow abstract enumerated types to have enumerators, since the semantics of these create difficult problems with inheritance (and open, in the words of one evaluator to a Sun bug submission, "a can of worms", related to the defunct "extendable enums" idea that has been proposed and rejected in the past.). > > > MAJOR ADVANTAGE: > > Eliminates a missing feature between java enumerations and java classes, and restores a feature of the "typesafe enumeration" pattern that is not supported by Java enumerations as they are currently implemented. > > > MAJOR BENEFIT: > > Elimination of duplicate code when related enumerated types need to be declared. Allows subclassing within enumeration types. Eases maintenance of families of enumerated types. Makes implementation sharing among related enumerated types work in a familiar manner analogous to how it works with classes. > > > MAJOR DISADVANTAGE: > > There will be some work in the compiler necessary to implement this feature. > > Some people would like to be able to have concrete enums extend each other ("extensible enums"). This proposal does not attempt to provide such a feature, since it has been determined to be very difficult to specify and implement in the past. > > > ALTERNATIVES: > > Note the delegation workaround being used above. This allows subtypes to share code, but results in potentially large numbers of forwarding methods and difficulties with code maintenance. > > > EXAMPLES > > SIMPLE EXAMPLE: > > abstract enum SuperEnum { > // Note: no enum constant declarations allowed here! > int getTheAnswerToTheUltimateQuestion() { > return 42; > } > } > > enum MyEnum extends SuperEnum { > MY_ENUMERATOR; > } > > class DeepThought { > Object returnTheAnswer() { > MyEnum[] values1 = MyEnum.values(); // OK > MyEnum values2 = MyEnum.valueOf("MY_ENUMERATOR"); // OK > SuperEnum values1 = SuperEnum.values(); // Error: No such method > SuperEnum values2 = SuperEnum.valueOf("whatever"); // Error: No such method > return MY_ENUMERATOR.getTheAnswerToTheUltimateQuestion(); > } > } > > ADVANCED EXAMPLE: > > abstract enum Base1 { > protected final int sharedData; > public int getSharedData() {return sharedData;} > protected Base1(int sharedData) { > this.sharedData = sharedData; > } > } > > abstract enum Base2 extends Base1 { > protected final int otherSharedData; > public int getOtherSharedData() {return sharedData;} > protected Base2(int sharedData, int otherSharedData) { > super(sharedData); > this.otherSharedData = sharedData; > } > } > > enum Instances extends Base2 { > INSTANCE1(10, 100), > INSTANCE2(20, 200), > INSTANCE3(30, 300) { > public int getSharedData() { return 40; } > } > private Instances(int sharedData, int otherSharedData) { > super(sharedData, otherSharedData); > } > } > > class AClient { > void someFunc() { > assert INSTANCE1.getSharedData()==10; > assert INSTANCE2.getSharedData()==20; > assert INSTANCE3.getSharedData()==40; > Instances[] values = instances.values(); // OK > Base2[] values = Base2.values(); // Error: No such method. > } > } > > DETAILS > > SPECIFICATION: > > A concept of an "abstract enum" shall be added to the Java language, denoted by prepending the word "abstract" to an enumerated type declaration, with restrictions as described below. > > Rule 1: An enumerated type shall either declare no supertype, or shall declare a supertype which is an abstract enumerated type. > > Rule 2: It shall be a compile-time error for an ordinary class to extend an enumerated type, either abstract or not. > > Rule 3: Both abstract and non-abstract enumerated types shall implicitly have a supertype (not necessarily a direct supertype) of Enum>. Thus, within the body of an abstract enumerated type, access to methods of this supertype is allowed. > > Rule 4: Abstract enumerated types shall not declare enumerators. The body of an abstract enumerated type shall be syntactically and semantically the same as that of an ordinary abstract class which extends its supertype (see rule 3), except with the restriction that all constructors shall be declared with 'protected' or 'package' access (since the class is abstract and cannot declare instances, constructors can only be invoked by subclasses so there is no need to make them more public than necessary). > > Rule 5: In an abstract enum, the compiler shall not generate the methods that it would generate for a non-abstract enumerated type (specifically, the "values()" or "valueOf(String) methods), for an abstract enumerated type. (Since it is illegal for there to be enumerators declared in an abstract enum, these methods would serve no purpose.) > > Rule 6: It shall be illegal for the expression used in a 'switch' statement to be an abstract enum type. > > > Specifically, section 8.9 of the JLS3, which currently reads: > > " > An enum declaration has the form: > > EnumDeclaration: > ClassModifiers_opt enum Identifier Interfaces_opt EnumBody > " > > shall be modified to read: > > " > An enum declaration has the form: > > EnumDeclaration: > ClassModifiersopt enum Identifier Super_opt Interfaces_opt EnumBody > " > > Also, section 8.1.1.1 of the JLS3, which currently reads: > > "Enum types (?8.9) must not be declared abstract; doing so will result in a compile-time error. It is a compile-time error for an enum type E to have an abstract method m as a member unless E has one or more enum constants, and all of E's enum constants have class bodies that provide concrete implementations of m. It is a compile-time error for the class body of an enum constant to declare an abstract method." > > shall be modified to read: > > "Enum types (?8.9) may be declared abstract. If an enum type is declared abstract, it may declare abstract methods. However, it is a compile-time error for an abstract enum type to declare enum constants. Furthermore, it is a compile-time error for any constructor declared by an abstract enum type to have 'public' or 'private' access. > > It is a compile-time error for a non-abstract enum type E to have an abstract method m as a member (either explicitly declared or implicitly inherited from an abstract enum supertype) unless E has one or more enum constants, and all of E's enum constants have class bodies that provide concrete implementations of m. It is a compile-time error for the class body of an enum constant to declare an abstract method. > " > > also, in the same section, the text which currently reads: > > "If the enum type has no constructor declarations, a parameterless default constructor is provided (which matches the implicit empty argument list). This default constructor is private." > > shall be modified to read: > > "If the enum type has no constructor declarations, a parameterless default constructor is provided (which matches the implicit empty argument list). This default constructor is protected if the enum is abstract, and private if it is non-abstract." > > and in the same section, the text which currently reads: > > "The direct superclass of an enum type named E is Enum." > > shall be modified to read: > > "A non-abstract enum type named E has a superclass (either direct or indirect via one or more abstract enums) of Enum." > > and in the same section, the text which currently reads: > > " > It is a compile-time error for an enum to declare a finalizer. An instance of an enum may never be finalized. > > In addition, if E is the name of an enum type, then that type has the following implicitly declared static methods: > " > > shall be modified to read: > > " > It is a compile-time error for an enum (whether abstract or not) to declare a finalizer. An instance of an enum may never be finalized. > > In addition, if E is the name of a non-abstract enum type, then that type has the following implicitly declared static methods: > " > > and in the same section, the text which currently reads: > > " > It is a compile-time error to reference a static field of an enum type that is not a compile-time constant (?15.28) from constructors, instance initializer blocks, or instance variable initializer expressions of that type. It is a compile-time error for the constructors, instance initializer blocks, or instance variable initializer expressions of an enum constant e to refer to itself or to an enum constant of the same type that is declared to the right of e. > " > > shall be modified to read: > > " > It is a compile-time error for a non-abstract enum type to reference one of its static fields which is not a compile-time constant (?15.28) from constructors, instance initializer blocks, or instance variable initializer expressions of that type. It is a compile-time error for the constructors, instance initializer blocks, or instance variable initializer expressions of an enum constant e to refer to itself or to an enum constant of the same type that is declared to the right of e. Note however that any code within a non-abstract enum type may legally reference static fields of its abstract enum supertypes, if such supertypes and fields exist. > " > > > > > and in section 14.11 ('The switch statement'), the text which reads: > > "The type of the Expression must be char, byte, short, int, Character, Byte, Short, Integer, or an enum type (?8.9), or a compile-time error occurs." > > shall be modified to read: > > "The type of the Expression must be char, byte, short, int, Character, Byte, Short, Integer, or a non-abstract enum type (?8.9), or a compile-time error occurs." > > > > COMPILATION: > > An abstract enumerated type with no declared supertype, such as: > > abstract enum Foo { > ,,, > } > > shall be desugared to code resembling: > > @AbstractEnum > abstract class Foo> extends Enum { > ... > } > > where "@AbstractEnum" is a private compiler-generated annotation similar to the one which is currently used to mark normal enumerated types, and in the same package. Like the annotation which is currently used to mark enumerated types, the @AbstractEnum annotation shall not be visible to ordinary users in source code form -- it exists solely in class files, to allow the compiler to distinguish an abstract class which was declared with the "abstract enum" syntax from one which was declared with the "abstract class" syntax, for the purpose of determining whether an attempt by one class to inherit from another (which may not be supplied in source code form) is legitimate. > > An abstract or non-abstract enumerated type with a declared supertype (which must be an abstract enumerated type), such as: > > abstract enum Foo1 extends Bar { > ... > } > > enum Foo2 extends Bar { > ... > } > > > shall be desugared to code resembling: > > @AbstractEnum > abstract class Foo1> extends Bar { > ... > } > > @... > class Foo2 extends Bar { > ... > } > > > When compiling such a class, the compiler shall emit a compile-time error if an enum (abstract or not) extends a supertype S unless the following is true: > > 1) Either S is declared as an "abstract enum" (if specified in source code form) or S is declared with the @AbstractEnum annotation (if specified in binary class file form), or the erasure of S is the type java.lang.Enum. > > 2) Regardless of whether S and its supertypes are declared in source code form or in binary class file form, all supertypes of S shall obey these same constraints. > > Furthermore, if a normal class is declared like so: > > class Bar extends Baz { > } > > it shall be a compile-time error if class Baz is declared in source code to be an abstract enum, or if its binary class file representation has the @AbstractEnum annotation. > > The Java compiler currently generates certain methods, such as values() and valueOf(String) for enumerated types. It shall not generate these for abstract enumerated types. That is, the following shall be a compile-time error: > > abstract enum Foo { > } > > void bar() { > Foo[] foo1 = Foo.values(); // Error: no such method as 'Foo.values()' > Foo foo2 = Foo.valueOf("whatever"); // Error: no such method as 'Foo.valueOf(String)' > } > > > SIMPLE EXAMPLE: > > These classes might be desugared to: > > @AbstractEnum > abstract class SuperEnum> extends Enum { > int getTheAnswerToTheUltimateQuestion() { > return 42; > } > } > > @... > class MyEnum extends SuperEnum { > // The majority of this non-abstract enumerated type, > // including generated methods and annotations, is exactly > // the same as the Java compiler would generate > // prior to this proposal. However, note that due to > // this proposal, it has a supertype of "SuperEnum" > // instead of "Enum". > } > > ADVANCED EXAMPLE: > > These classes might be desugared to: > > @AbstractEnum > abstract class Base1> extends Enum { > protected final int sharedData; > public int getSharedData() {return sharedData;} > protected Base1(int sharedData) { > this.sharedData = sharedData; > } > } > > @AbstractEnum > abstract class Base2> extends Base1 { > protected final int otherSharedData; > public int getOtherSharedData() {return sharedData;} > protected Base2(int sharedData, int otherSharedData) { > super(sharedData); > this.otherSharedData = sharedData; > } > } > > @... > class Instances extends Base2 { > // The majority of this non-abstract enumerated type, > // including generated methods and annotations, is exactly > // the same as the Java compiler would generate > // prior to this proposal. However, note that due to > // this proposal, it has a supertype of "Base2" > // instead of "Enum". > } > > > TESTING: > > Testing can be accomplished by declaring various abstract enumerated types, having them extend each other, and having non-abstract enumerated types extend them. Normal inheritance relations (method overriding, etc.) should exist among the resulting types. > > Furthermore, at least one test should ensure that an attempt to extend an abstract enum (either specified in source or binary form) with a normal class is considered illegal, as is an attempt to have a non-abstract enum or an abstract enum extend a class which is not an abstract enum. > > Furthermore, a test should ensure that an attempt to use an expression whose compile-time type is that of an abstract enum in a 'switch' statement is considered illegal. > > Furthermore, a test should ensure that an attempt to reference the "values()" or "valueOf()" methods of an abstract enum is considered illegal. > > > LIBRARY SUPPORT: > > No changes to supporting libraries are needed, except for the addition of the "@AbstractEnum" annotation type as mentioned above. > > REFLECTIVE APIS: > > The "Class.isEnum()" method shall return false when invoked on an abstract enum. (This is necessary to avoid unexpected side effects in methods which currently depend on identifying concrete enumerated types with this method. Technically, despite the syntax used to declare them, abstract enums aren't really enums -- they are just supertypes of them, and so should be treated basically exactly the same as class Enum is for the purposes of reflection, etc. This should be documented clearly in the javadoc for Class.isEnum()) > > It may be desirable to create a "Class.isAbstractEnum()" convenience method to detect the @AbstractEnum annotation. For consistency, such a method should probably return 'true' when invoked on the Enum supertype as well. > > > OTHER CHANGES: > > Javadoc might possibly need to be updated to handle the possibility of generating documentation for an abstract enumerated type. > > In order to allow abstract supertypes to be added or removed from an abstract enum without making it impossible to read back existing serialized data, it will be necessary to modify the Java serialization specification as follows: > > In section "1.12 Serialization of Enum Constants", the following text shall be added at the end of the section: > > " > Furthermore, in order to preserve the ability to deserialize enumerated constants which may have been serialized with an enumerated type having a different type hierarchy from what was written (due to the addition or deletion of "abstract enum" supertypes), the type of every enumerated constant shall be serialized and deserialized as if the immediate supertype of the declared non-abstract enum type which defines the constant was java.lang.Enum. In particular, a type such as: > > abstract enum Foo { > } > > abstract enum Bar extends Foo { > } > > enum Baz extends Bar { > QUX; > } > > shall exist in serialized form exactly as if it were declared as: > > enum Baz { // implicit supertype of Enum> > QUX; > } > " > > MIGRATION: > > New abstract enumerated types can be created, as desired, to do code sharing between existing non-abstract enumerated types in an existing code base. > > The above "OTHER CHANGES" section ensures that adding or removing abstract supertypes of an enum will not affect the ability to serialize or deserialize instances of it. > > COMPATIBILITY > > BREAKING CHANGES: > > Since this syntax was previously considered a syntax error, no previously valid programs will be invalidated by it. > > EXISTING PROGRAMS: > > This feature should not change the semantics of existing class files. The features being added should desugar to normal method calls, class declarations, etc. Hence, I do not anticipate problems interacting with existing class files. > > REFERENCES > > EXISTING BUGS: > > Add language support for abstract Enum's > http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6507006 > > allow "abstract enum AbstractEnum" and "enum MyEnum extends AbstractEnum" > http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6222244 > > Support for public abstract enum declaration > http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6570766 > > (The original enum proposal, the comments for which allude to the possibility of abstract enums) > Bug ID: 4401321 Add type-safe enums to Java > http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4401321 > > > URL FOR PROTOTYPE (optional): > > Although not implemented in response to this specific proposal, Fred Simon has implemented a substantially similar feature in Kijaro: > > http://tech.puredanger.com/2008/01/10/property-enum/ > > > > From howard.lovatt at iee.org Wed May 6 17:32:13 2009 From: howard.lovatt at iee.org (Howard Lovatt) Date: Thu, 7 May 2009 10:32:13 +1000 Subject: PROPOSAL: Abstract enums (version 2) Message-ID: <3dd3f56a0905061732i28671059xcce2b22189ec805e@mail.gmail.com> Hi Derek, Your proposal isn't as straight forward as you are making out, Joe Darcy has summarised the issues nicely. If we made Enum an interface and had the compiler synthesise the required methods then this would allow any compatible class (see below) to be a super class of an enum. IE a class declared using enum, whether abstract enum or plain enum, would implicitly implement Enum, implicitly have private constructors, and the compiler would add the methods and fields that are currently in class Enum (including valueOf). A compatible superclass would need to be compatible with interface Enum and have an accessible no-args constructor. The no-args constructor limitation of superclasses isn't strictly necessary, but it simplifies the compiler (relaxing the no-args rule could be for Java 8 :) ). The tricky bit is method valueOf, because this method is static and therefore can't be specified in an interface. As stated above this method is added to enums and this will catch most uses of this method in user code. However code that currently says Enum.valueOf( ... ) will break. To ease the transition an Enums, note s, class with a static valueOf could be provided. This is a simpler change, e.g. no change in meaning of abstract enum, and also a more powerful change, i.e. any compatible class can be the superclass. It is theoretically possible that this change would break existing code, as outlined above, but in practice I doubt if much code would actually be broken. Obviously one of the issues for an expert group to study would be my claim, based on my own coding style, that little code in practice would be broken. -- Howard. From vapor1 at teleport.com Wed May 6 21:16:27 2009 From: vapor1 at teleport.com (Derek Foster) Date: Thu, 7 May 2009 00:16:27 -0400 (EDT) Subject: PROPOSAL: Abstract enums (version 2) Message-ID: <12684881.1241669787649.JavaMail.root@elwamui-norfolk.atl.sa.earthlink.net> -----Original Message----- >From: Bruce Chapman >Sent: May 1, 2009 7:06 AM >To: Derek Foster , "coin-dev at openjdk.java.net" >Subject: Re: PROPOSAL: Abstract enums (version 2) > >... >Should this type parameter be explicit or implicit? - guess since enums >have an explicit extends, abstract ones could have an explicit type >parameter. > >your compilation section chooses implicit and says > > abstract enum Foo {} > >shall be desugared to code resembling: > > @AbstractEnum abstract class Foo> extends Enum {} > >But I think it should be > > abstract class Foo> extends Enum { I think you are right on this -- I had intended it to be that way, but mistyped. I will post a revised proposal. >re @AbstractAnnotation > >I think you are confusing annotations in source files, with byte code >annotations which are different. You are correct -- I was using a webpage for my reference which was not clear on which was being used in this case. I have since found the relevant sections in the class file specification which makes it more clear that the ACC_ENUM flag of the access_flags field in the class file is being used for this. However, having done this, I'm not sure that the approach I suggested in my proposal is necessarily a bad idea -- the bits in the access_flags section of the class file format are a limited resource, after all, and over half of them (8 out of a possible 16) are already allocated. Still, by default it probably makes more sense to assume use of an ACC_ABSTRACTENUM flag rather than an @AbstractEnum annotation, with a comment that the @AbstractEnum approach could be used if necessary. I am in the process of revising the proposal, and will make this change when I do so. > I don't think you'd need a new >annotation (of either sort) because the bytecode for an abstract enum >could have both the normal abstract annotation/modifier, and the >existing enum one, allowing the compiler to correctly determine that it >was in fact an abstract enum. I don't think that this will work. The reason is that in the language as it exists now, in cases where enums have anonymous subclasses for individual enum constants, the declared enum type has both ACC_ENUM and ACC_ABSTRACT already. If the presence of these flags were the only distinguishing feature, these enum types would be impossible to distinguish from the user-specified enum supertypes that my proposal adds to the language. It was for this reason that I chose to introduce the "@AbstractEnum" annotation in my proposal (which I will change to ACC_ABSTRACTENUM when I revise it) rather than trying to alter the meaning of the existing ACC_ENUM annotation. As Joe Darcy points out (in a message that I will answer next), altering the meaning of the existing annotation has the potential to cause unexpected consequences on the algorithms that manipulate it. The intent of my proposal was to sidestep this issue by adding a new annotation and leaving the old one to mean exactly what it already does, so that these algorithms would be unaffected. Note that the existing algorithms that care about ACC_ENUM are basically concerned with the creation of and inheritance from the actual concrete enum types (and their anonymous subtypes). They are looking "down" the type hierarchy, which is not changed by my proposal, rather than "up" the type hierarchy, which my proposal affects. Therefore, these algorithms don't really need to care about whether or not a concrete enum type has only one abstract supertype (Enum) or more than one (as my proposal would allow). By using an ACC_ABSTRACTENUM annotation instead of altering the meaning of ACC_ENUM, I can allow their behavior to continue unchanged. >Could the abstract enum have type parameters, such that declared methods >were type polymorphic? (You enum for database table columns comes to >mind here) and if so, could the methods be abstract thereby forcing the >concrete enum to implement it? The basic argument here is that if you >are fixing enums to be consistent with the rest of the language in terms >of inheritance, then maybe you should be in terms of type polymorphism >as well. If you did, it would put a different slant on the >implicit/explicit type parameter issue discussed above. An interesting question. I mulled over this for a while, but was unable to come up with a solution I liked very much that was consistent with the rest of the language. For instance, if the type parameter is explicit, that leaves people typing things like: abstract enum Foo> { // Implicitly extends Enum E getSuccessor() {return getDeclaringClass().getEnumConstants()[ordinal()+1];} } abstract enum Bar> extends Foo { } enum Baz extends Bar> { SPORK, CHATOYANCY, WOMBAT, CHEESE; } which is quite annoyingly verbose but is what you would have to do if the user really had to specify the types correctly. This would require the compiler to do a bunch of extra checking as well, to make sure that all of the types were in fact correctly specified according to the necessary pattern. This seems like it would complicate basic use of the feature considerably (making the user type lots of boilerplate code), in order to handle a rare use case. Another alternative would be to allow the user to just specify the name of the type parameter, and have its type be determined by the compiler (or omit even the name if it wasn't going to be used), such as: abstract enum Foo { // Implicitly extends Enum> E getSuccessor() {return getDeclaringClass().getEnumConstants()[ordinal()+1];} } abstract enum Bar extends Foo { // No need for Bar since not used in the body } enum Baz extends Bar { SPORK, CHATOYANCY, WOMBAT, CHEESE; } This is nicely compact and requires the user to only specify the one thing they can change (the name of the type parameter, not its type). However, it is inconsistent with how the language normally works (Foo normally indicates that E extends Object, not that E extends Foo), which could be confusing. I think on the whole, that referencing a subtype like this is a rare enough occurrence (I had to struggle to come up with plausible examples like the getSuccessor() method above) that we probably can do without language support for it. After all, in general, ordinary types can't access their subtypes like this at all, so the fact that it is even possible in the case of Enums is rather unusual. If this feature is desperately needed, most of the obvious (to me, anyway) use cases can be handled with existing techniques like method return covariance anyway: abstract enum Foo { // Implicitly extends Enum> Foo getSuccessor() {return getDeclaringClass().getEnumConstants()[ordinal()+1];} } abstract enum Bar extends Foo { } enum Baz extends Bar { SPORK, FRIENDSHIP, WOMBAT, CHEESE; @Override Baz getSuccessor() { return (Baz)super.getSuccessor(); } } >Other than those issues, this proposal is looking good by me. Thanks for the feedback! Derek From Joe.Darcy at Sun.COM Wed May 6 22:14:58 2009 From: Joe.Darcy at Sun.COM (Joseph D. Darcy) Date: Wed, 06 May 2009 22:14:58 -0700 Subject: On PROPOSAL Narrow Hexadecimal and Binary Integer Literals In-Reply-To: <4A0001E7.1020506@sun.com> References: <4A0001E7.1020506@sun.com> Message-ID: <4A026E52.3070809@sun.com> Weijun Wang wrote: > Hi All > > I'm reading this proposal, which recommends: > > byte[] stuff = { 0x00, 0x7F, (byte)0x80, (byte)0xFF}; > > can be recoded as > > byte[] ufum7 = { 0h00, 0h7F, 0h80, 0hFF}; > > How about using the C style? > > byte[] bs = '\x00\x7f\x80\xff'; > > This should work since multiple bytes in '' is illegal now. When you > I think this style of syntax is too far of a departure from current practice. > want to create a byte[] with only one element, you still have to write > > byte[] bs = { 0x00 }; > > BTW, if the VM can be enhanced to support byte[] in constant pool, that > will be even better. Of course, if the VM is already able to view > bytecodes from the statement above as a single byte block reference, > that's enough. > > Thanks > Max > > Better VM support for constant data of various kinds would be handy, but outside the scope of Coin. -Joe From vapor1 at teleport.com Thu May 7 00:17:00 2009 From: vapor1 at teleport.com (Derek Foster) Date: Thu, 7 May 2009 03:17:00 -0400 (EDT) Subject: PROPOSAL: Abstract enums (version 2) Message-ID: <27092986.1241680621030.JavaMail.root@elwamui-norfolk.atl.sa.earthlink.net> -----Original Message----- >From: Joe Darcy >Sent: May 6, 2009 5:55 PM >To: Derek Foster >Cc: Project Coin >Subject: Re: PROPOSAL: Abstract enums (version 2) > >Hello. > >A few general comments and then some specifics. > >My general limited sympathy for this approach continues. For example, >in the motivating example, the real enum types and enum constants could >be defined to return TableEnumGuts objects (perhaps with type >parameters) rather than delegating internally. For correctness, the >TableEnumGuts objects should be immutable, etc. Hi, Joe. Thanks for the detailed reply. It is true that an enum could be refactored in the manner you suggest above. However, please note that this approach has some notable drawbacks. For instance, it makes an implementation concern (sharing of implementation among related enum subclasses) into an interface concern (now everyone who uses the enum has to use "foo.getGuts().bar()" instead of "foo.bar()". For instance, it means that all the clients of the class have to be modified. If there were two similar enums from which someone might want to do a conceptual "extract superclass" refactoring in order to reduce duplicate code, they cannot do it with this technique without modifying pretty much EVERY location where those enums are used (or at least, every location where a method call is made on them). If both the definition and all uses of the enums occur within the same codebase, which is modifiable, this can be done (although it is ugly, and annoying in that it may cause changes to a lot of code outside of the enums being so modified). However, if the enums are within a library which is delivered as a JAR file to various clients (say, released as open source on a website), then this refactoring would be a heavily breaking change to all of the clients that might use it. API definers are understandably fairly unwilling to make changes like this. In order to keep the interface stable, they would basically be forced into using some variation of the delegation approach I suggested, or some form of duplicate code. >On the the specifics, as Bruce has pointed out, there is no >"@AbstractEnum" annotation or class file attributes to mark enum types. >There is an ACC_ENUM class modifier bit used for that purpose. However, >today there are situations where the class file is marked with ACC_ENUM >and the class file is marked abstract >... >This proposal would complicate making sure those instance control checks >were still being enforced in all locations. Although I understand and am sympathetic to the issue you are raising here, I think that your concern for its application in this case stems from an incorrect understanding of the details of my proposal. I have already replied to Bruce on this, but to clear up some apparent confusion, I would like to point out that it was never part of my proposal to suggest that ACC_ENUM combined with ACC_ABSTRACT was an acceptable substitute for @AbstractEnum. Bruce suggested this in his recent email, but (as I just pointed out in my reply to him) I deliberately decided when writing my proposal not to take that approach, for basically exactly the reasons you list. Firstly, that it is ambiguous with respect to the existing uses of ACC_ENUM with ACC_ABSTRACT on enum classes with anonymous subtypes, and secondly, that it would require extensive re-analysis and possibly re-working of any algorithms that depended on the existing behavior and definition of ACC_ENUM. You have in the past stated how difficult it was to get these algorithms right, and I share your concern that changes to these would be difficult to perform correctly. Therefore, I tried to design my proposal so that changes are unnecessary. For this reason, I left the behavior of ACC_ENUM unmodified, but introduced a new annotation, which I called @AbstractEnum in version 2 of the proposal but for which I will use a new class attribute (ACC_ABSTRACTENUM) in the upcoming version 3 which I will post tonight. ACC_ABSTRACTENUM is intended for exactly one purpose: allowing the compiler to detect illegal attempts to inherit abstract enums from normal classes and vice versa. This can't be done with ACC_ENUM because these classes will not have ACC_ENUM set on them (since that would change its current definition by widening it to include abstract supertypes of enums, which it is currently not used for). Note that ACC_ABSTRACTENUM will have no effect on serialization, Class.isEnum(), or any other existing code which currently makes decisions based on the presence or absence of ACC_ENUM. So a typical hierarchy might be something like: Enum // ACC_ABSTRACT abstract enum Foo { } // ACC_ABSTRACT, ACC_ABSTRACTENUM abstract enum Bar extends Foo { } // ACC_ABSTRACT, ACC_ABSTRACTENUM enum Baz extends Bar { BAZ1; } // ACC_ENUM enum Qux extends Bar { // ACC_ABSTRACT, ACC_ENUM QUX1 { void quux() {} }; abstract void quux(); } Thus, the existing algorithms that depend on ACC_ENUM meaning what it currently does should continue to work unmodified. ACC_ENUM will continue to be used as it currently is to detect illegal attempts to manipulate enums that are not declared abstract (illegal attempts such as cloning, constructing by reflection, illegally inheriting from, and so forth). Note that most of these operations are already illegal on any abstract class: you can't construct an abstract class by reflection, for instance, or try to clone one if neither its superclass Enum nor its subclass [a specific concrete enum] support cloning. Therefore, the only related issues for enums declared abstract are those which ACC_ABSTRACTENUM is intended to deal with, namely illegal inheritance. > 536 if ((clazz.getModifiers() & Modifier.ENUM) != 0) > 537 throw new IllegalArgumentException("Cannot >reflectively create enum objects"); > 538 if (constructorAccessor == null) >acquireConstructorAccessor(); > 539 return (T) constructorAccessor.newInstance(initargs); > >http://hg.openjdk.java.net/jdk7/jdk7/jdk/file/6c7c0bccab55/src/share/classes/java/lang/reflect/Constructor.java For example, the above code would be unmodified under my proposal: Since an enum declared abstract would not have the Modifier.ENUM attribute, there would be no confusion or change in behavior: it would be treated by this code exactly like the existing Enum class is. (Actually, there is another reason this particular code wouldn't change: this code could never be called for such a class anyway, since you can't call a constructor for an abstract class except from a subclass constructor, and doing so would thus perform the check on the non-abstract enum at the bottom of the inheritance hierarchy first. It would fail the check at that level before it ever got to trying to construct any abstract supertypes of that class.) As per what I have said above, I believe that this proposal will not affect the validity of existing instance control checks. They are already designed to have effect on the "enum" classes and their possible anonymous subclasses, but not on the abstract supertypes of them (of which only one currently exists: Enum). My proposal just adds the possibility of there being additional abstract supertypes in addition to Enum, which will have the same access control flags as it does (with the exception of ACC_ABSTRACTENUM which these existing checks won't know about and will therefore ignore) and thus these new abstract supertypes will be treated in the same manner by these checks as Enum is. Derek >On 04/30/09 11:20 PM, Derek Foster wrote: >> Per feedback on the Project Coin mailing list, this proposal has been revised to provide more detail about how abstract enums affect serialization, class file format, the 'switch' statement, and 'Class.isEnum()', as well as additional text making more explicit the fact that this proposal is substantially different in both intent and implementation from various "extensible enums" proposals that have been considered and rejected in the past by the enum working group. >> >> AUTHOR: Derek Foster >> >> OVERVIEW >> >> The Java Enumerated type feature is unlike similar features in any other language which preceded it. In prior languages, an enumerated type was simply a collection of integer constants. In contrast, Java's enumerated type is a rich datatype that has more in common with classes than it has with a simple constants. Enumerated types can contain complex data, as well as methods to operate on that data. Individual enumerators may be subclasses of the enumeration class that contains them, and may override methods to provide enumerator-specific behavior. >> >> Unfortunately, there is one striking difference between Java's enumerations and classes that can become a significant inconvenience: While classes allow use of a superclass to hold data and methods which are shared between a variety of subclasses, Java enumerations have no such feature. In particular, every Java enumerated type must explicitly specify all of its data and methods that are not inherited from the base class Enum. If there are a number of enumerations that share related behavior, each enumeration must specify it redundantly. The only way to share behavior between these enumerations is to manually implement use delegation. >> >> Note that the term "abstract enum" is somewhat imprecise, and has historically been interpreted (in particular, by the team responsible for defining how to add enumerated types to Java) to refer to a different concept than the one that is specified by this proposal. Specifically, the "extendable enums" approach, in which an abstract enumerated type which declares enumeration constants could be extended by another enumerated type which declares additional constants. Since there seems to have been some confusion on this point, I wish to specifically point out that the interpretation of the phrase "abstract enum" as it is used in this proposal is quite different from that assumed by the "extensible enums" feature that has been considered (and rejected) in the past. The extensible enums proposal was an attempt to define behavior of concrete subtypes of concrete enumerated types. This proposal, on the other hand, attempts to define the behavior of abstract uninstantiable supertypes of enumerated types. The focus of this proposal is not on adding "interface"-related features to enums -- it is on implementation sharing. As such, it is specifically designed to avoid the implementation and specification problems (difficulty with serialization, switch statements, etc.) that have given the phrase "abstract enums" a bad name in the past. >> >> For instance, imagine a system in which enumerations are used to access columns of tables in a relational database. There might be one enumeration for each table, and the enumerators of each type might represent the columns in that table. Presumably, each enumerator would contain the name of the table, as well as the name of a specific column, and perhaps other metadata, such as access privileges. >> >> It would seem natural to model such a system like this: >> >> enum Access { PUBLIC, PRIVATE }; >> >> /** >> * This holds the shared definition of what it means >> * to be a database table column identifier >> */ >> abstract enum TableColumnDef { >> // Note: No enum constants are declared here! >> // This is just a supertype! >> private String tableName; >> private String columnName; >> private Access access; >> protected TableColumnDef(String tablename, String columnName, Access access) { >> this.tableName = tableName; >> this.columnName = columnName; >> this.access = access; >> } >> public String getTableName() { >> return tableName; >> } >> public String getColumnName() { >> return columnName; >> } >> public Access getAccess() { >> return access; >> } >> @Override >> final String toString() { >> return tableName + "." + columnName; >> } >> } >> >> /** A specific table */ >> enum PersonTable extends TableColumnDef { >> NAME_COLUMN("Name", Access.PUBLIC), >> AGE_COLUMN("Age", Access.PRIVATE), >> WEIGHT_COLUMN("Weight", ACCESS.PUBLIC); >> private PersonTable(String columnName, Access access) { >> super("PersonTable", columnName, access); >> } >> } >> >> /** Another specific table */ >> enum PetTable extends TableColumnDef { >> PETNAME_COLUMN("PetName", Access.PUBLIC), >> SPECIES_COLUMN("Species", Access.PUBLIC); >> private PersonTable(String columnName, Access access) { >> super("PetTable", columnName, access); >> } >> } >> >> However, this cannot be done in Java, because inheritance from user-specified abstract types is not supported for enumerated types. (The only abstract type that is considered legal to inherit from is Enum). The closest equivalent in Java as it currently exists is to model the desired system is something like this, using delegation instead of inheritance: >> >> class TableEnumGuts { >> private String tableName; >> private String columnName; >> private Access access; >> protected DatabaseEnum(String tablename, String columnName, Access access) { >> this.tableName = tableName; >> this.columnName = columnName; >> this.access = access; >> } >> public String getTableName() { >> return tableName; >> } >> public String getColumnName() { >> return columnName; >> } >> public Access getAccess() { >> return access; >> } >> @Override >> final String toString() { >> return tableName + "." + columnName; >> } >> } >> >> enum PersonTable { >> NAME_COLUMN("Name"), >> AGE_COLUMN("Age"), >> WEIGHT_COLUMN("Weight"); >> private TableEnumGuts guts; >> private PersonTable(String columnName, Access access) { >> guts = new TableEnumGuts("PersonTable", columnName, access); >> } >> public String getTableName() { >> return guts.getTableName(); >> } >> public String getColumnName() { >> return guts.getColumnName(); >> } >> public Access getAccess() { >> return guts.getAccess(); >> } >> @Override >> final String toString() { >> return guts.toString(); >> } >> } >> >> enum PetTable extends TableEnum { >> PETNAME_COLUMN("PetName"), >> SPECIES_COLUMN("Species"); >> private TableEnumGuts guts; >> private PersonTable(String columnName) { >> guts = new TableEnumGuts("PersonTable", columnName, access); >> } >> public String getTableName() { >> return guts.getTableName(); >> } >> public String getColumnName() { >> return guts.getColumnName(); >> } >> public Access getAccess() { >> return guts.getAccess(); >> } >> @Override >> final String toString() { >> return guts.toString(); >> } >> } >> >> Note how much more code (and worst of all, boilerplate duplicate code) is required in the second example, since each enumerated type must provide forwarding methods for each method in the 'TableEnumGuts' class. >> >> In one example that the author of this proposal was forced to deal with, there were 30 such enumerated types which conceptually extended the same base class, each of which had to implement that conceptual inheritance by delegating four or so methods to an internal "guts" object. This meant that any time time the signature of any of those four methods had to be changed, the change had to take place in 30 different forwarding methods as well. In another case (working for a different company) there were 10 such methods, duplicated over four conceptual subclasses, with similar problems. >> >> This proposal attempts to solve the above problem by defining the semantics of abstract enumerated types, and what it means for an enumerated type to have an abstract supertype, so as to allow code similar to the first example to work as expected in a Java compiler. >> >> >> FEATURE SUMMARY: >> >> Defines the meaning of inheritance from abstract supertypes for enumerated types. >> >> Note that this proposal specifically does not allow abstract enumerated types to have enumerators, since the semantics of these create difficult problems with inheritance (and open, in the words of one evaluator to a Sun bug submission, "a can of worms", related to the defunct "extendable enums" idea that has been proposed and rejected in the past.). >> >> >> MAJOR ADVANTAGE: >> >> Eliminates a missing feature between java enumerations and java classes, and restores a feature of the "typesafe enumeration" pattern that is not supported by Java enumerations as they are currently implemented. >> >> >> MAJOR BENEFIT: >> >> Elimination of duplicate code when related enumerated types need to be declared. Allows subclassing within enumeration types. Eases maintenance of families of enumerated types. Makes implementation sharing among related enumerated types work in a familiar manner analogous to how it works with classes. >> >> >> MAJOR DISADVANTAGE: >> >> There will be some work in the compiler necessary to implement this feature. >> >> Some people would like to be able to have concrete enums extend each other ("extensible enums"). This proposal does not attempt to provide such a feature, since it has been determined to be very difficult to specify and implement in the past. >> >> >> ALTERNATIVES: >> >> Note the delegation workaround being used above. This allows subtypes to share code, but results in potentially large numbers of forwarding methods and difficulties with code maintenance. >> >> >> EXAMPLES >> >> SIMPLE EXAMPLE: >> >> abstract enum SuperEnum { >> // Note: no enum constant declarations allowed here! >> int getTheAnswerToTheUltimateQuestion() { >> return 42; >> } >> } >> >> enum MyEnum extends SuperEnum { >> MY_ENUMERATOR; >> } >> >> class DeepThought { >> Object returnTheAnswer() { >> MyEnum[] values1 = MyEnum.values(); // OK >> MyEnum values2 = MyEnum.valueOf("MY_ENUMERATOR"); // OK >> SuperEnum values1 = SuperEnum.values(); // Error: No such method >> SuperEnum values2 = SuperEnum.valueOf("whatever"); // Error: No such method >> return MY_ENUMERATOR.getTheAnswerToTheUltimateQuestion(); >> } >> } >> >> ADVANCED EXAMPLE: >> >> abstract enum Base1 { >> protected final int sharedData; >> public int getSharedData() {return sharedData;} >> protected Base1(int sharedData) { >> this.sharedData = sharedData; >> } >> } >> >> abstract enum Base2 extends Base1 { >> protected final int otherSharedData; >> public int getOtherSharedData() {return sharedData;} >> protected Base2(int sharedData, int otherSharedData) { >> super(sharedData); >> this.otherSharedData = sharedData; >> } >> } >> >> enum Instances extends Base2 { >> INSTANCE1(10, 100), >> INSTANCE2(20, 200), >> INSTANCE3(30, 300) { >> public int getSharedData() { return 40; } >> } >> private Instances(int sharedData, int otherSharedData) { >> super(sharedData, otherSharedData); >> } >> } >> >> class AClient { >> void someFunc() { >> assert INSTANCE1.getSharedData()==10; >> assert INSTANCE2.getSharedData()==20; >> assert INSTANCE3.getSharedData()==40; >> Instances[] values = instances.values(); // OK >> Base2[] values = Base2.values(); // Error: No such method. >> } >> } >> >> DETAILS >> >> SPECIFICATION: >> >> A concept of an "abstract enum" shall be added to the Java language, denoted by prepending the word "abstract" to an enumerated type declaration, with restrictions as described below. >> >> Rule 1: An enumerated type shall either declare no supertype, or shall declare a supertype which is an abstract enumerated type. >> >> Rule 2: It shall be a compile-time error for an ordinary class to extend an enumerated type, either abstract or not. >> >> Rule 3: Both abstract and non-abstract enumerated types shall implicitly have a supertype (not necessarily a direct supertype) of Enum>. Thus, within the body of an abstract enumerated type, access to methods of this supertype is allowed. >> >> Rule 4: Abstract enumerated types shall not declare enumerators. The body of an abstract enumerated type shall be syntactically and semantically the same as that of an ordinary abstract class which extends its supertype (see rule 3), except with the restriction that all constructors shall be declared with 'protected' or 'package' access (since the class is abstract and cannot declare instances, constructors can only be invoked by subclasses so there is no need to make them more public than necessary). >> >> Rule 5: In an abstract enum, the compiler shall not generate the methods that it would generate for a non-abstract enumerated type (specifically, the "values()" or "valueOf(String) methods), for an abstract enumerated type. (Since it is illegal for there to be enumerators declared in an abstract enum, these methods would serve no purpose.) >> >> Rule 6: It shall be illegal for the expression used in a 'switch' statement to be an abstract enum type. >> >> >> Specifically, section 8.9 of the JLS3, which currently reads: >> >> " >> An enum declaration has the form: >> >> EnumDeclaration: >> ClassModifiers_opt enum Identifier Interfaces_opt EnumBody >> " >> >> shall be modified to read: >> >> " >> An enum declaration has the form: >> >> EnumDeclaration: >> ClassModifiersopt enum Identifier Super_opt Interfaces_opt EnumBody >> " >> >> Also, section 8.1.1.1 of the JLS3, which currently reads: >> >> "Enum types (?8.9) must not be declared abstract; doing so will result in a compile-time error. It is a compile-time error for an enum type E to have an abstract method m as a member unless E has one or more enum constants, and all of E's enum constants have class bodies that provide concrete implementations of m. It is a compile-time error for the class body of an enum constant to declare an abstract method." >> >> shall be modified to read: >> >> "Enum types (?8.9) may be declared abstract. If an enum type is declared abstract, it may declare abstract methods. However, it is a compile-time error for an abstract enum type to declare enum constants. Furthermore, it is a compile-time error for any constructor declared by an abstract enum type to have 'public' or 'private' access. >> >> It is a compile-time error for a non-abstract enum type E to have an abstract method m as a member (either explicitly declared or implicitly inherited from an abstract enum supertype) unless E has one or more enum constants, and all of E's enum constants have class bodies that provide concrete implementations of m. It is a compile-time error for the class body of an enum constant to declare an abstract method. >> " >> >> also, in the same section, the text which currently reads: >> >> "If the enum type has no constructor declarations, a parameterless default constructor is provided (which matches the implicit empty argument list). This default constructor is private." >> >> shall be modified to read: >> >> "If the enum type has no constructor declarations, a parameterless default constructor is provided (which matches the implicit empty argument list). This default constructor is protected if the enum is abstract, and private if it is non-abstract." >> >> and in the same section, the text which currently reads: >> >> "The direct superclass of an enum type named E is Enum." >> >> shall be modified to read: >> >> "A non-abstract enum type named E has a superclass (either direct or indirect via one or more abstract enums) of Enum." >> >> and in the same section, the text which currently reads: >> >> " >> It is a compile-time error for an enum to declare a finalizer. An instance of an enum may never be finalized. >> >> In addition, if E is the name of an enum type, then that type has the following implicitly declared static methods: >> " >> >> shall be modified to read: >> >> " >> It is a compile-time error for an enum (whether abstract or not) to declare a finalizer. An instance of an enum may never be finalized. >> >> In addition, if E is the name of a non-abstract enum type, then that type has the following implicitly declared static methods: >> " >> >> and in the same section, the text which currently reads: >> >> " >> It is a compile-time error to reference a static field of an enum type that is not a compile-time constant (?15.28) from constructors, instance initializer blocks, or instance variable initializer expressions of that type. It is a compile-time error for the constructors, instance initializer blocks, or instance variable initializer expressions of an enum constant e to refer to itself or to an enum constant of the same type that is declared to the right of e. >> " >> >> shall be modified to read: >> >> " >> It is a compile-time error for a non-abstract enum type to reference one of its static fields which is not a compile-time constant (?15.28) from constructors, instance initializer blocks, or instance variable initializer expressions of that type. It is a compile-time error for the constructors, instance initializer blocks, or instance variable initializer expressions of an enum constant e to refer to itself or to an enum constant of the same type that is declared to the right of e. Note however that any code within a non-abstract enum type may legally reference static fields of its abstract enum supertypes, if such supertypes and fields exist. >> " >> >> >> >> >> and in section 14.11 ('The switch statement'), the text which reads: >> >> "The type of the Expression must be char, byte, short, int, Character, Byte, Short, Integer, or an enum type (?8.9), or a compile-time error occurs." >> >> shall be modified to read: >> >> "The type of the Expression must be char, byte, short, int, Character, Byte, Short, Integer, or a non-abstract enum type (?8.9), or a compile-time error occurs." >> >> >> >> COMPILATION: >> >> An abstract enumerated type with no declared supertype, such as: >> >> abstract enum Foo { >> ,,, >> } >> >> shall be desugared to code resembling: >> >> @AbstractEnum >> abstract class Foo> extends Enum { >> ... >> } >> >> where "@AbstractEnum" is a private compiler-generated annotation similar to the one which is currently used to mark normal enumerated types, and in the same package. Like the annotation which is currently used to mark enumerated types, the @AbstractEnum annotation shall not be visible to ordinary users in source code form -- it exists solely in class files, to allow the compiler to distinguish an abstract class which was declared with the "abstract enum" syntax from one which was declared with the "abstract class" syntax, for the purpose of determining whether an attempt by one class to inherit from another (which may not be supplied in source code form) is legitimate. >> >> An abstract or non-abstract enumerated type with a declared supertype (which must be an abstract enumerated type), such as: >> >> abstract enum Foo1 extends Bar { >> ... >> } >> >> enum Foo2 extends Bar { >> ... >> } >> >> >> shall be desugared to code resembling: >> >> @AbstractEnum >> abstract class Foo1> extends Bar { >> ... >> } >> >> @... >> class Foo2 extends Bar { >> ... >> } >> >> >> When compiling such a class, the compiler shall emit a compile-time error if an enum (abstract or not) extends a supertype S unless the following is true: >> >> 1) Either S is declared as an "abstract enum" (if specified in source code form) or S is declared with the @AbstractEnum annotation (if specified in binary class file form), or the erasure of S is the type java.lang.Enum. >> >> 2) Regardless of whether S and its supertypes are declared in source code form or in binary class file form, all supertypes of S shall obey these same constraints. >> >> Furthermore, if a normal class is declared like so: >> >> class Bar extends Baz { >> } >> >> it shall be a compile-time error if class Baz is declared in source code to be an abstract enum, or if its binary class file representation has the @AbstractEnum annotation. >> >> The Java compiler currently generates certain methods, such as values() and valueOf(String) for enumerated types. It shall not generate these for abstract enumerated types. That is, the following shall be a compile-time error: >> >> abstract enum Foo { >> } >> >> void bar() { >> Foo[] foo1 = Foo.values(); // Error: no such method as 'Foo.values()' >> Foo foo2 = Foo.valueOf("whatever"); // Error: no such method as 'Foo.valueOf(String)' >> } >> >> >> SIMPLE EXAMPLE: >> >> These classes might be desugared to: >> >> @AbstractEnum >> abstract class SuperEnum> extends Enum { >> int getTheAnswerToTheUltimateQuestion() { >> return 42; >> } >> } >> >> @... >> class MyEnum extends SuperEnum { >> // The majority of this non-abstract enumerated type, >> // including generated methods and annotations, is exactly >> // the same as the Java compiler would generate >> // prior to this proposal. However, note that due to >> // this proposal, it has a supertype of "SuperEnum" >> // instead of "Enum". >> } >> >> ADVANCED EXAMPLE: >> >> These classes might be desugared to: >> >> @AbstractEnum >> abstract class Base1> extends Enum { >> protected final int sharedData; >> public int getSharedData() {return sharedData;} >> protected Base1(int sharedData) { >> this.sharedData = sharedData; >> } >> } >> >> @AbstractEnum >> abstract class Base2> extends Base1 { >> protected final int otherSharedData; >> public int getOtherSharedData() {return sharedData;} >> protected Base2(int sharedData, int otherSharedData) { >> super(sharedData); >> this.otherSharedData = sharedData; >> } >> } >> >> @... >> class Instances extends Base2 { >> // The majority of this non-abstract enumerated type, >> // including generated methods and annotations, is exactly >> // the same as the Java compiler would generate >> // prior to this proposal. However, note that due to >> // this proposal, it has a supertype of "Base2" >> // instead of "Enum". >> } >> >> >> TESTING: >> >> Testing can be accomplished by declaring various abstract enumerated types, having them extend each other, and having non-abstract enumerated types extend them. Normal inheritance relations (method overriding, etc.) should exist among the resulting types. >> >> Furthermore, at least one test should ensure that an attempt to extend an abstract enum (either specified in source or binary form) with a normal class is considered illegal, as is an attempt to have a non-abstract enum or an abstract enum extend a class which is not an abstract enum. >> >> Furthermore, a test should ensure that an attempt to use an expression whose compile-time type is that of an abstract enum in a 'switch' statement is considered illegal. >> >> Furthermore, a test should ensure that an attempt to reference the "values()" or "valueOf()" methods of an abstract enum is considered illegal. >> >> >> LIBRARY SUPPORT: >> >> No changes to supporting libraries are needed, except for the addition of the "@AbstractEnum" annotation type as mentioned above. >> >> REFLECTIVE APIS: >> >> The "Class.isEnum()" method shall return false when invoked on an abstract enum. (This is necessary to avoid unexpected side effects in methods which currently depend on identifying concrete enumerated types with this method. Technically, despite the syntax used to declare them, abstract enums aren't really enums -- they are just supertypes of them, and so should be treated basically exactly the same as class Enum is for the purposes of reflection, etc. This should be documented clearly in the javadoc for Class.isEnum()) >> >> It may be desirable to create a "Class.isAbstractEnum()" convenience method to detect the @AbstractEnum annotation. For consistency, such a method should probably return 'true' when invoked on the Enum supertype as well. >> >> >> OTHER CHANGES: >> >> Javadoc might possibly need to be updated to handle the possibility of generating documentation for an abstract enumerated type. >> >> In order to allow abstract supertypes to be added or removed from an abstract enum without making it impossible to read back existing serialized data, it will be necessary to modify the Java serialization specification as follows: >> >> In section "1.12 Serialization of Enum Constants", the following text shall be added at the end of the section: >> >> " >> Furthermore, in order to preserve the ability to deserialize enumerated constants which may have been serialized with an enumerated type having a different type hierarchy from what was written (due to the addition or deletion of "abstract enum" supertypes), the type of every enumerated constant shall be serialized and deserialized as if the immediate supertype of the declared non-abstract enum type which defines the constant was java.lang.Enum. In particular, a type such as: >> >> abstract enum Foo { >> } >> >> abstract enum Bar extends Foo { >> } >> >> enum Baz extends Bar { >> QUX; >> } >> >> shall exist in serialized form exactly as if it were declared as: >> >> enum Baz { // implicit supertype of Enum> >> QUX; >> } >> " >> >> MIGRATION: >> >> New abstract enumerated types can be created, as desired, to do code sharing between existing non-abstract enumerated types in an existing code base. >> >> The above "OTHER CHANGES" section ensures that adding or removing abstract supertypes of an enum will not affect the ability to serialize or deserialize instances of it. >> >> COMPATIBILITY >> >> BREAKING CHANGES: >> >> Since this syntax was previously considered a syntax error, no previously valid programs will be invalidated by it. >> >> EXISTING PROGRAMS: >> >> This feature should not change the semantics of existing class files. The features being added should desugar to normal method calls, class declarations, etc. Hence, I do not anticipate problems interacting with existing class files. >> >> REFERENCES >> >> EXISTING BUGS: >> >> Add language support for abstract Enum's >> http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6507006 >> >> allow "abstract enum AbstractEnum" and "enum MyEnum extends AbstractEnum" >> http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6222244 >> >> Support for public abstract enum declaration >> http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6570766 >> >> (The original enum proposal, the comments for which allude to the possibility of abstract enums) >> Bug ID: 4401321 Add type-safe enums to Java >> http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4401321 >> >> >> URL FOR PROTOTYPE (optional): >> >> Although not implemented in response to this specific proposal, Fred Simon has implemented a substantially similar feature in Kijaro: >> >> http://tech.puredanger.com/2008/01/10/property-enum/ From vapor1 at teleport.com Thu May 7 01:27:15 2009 From: vapor1 at teleport.com (Derek Foster) Date: Thu, 7 May 2009 04:27:15 -0400 (EDT) Subject: PROPOSAL: Abstract enums (version 3) Message-ID: <9806262.1241684835658.JavaMail.root@elwamui-norfolk.atl.sa.earthlink.net> Per feedback on the Project Coin mailing list, this proposal has been revised once again to replace discussion of the @AbstractEnum annotation with a class file attribute, ACC_ABSTRACTENUM, and provide more explanation of its intended use and meaning. Additionally, this version addresses another suggested workaround for the problem being addressed (Thanks, Joe!), corrects a flaw in the suggested desugarings of prior versions (thanks, Bruce!) and adds to the ALTERNATIVES section some discussion of a minor possible extension to the proposal: the possibility of access to the type of the concrete subtype of the enum using a generic type parameter (thanks again, Bruce!) Abstract Enums (Version 3) AUTHOR: Derek Foster OVERVIEW The Java Enumerated type feature is unlike similar features in any other language which preceded it. In prior languages, an enumerated type was simply a collection of integer constants. In contrast, Java's enumerated type is a rich datatype that has more in common with classes than it has with a simple constants. Enumerated types can contain complex data, as well as methods to operate on that data. Individual enumerators may be subclasses of the enumeration class that contains them, and may override methods to provide enumerator-specific behavior. Unfortunately, there is one striking difference between Java's enumerations and classes that can become a significant inconvenience: While classes allow use of a superclass to hold data and methods which are shared between a variety of subclasses, Java enumerations have no such feature. In particular, every Java enumerated type must explicitly specify all of its data and methods that are not inherited from the base class Enum. If there are a number of enumerations that share related behavior, each enumeration must specify it redundantly. The only way to share behavior between these enumerations is to manually implement it via delegation. Note that the term "abstract enum" is somewhat imprecise, and has historically been interpreted (in particular, by the team responsible for defining how to add enumerated types to Java) to refer to a different concept than the one that is specified by this proposal. Specifically, the "extendable enums" approach, in which an abstract enumerated type which declares enumeration constants could be extended by another enumerated type which declares additional constants. Since there seems to have been some confusion on this point, I wish to specifically point out that the interpretation of the phrase "abstract enum" as it is used in this proposal is quite different from that assumed by the "extensible enums" feature that has been considered (and rejected) in the past. The extensible enums proposal was an attempt to define behavior of concrete subtypes of concrete enumerated types. This proposal, on the other hand, attempts to define the behavior of abstract uninstantiable supertypes of enumerated types. The focus of this proposal is not on adding "interface"-related features to enums -- it is on implementation sharing. As such, it is specifically designed to avoid the implementation and specification problems (difficulty with serialization, switch statements, etc.) that are problems for "extensible enums" approaches and which have therefore given the phrase "abstract enums" a bad name in the past. For instance, imagine a system in which enumerations are used to access columns of tables in a relational database. There might be one enumeration for each table, and the enumerators of each type might represent the columns in that table. Presumably, each enumerator would contain the name of the table, as well as the name of a specific column, and perhaps other metadata, such as access privileges. It would seem natural to model such a system like this: enum Access { PUBLIC, PRIVATE }; /** * This holds the shared definition of what it means * to be a database table column identifier */ abstract enum TableColumnDef { // Note: No enum constants are declared here! // This is just a supertype! private String tableName; private String columnName; private Access access; protected TableColumnDef(String tablename, String columnName, Access access) { this.tableName = tableName; this.columnName = columnName; this.access = access; } public String getTableName() { return tableName; } public String getColumnName() { return columnName; } public Access getAccess() { return access; } @Override final String toString() { return tableName + "." + columnName; } } /** A specific table */ enum PersonTable extends TableColumnDef { NAME_COLUMN("Name", Access.PUBLIC), AGE_COLUMN("Age", Access.PRIVATE), WEIGHT_COLUMN("Weight", ACCESS.PUBLIC); private PersonTable(String columnName, Access access) { super("PersonTable", columnName, access); } } /** Another specific table */ enum PetTable extends TableColumnDef { PETNAME_COLUMN("PetName", Access.PUBLIC), SPECIES_COLUMN("Species", Access.PUBLIC); private PersonTable(String columnName, Access access) { super("PetTable", columnName, access); } } However, this cannot be done in Java, because inheritance from user-specified abstract types is not supported for enumerated types. (The only abstract type that is considered legal to inherit from is Enum). The closest equivalent in Java as it currently exists is to model the desired system is something like this, using delegation instead of inheritance: class TableEnumGuts { private String tableName; private String columnName; private Access access; protected DatabaseEnum(String tablename, String columnName, Access access) { this.tableName = tableName; this.columnName = columnName; this.access = access; } public String getTableName() { return tableName; } public String getColumnName() { return columnName; } public Access getAccess() { return access; } @Override final String toString() { return tableName + "." + columnName; } } enum PersonTable { NAME_COLUMN("Name"), AGE_COLUMN("Age"), WEIGHT_COLUMN("Weight"); private TableEnumGuts guts; private PersonTable(String columnName, Access access) { guts = new TableEnumGuts("PersonTable", columnName, access); } public String getTableName() { return guts.getTableName(); } public String getColumnName() { return guts.getColumnName(); } public Access getAccess() { return guts.getAccess(); } @Override final String toString() { return guts.toString(); } } enum PetTable extends TableEnum { PETNAME_COLUMN("PetName"), SPECIES_COLUMN("Species"); private TableEnumGuts guts; private PersonTable(String columnName) { guts = new TableEnumGuts("PersonTable", columnName, access); } public String getTableName() { return guts.getTableName(); } public String getColumnName() { return guts.getColumnName(); } public Access getAccess() { return guts.getAccess(); } @Override final String toString() { return guts.toString(); } } Note how much more code (and worst of all, boilerplate duplicate code) is required in the second example, since each enumerated type must provide forwarding methods for each method in the 'TableEnumGuts' class. In one example that the author of this proposal was forced to deal with, there were 30 such enumerated types which conceptually extended the same base class, each of which had to implement that conceptual inheritance by delegating four or so methods to an internal "guts" object. This meant that any time time the signature of any of those four methods had to be changed, the change had to take place in 30 different forwarding methods as well. In another case (working for a different company) there were 10 such methods, duplicated over four conceptual subclasses, with similar problems. Another possible attempt to deal with this issue (suggested on the Project Coin mailing list by Joe Darcy), would be to rewrite the above example like so: class TableEnumGuts { private final String tableName; private final String columnName; private final Access access; protected TableEnumGuts(String tablename, String columnName, Access access) { this.tableName = tableName; this.columnName = columnName; this.access = access; } public String getTableName() { return tableName; } public String getColumnName() { return columnName; } public Access getAccess() { return access; } @Override final String toString() { return tableName + "." + columnName; } } enum PersonTable { NAME_COLUMN("Name"), AGE_COLUMN("Age"), WEIGHT_COLUMN("Weight"); private TableEnumGuts guts; public TableEnumGuts getGuts() { return guts; } private PersonTable(String columnName, Access access) { guts = new TableEnumGuts("PersonTable", columnName, access); } @Override final String toString() { return guts.toString(); } } enum PetTable extends TableEnum { PETNAME_COLUMN("PetName"), SPECIES_COLUMN("Species"); private TableEnumGuts guts; public TableEnumGuts getGuts() { return guts; } private PersonTable(String columnName) { guts = new TableEnumGuts("PersonTable", columnName, access); } @Override final String toString() { return guts.toString(); } } Note that this rewrite has improved one aspect of the problem (it has substantially reduced the amount of duplicate boilerplate code due to forwarding methods) at the cost of introducing another concern: it has changed the interface to the class in order to deal with this implementation problem. In particular, calling a method on an instance of one of the above enums now requires the syntax "foo.getGuts().getColumnName()" instead of the prior "foo.getColumnName()". Note that besides being more verbose and thus contributing to cluttered code in the clients, this refactoring will also unfortunately force the source and binary code in the clients to change. Thus, if the enum in question is part of the public API to a library (a JAR file), for instance, upgrading to a new version of the library which attempts to introduce a "extract supertype" refactoring from two related enums will be a breaking change to any source or class files that depended on the old interface to the library. This proposal attempts to solve the above problem by defining the semantics of abstract enumerated types, and what it means for an enumerated type to have an abstract supertype, so as to allow code similar to the first example to work as expected in a Java compiler, without introducing the drawbacks that exist due to the second and third approaches. FEATURE SUMMARY: Defines the meaning of inheritance from abstract supertypes for enumerated types. Note that this proposal specifically does not allow abstract enumerated types to have enumerators, since the semantics of these create difficult problems with inheritance (and open, in the words of one evaluator to a Sun bug submission, "a can of worms", related to the defunct "extendable enums" idea that has been proposed and rejected in the past.). MAJOR ADVANTAGE: Eliminates a missing feature between java enumerations and java classes, and restores a feature of the "typesafe enumeration" pattern that is not supported by Java enumerations as they are currently implemented. MAJOR BENEFIT: Elimination of duplicate code when related enumerated types need to be declared. Allows subclassing within enumeration types. Eases maintenance of families of enumerated types. Makes implementation sharing among related enumerated types work in a familiar manner analogous to how it works with classes. MAJOR DISADVANTAGE: There will be some work in the compiler necessary to implement this feature. Some people would like to be able to have concrete enums extend each other ("extensible enums"). This proposal does not attempt to provide such a feature, since it has been determined to be very difficult to specify and implement in the past. ALTERNATIVES: Note the delegation workarounds being used above. These allows subtypes to share code, but results in potentially large numbers of forwarding methods and/or difficulties with code maintenance and refactoring. As a minor variation to this proposal, Bruce Chapman has suggested (on the Project Coin mailing list) that it might be desirable for an abstract enum to be able to reference the subtype that is being instantiated by using a generic type parameter, as Enum can. It might be possible, for instance, to slightly abuse the generic typing mechanism to declare a type such as: abstract enum Foo extends Bar { E getSuccessor() { return getDeclaringClass().getEnumConstants()[ordinal()+1];} } where the generic type parameter E would be considered to have the type "E extends Foo". This proposal does not currently attempt to provide such a feature, primarily since it is not expected to be frequently needed and because in those few cases where it is needed, existing mechanisms (method overloading with covariant return types, for instance) can provide the necessary interface in many cases without a great deal of extra code (usually, a single one-line forwarding/casting method per non-abstract enum class that delegates to a superclass method). However, such a feature could be considered a natural extension of this proposal and could be implemented if it turns out to be needed often enough to outweigh the somewhat nonintuitive syntax. EXAMPLES SIMPLE EXAMPLE: abstract enum SuperEnum { // Note: no enum constant declarations allowed here! int getTheAnswerToTheUltimateQuestion() { return 42; } } enum MyEnum extends SuperEnum { MY_ENUMERATOR; } class DeepThought { Object returnTheAnswer() { MyEnum[] values1 = MyEnum.values(); // OK MyEnum values2 = MyEnum.valueOf("MY_ENUMERATOR"); // OK SuperEnum values1 = SuperEnum.values(); // Error: No such method SuperEnum values2 = SuperEnum.valueOf("whatever"); // Error: No such method return MY_ENUMERATOR.getTheAnswerToTheUltimateQuestion(); } } ADVANCED EXAMPLE: abstract enum Base1 { protected final int sharedData; public int getSharedData() {return sharedData;} protected Base1(int sharedData) { this.sharedData = sharedData; } } abstract enum Base2 extends Base1 { protected final int otherSharedData; public int getOtherSharedData() {return sharedData;} protected Base2(int sharedData, int otherSharedData) { super(sharedData); this.otherSharedData = sharedData; } } enum Instances extends Base2 { INSTANCE1(10, 100), INSTANCE2(20, 200), INSTANCE3(30, 300) { public int getSharedData() { return 40; } } private Instances(int sharedData, int otherSharedData) { super(sharedData, otherSharedData); } } class AClient { void someFunc() { assert INSTANCE1.getSharedData()==10; assert INSTANCE2.getSharedData()==20; assert INSTANCE3.getSharedData()==40; Instances[] values = instances.values(); // OK Base2[] values = Base2.values(); // Error: No such method. } } DETAILS SPECIFICATION: A concept of an "abstract enum" shall be added to the Java language, denoted by prepending the word "abstract" to an enumerated type declaration, with restrictions as described below. Rule 1: An enumerated type shall either declare no supertype, or shall declare a supertype which is an abstract enumerated type. Rule 2: It shall be a compile-time error for an ordinary class to extend an enumerated type, either abstract or not. Rule 3: Both abstract and non-abstract enumerated types shall implicitly have a supertype (not necessarily a direct supertype) of Enum>. Thus, within the body of an abstract enumerated type, access to methods of this supertype is allowed. Rule 4: Abstract enumerated types shall not declare enumerators. The body of an abstract enumerated type shall be syntactically and semantically the same as that of an ordinary abstract class which extends its supertype (see rule 3), except with the restriction that all constructors shall be declared with 'protected' or 'package' access (since the class is abstract and cannot declare instances, constructors can only be invoked by subclasses so there is no need to make them more public than necessary). Rule 5: In an abstract enum, the compiler shall not generate the methods that it would generate for a non-abstract enumerated type (specifically, the "values()" or "valueOf(String) methods), for an abstract enumerated type. (Since it is illegal for there to be enumerators declared in an abstract enum, these methods would serve no purpose.) Rule 6: It shall be illegal for the expression used in a 'switch' statement to be an abstract enum type. Specifically, section 8.9 of the JLS3, which currently reads: " An enum declaration has the form: EnumDeclaration: ClassModifiers_opt enum Identifier Interfaces_opt EnumBody " shall be modified to read: " An enum declaration has the form: EnumDeclaration: ClassModifiersopt enum Identifier Super_opt Interfaces_opt EnumBody " Also, section 8.1.1.1 of the JLS3, which currently reads: "Enum types (?8.9) must not be declared abstract; doing so will result in a compile-time error. It is a compile-time error for an enum type E to have an abstract method m as a member unless E has one or more enum constants, and all of E's enum constants have class bodies that provide concrete implementations of m. It is a compile-time error for the class body of an enum constant to declare an abstract method." shall be modified to read: "Enum types (?8.9) may be declared abstract. If an enum type is declared abstract, it may declare abstract methods. However, it is a compile-time error for an abstract enum type to declare enum constants. Furthermore, it is a compile-time error for any constructor declared by an abstract enum type to have 'public' or 'private' access. It is a compile-time error for a non-abstract enum type E to have an abstract method m as a member (either explicitly declared or implicitly inherited from an abstract enum supertype) unless E has one or more enum constants, and all of E's enum constants have class bodies that provide concrete implementations of m. It is a compile-time error for the class body of an enum constant to declare an abstract method. " also, in the same section, the text which currently reads: "If the enum type has no constructor declarations, a parameterless default constructor is provided (which matches the implicit empty argument list). This default constructor is private." shall be modified to read: "If the enum type has no constructor declarations, a parameterless default constructor is provided (which matches the implicit empty argument list). This default constructor is protected if the enum is abstract, and private if it is non-abstract." and in the same section, the text which currently reads: "The direct superclass of an enum type named E is Enum." shall be modified to read: "A non-abstract enum type named E has a superclass (either direct or indirect via one or more abstract enums) of Enum." and in the same section, the text which currently reads: " It is a compile-time error for an enum to declare a finalizer. An instance of an enum may never be finalized. In addition, if E is the name of an enum type, then that type has the following implicitly declared static methods: " shall be modified to read: " It is a compile-time error for an enum (whether abstract or not) to declare a finalizer. An instance of an enum may never be finalized. In addition, if E is the name of a non-abstract enum type, then that type has the following implicitly declared static methods: " and in the same section, the text which currently reads: " It is a compile-time error to reference a static field of an enum type that is not a compile-time constant (?15.28) from constructors, instance initializer blocks, or instance variable initializer expressions of that type. It is a compile-time error for the constructors, instance initializer blocks, or instance variable initializer expressions of an enum constant e to refer to itself or to an enum constant of the same type that is declared to the right of e. " shall be modified to read: " It is a compile-time error for a non-abstract enum type to reference one of its static fields which is not a compile-time constant (?15.28) from constructors, instance initializer blocks, or instance variable initializer expressions of that type. It is a compile-time error for the constructors, instance initializer blocks, or instance variable initializer expressions of an enum constant e to refer to itself or to an enum constant of the same type that is declared to the right of e. Note however that any code within a non-abstract enum type may legally reference static fields of its abstract enum supertypes, if such supertypes and fields exist. " and in section 14.11 ('The switch statement'), the text which reads: "The type of the Expression must be char, byte, short, int, Character, Byte, Short, Integer, or an enum type (?8.9), or a compile-time error occurs." shall be modified to read: "The type of the Expression must be char, byte, short, int, Character, Byte, Short, Integer, or a non-abstract enum type (?8.9), or a compile-time error occurs." and in the JVM specification (version 2) in the section "Class file format", in table 4.1 ("Class access and property modifiers") the following entry shall be added after the ACC_ENUM entry: ACC_ABSTRACTENUM 0x8000 Declared as an abstract enum type and in the same section, the text "The ACC_ENUM bit indicates that this class or its superclass is declared as an enumerated type" shall be replaced with: " The ACC_ENUM bit indicates that this class or its superclass is declared as a non-abstract enumerated type. (Note that a class having this attribute may be DECLARED as non-abstract in source code, but may still actually be abstract (and hence have the ACC_ABSTRACT bit) due to having abstract methods and anonymous subtypes which provide implementations of them). If this bit is set, the ACC_ABSTRACTENUM bit must not be set. The ACC_ABSTRACTENUM bit indicates that this class is declared as an abstract enumerated type. If this bit is set, the ACC_ENUM bit must not be set. " In the Java serialization specification, in section "1.12 Serialization of Enum Constants", the following text shall be added at the end of the section: " Furthermore, in order to preserve the ability to deserialize enumerated constants which may have been serialized with an enumerated type having a different type hierarchy from what was written (due to the addition or deletion of "abstract enum" supertypes), the type of every enumerated constant shall be serialized and deserialized as if the immediate supertype of the declared non-abstract enum type which defines the constant was java.lang.Enum. In particular, a type such as: abstract enum Foo { } abstract enum Bar extends Foo { } enum Baz extends Bar { QUX; } shall exist in serialized form exactly as if it were declared as: enum Baz { // implicit supertype of Enum> QUX; } " COMPILATION: An abstract enumerated type with no declared supertype, such as: abstract enum Foo { ,,, } shall be desugared to code resembling: // with the ACC_ABSTRACTENUM bit set in the access_flags field of the corresponding class file... abstract class Foo> extends Enum { ... } An abstract or non-abstract enumerated type with a declared supertype (which must be an abstract enumerated type), such as: abstract enum Foo1 extends Bar { ... } enum Foo2 extends Bar { ... } shall be desugared to code resembling: // with the ACC_ABSTRACTENUM bit set in the access_flags field of the corresponding class file. abstract class Foo1> extends Bar { ... } // with the ACC_ENUM bit set in the access_flags field of the corresponding class file (as it would be prior to this proposal)... class Foo2 extends Bar { ... } When compiling such a class, the compiler shall emit a compile-time error if a declared enum (abstract or not) extends a supertype S unless the following is true: 1) Either S is declared as an "abstract enum" (if specified in source code form) or S is declared with the ACC_ABSTRACTENUM bit set (if specified in binary class file form), or the erasure of S is the type java.lang.Enum. 2) Regardless of whether S and its supertypes are declared in source code form or in binary class file form, all supertypes of S shall obey these same constraints. Furthermore, if a normal class is declared like so: class Bar extends Baz { } it shall be a compile-time error if class Baz is declared in source code to be an abstract enum, or if its binary class file representation has the ACC_ABSTRACTENUM bit set. The Java compiler currently generates certain methods, such as values() and valueOf(String) for enumerated types. It shall not generate these for abstract enumerated types. That is, the following shall be a compile-time error: abstract enum Foo { } void bar() { Foo[] foo1 = Foo.values(); // Error: no such method as 'Foo.values()' Foo foo2 = Foo.valueOf("whatever"); // Error: no such method as 'Foo.valueOf(String)' } SIMPLE EXAMPLE: These classes might be desugared to: // Note: ACC_ABSTRACTENUM set in class file abstract class SuperEnum> extends Enum { int getTheAnswerToTheUltimateQuestion() { return 42; } } // Note: ACC_ENUM set in class file as it was prior to this proposal class MyEnum extends SuperEnum { // The majority of this non-abstract enumerated type, // including generated methods and annotations, is exactly // the same as the Java compiler would generate // prior to this proposal. However, note that due to // this proposal, it has a supertype of "SuperEnum" // instead of "Enum". } ADVANCED EXAMPLE: These classes might be desugared to: // Note: ACC_ABSTRACTENUM set in class file abstract class Base1> extends Enum { protected final int sharedData; public int getSharedData() {return sharedData;} protected Base1(int sharedData) { this.sharedData = sharedData; } } // Note: ACC_ABSTRACTENUM set in class file abstract class Base2> extends Base1 { protected final int otherSharedData; public int getOtherSharedData() {return sharedData;} protected Base2(int sharedData, int otherSharedData) { super(sharedData); this.otherSharedData = sharedData; } } // Note: ACC_ENUM set in class file as it was prior to this proposal class Instances extends Base2 { // The majority of this non-abstract enumerated type, // including generated methods and annotations, is exactly // the same as the Java compiler would generate // prior to this proposal. However, note that due to // this proposal, it has a supertype of "Base2" // instead of "Enum". } TESTING: Testing can be accomplished by declaring various abstract enumerated types, having them extend each other, and having non-abstract enumerated types extend them. Normal inheritance relations (method overriding, etc.) should exist among the resulting types. Furthermore, at least one test should ensure that an attempt to extend an abstract enum (either specified in source or binary form) with a normal class is considered illegal, as is an attempt to have a non-abstract enum or an abstract enum extend a class which is not an abstract enum. Furthermore, a test should ensure that an attempt to use an expression whose compile-time type is that of an abstract enum in a 'switch' statement is considered illegal. Furthermore, a test should ensure that an attempt to reference the "values()" or "valueOf()" methods of an abstract enum is considered illegal. LIBRARY SUPPORT: No changes to supporting libraries are needed. REFLECTIVE APIS: The "Class.isEnum()" method shall return false when invoked on an abstract enum. (This is necessary to avoid unexpected side effects in methods which currently depend on identifying concrete enumerated types with this method. Technically, despite the syntax used to declare them, abstract enums aren't really enums -- they are just supertypes of them, and so should be treated basically exactly the same as class Enum is for the purposes of reflection, etc. This should be documented clearly in the javadoc for Class.isEnum()) It may be desirable to create a "Class.isAbstractEnum()" convenience method to detect the ACC_ABSTRACTENUM class file annotation. For consistency, such a method should probably return 'true' when invoked on the Enum supertype as well. OTHER CHANGES: Javadoc might possibly need to be updated to handle the possibility of generating documentation for an abstract enumerated type. Changes to the class file format (addition of the ACC_ABSTRACTENUM bit) are noted in the specification section above. Changes to the Java serialization format (serialization of enums with abstract supertypes as if they did not have such supertypes) are noted in the specification section above. MIGRATION: New abstract enumerated types can be created, as desired, to do code sharing between existing non-abstract enumerated types in an existing code base. The above "OTHER CHANGES" section ensures that adding or removing abstract supertypes of an enum will not affect the ability to serialize or deserialize instances of it. COMPATIBILITY BREAKING CHANGES: Since this syntax was previously considered a syntax error, no previously valid programs will be invalidated by it. This format will require an increase in the class file version number, which is expected for Java 7 anyway. EXISTING PROGRAMS: This feature should not change the semantics of existing class files (other than to require that they be regenerated with an appropriate version number corresponding to the JDK 7 class file format). The features being added should desugar to normal method calls, class declarations, etc. REFERENCES EXISTING BUGS: Add language support for abstract Enum's http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6507006 allow "abstract enum AbstractEnum" and "enum MyEnum extends AbstractEnum" http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6222244 Support for public abstract enum declaration http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6570766 (The original enum proposal, the comments for which allude to the possibility of abstract enums) Bug ID: 4401321 Add type-safe enums to Java http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4401321 URL FOR PROTOTYPE (optional): Although not implemented in response to this specific proposal, Fred Simon has implemented a substantially similar feature in Kijaro: http://tech.puredanger.com/2008/01/10/property-enum/ From brucechapman at paradise.net.nz Thu May 7 03:28:47 2009 From: brucechapman at paradise.net.nz (Bruce Chapman) Date: Thu, 07 May 2009 22:28:47 +1200 Subject: PROPOSAL: Abstract enums (version 2) In-Reply-To: <12684881.1241669787649.JavaMail.root@elwamui-norfolk.atl.sa.earthlink.net> References: <12684881.1241669787649.JavaMail.root@elwamui-norfolk.atl.sa.earthlink.net> Message-ID: <4A02B7DF.30207@paradise.net.nz> Derek Foster wrote: > -----Original Message----- > > >> Could the abstract enum have type parameters, such that declared methods >> were type polymorphic? (You enum for database table columns comes to >> mind here) and if so, could the methods be abstract thereby forcing the >> concrete enum to implement it? The basic argument here is that if you >> are fixing enums to be consistent with the rest of the language in terms >> of inheritance, then maybe you should be in terms of type polymorphism >> as well. If you did, it would put a different slant on the >> implicit/explicit type parameter issue discussed above. >> > > An interesting question. I mulled over this for a while, but was unable to come up with a solution I liked very much that was consistent with the rest of the language. For instance, if the type parameter is explicit, that leaves people typing things like: > > abstract enum Foo> { // Implicitly extends Enum > E getSuccessor() {return getDeclaringClass().getEnumConstants()[ordinal()+1];} > } > > abstract enum Bar> extends Foo { > } > > enum Baz extends Bar> { > SPORK, CHATOYANCY, WOMBAT, CHEESE; > } > > which is quite annoyingly verbose but is what you would have to do if the user really had to specify the types correctly. This would require the compiler to do a bunch of extra checking as well, to make sure that all of the types were in fact correctly specified according to the necessary pattern. This seems like it would complicate basic use of the feature considerably (making the user type lots of boilerplate code), in order to handle a rare use case. > > Another alternative would be to allow the user to just specify the name of the type parameter, and have its type be determined by the compiler (or omit even the name if it wasn't going to be used), such as: > > abstract enum Foo { // Implicitly extends Enum> > E getSuccessor() {return getDeclaringClass().getEnumConstants()[ordinal()+1];} > } > > abstract enum Bar extends Foo { // No need for Bar since not used in the body > } > > enum Baz extends Bar { > SPORK, CHATOYANCY, WOMBAT, CHEESE; > } > > This is nicely compact and requires the user to only specify the one thing they can change (the name of the type parameter, not its type). However, it is inconsistent with how the language normally works (Foo normally indicates that E extends Object, not that E extends Foo), which could be confusing. > > I think on the whole, that referencing a subtype like this is a rare enough occurrence (I had to struggle to come up with plausible examples like the getSuccessor() method above) that we probably can do without language support for it. After all, in general, ordinary types can't access their subtypes like this at all, so the fact that it is even possible in the case of Enums is rather unusual. > > Derek, I was really thinking about an additional type parameter not the implicit Enum one. Taking your database definition use case a step further, (probably an overly complex example but ...) then with type parameters you could do this enum Access { PUBLIC, PRIVATE }; enum SqlType { // VARCHAR has type SqlType VARCHAR { public String getValue(ResultSet r, String name) { return r.getString(name); } INTEGER { public Integer getValue(ResultSet r, String name) { return r.getInt(name); } } FLOAT { public Float getValue(ResultSet r, String name) { return r.getFloat(name); } } public abstract T getValue(ResultSet r, String name); } /** * This holds the shared definition of what it means * to be a database table column identifier * @param The java type of the column. */ abstract enum TableColumnDef { // Note: No enum constants are declared here! // This is just a supertype! private SqlType sqlType; private String tableName; private String columnName; private Access access; protected TableColumnDef(String tablename, String columnName, SqlType sqlType, Access access) { this.tableName = tableName; this.columnName = columnName; this.access = access; this.sqlType = sqlType; } public String getTableName() { return tableName; } public String getColumnName() { return columnName; } public Access getAccess() { return access; } @Override final String toString() { return tableName + "." + columnName; } public T getFrom(ResultSet r) { // check ResultSet is for this table - ellided return sqlType.getValue(r,columnName); } } /** A specific table */ enum PersonTable extends TableColumnDef { NAME_COLUMN has Type PersonTable NAME_COLUMN("Name", SqlType.VARCHAR, Access.PUBLIC), AGE_COLUMN("Age", SqlType.INT, Access.PRIVATE), WEIGHT_COLUMN("Weight", SqlType.FLOAT, ACCESS.PUBLIC); private PersonTable(String columnName, SqlType sqlType, Access access) { super("PersonTable", columnName, sqlType, access); } } /** Another specific table */ enum PetTable extends TableColumnDef { PETNAME_COLUMN("PetName", SqlType.VARCHAR, Access.PUBLIC), SPECIES_COLUMN("Species", SqlType.VARCHAR, Access.PUBLIC); private PersonTable(String columnName, SqlType sqlType, Access access) { super("PetTable", columnName, sqlType, access); } } And then you write ResultSet r = ... float weight = PersonTable.WEIGHT_COLUMN.getFrom(r); Maybe its the strange stuff I write, but often I find that something I'd like to encode as an enum, doesn't really work, because there is some type variability represented by the various constants. Being able to express this would be great (but probably isn't coin sized :( ) Bruce From Joe.Darcy at Sun.COM Thu May 7 18:42:37 2009 From: Joe.Darcy at Sun.COM (Joe Darcy) Date: Thu, 07 May 2009 18:42:37 -0700 Subject: PROTOTYPE: In-Reply-To: <49EC5051.9000705@paradise.net.nz> References: <11482659.1238468832504.JavaMail.root@mswamui-andean.atl.sa.earthlink.net> <49EC5051.9000705@paradise.net.nz> Message-ID: <4A038E0D.2030106@sun.com> On 04/20/09 03:37 AM, Bruce Chapman wrote: > A prototype compiler for the follow proposals > > Underscores in numbers > Narrow Hexadecimal and Binary Integer Literals > Byte and Short Integer Literal Suffixes > > is now available at > https://kijaro.dev.java.net/servlets/ProjectDocumentList?folderID=11247&expandFolder=11247&folderID=8804 > > I have bundled them altogether so that the interaction between > underscores and the others can be assessed and so that the two new > literal forms can be compared side by side. > > There is one fault in the test class, fix that and it should compile and > run. > > -- Joe, should we update the proposals with this information or is this > email sufficient? > > > Bruce > > > If new revisions of the proposals are submitted, they should include a link. Otherwise your email suffices. -Joe From Joe.Darcy at Sun.COM Thu May 7 18:59:15 2009 From: Joe.Darcy at Sun.COM (Joe Darcy) Date: Thu, 07 May 2009 18:59:15 -0700 Subject: PROPOSAL: Underscores in Numbers (Version 2) In-Reply-To: <24587044.1241150495473.JavaMail.root@elwamui-hound.atl.sa.earthlink.net> References: <24587044.1241150495473.JavaMail.root@elwamui-hound.atl.sa.earthlink.net> Message-ID: <4A0391F3.4080304@sun.com> Hello. A few comments. This is well-localized change and judicious use of the feature would improve the readability of some numerical constants. However, I generally agree with Bruce's earlier comments that phone numbers, credit card numbers, social security numbers, etc. are not a good motivating example since they are really strings whose digits are (mostly) constrained to be numeric as opposed to actual integral or real-valued data. (Using floating-point types to store dollars and cents is also ill-advised because fractions like 0.12 generally cannot be stored exactly as binary fractions.) As a minor point, I believe the NumberFormat class and friends do allow some input/output formatting with digit separators, but that doesn't help literal values of course. For more substantive feedback, I believe the grammar changes still need some work. First, my reading of the grammar is that it is ambiguous regarding underscores, there are multiple ways for "0__1" to be parsed and the grammar as written does not ban "5_" (NonZeroDigit followed by Undersccores_opt). How about treating underscore as an extra digit in some cases, something like: Decimal Numeral 0 NonZeroDigit DigitsAndUnderscores_opt DigitsAndUnderscores DigitOrUnderscore_opt Digit DigitOrUnderscore 0 ... 9 _ This grammar: * forces a nonzero leading digit * forces a non-underscore final character * allows any number of intermixed digits and underscores in between -Joe On 04/30/09 09:01 PM, Derek Foster wrote: > Per feedback on the Project Coin mailing list, the following proposal has been revised to disallow placing underscores at the beginning or end of a sequence of digits within a number. I have also revised the value used for the "alsoMaxLong" example (as it was previously illegal), as well as the other examples showing where underscores can/cannot be placed. > > AUTHOR(S): Derek Foster > > OVERVIEW > > In Java, currently, numbers of various types currently are expressed in their pure form, as a long string of digits possibly interspersed with other punctuation (periods, an exponent specifier, etc.) needed to separate distinct sections of the number. While this is easy for a compiler to process, it is often difficult for a human being to visually parse. > > The ability of a human to visually separate separate items tops out somewhere near "seven plus or minus two" items. Research done by telephone companies suggests that for many practical purposes, the longest string of numbers an average human can successfully hold in memory at a time is around three or four. Also, it is difficult for the human eye to find common positions in numbers that have no break in their visual structure. > > As a result, most numbers that humans deal with in day-to-day life have separators included in them to break the long sequence of digits into manageable chunks that are easy to deal with as separate entities. This includes items such as (apologies to non-USA readers...): > > Phone numbers: 555-555-1212 > Credit card numbers: 1234-5678-9012-3456 > Social security numbers: 999-99-9999 > Monetary amounts: $12,345,132.12 > > and a wide variety of other types of numbers. > > However, Java provides no way to add these kinds of visual separators into a number. Java expects the number to be essentially an unbroken string of digits. > > This proposal suggests that Java follow the lead of the Ruby programming language in allowing the underscore character to be inserted into numbers in most positions, for readability purposes. > > > FEATURE SUMMARY: > > Java numeric literals will allow underscores to be placed in (nearly) arbitrary positions within the number, at the programmer's discretion, for readability purposes. These underscores shall be ignored by the compiler for the purposes of code generation. > > > MAJOR ADVANTAGE: > > Programmers won't have to visually parse long strings of digits (a task humans are quite poor at). The internal digit-oriented structure of many numbers can be made more clear. > > > MAJOR BENEFIT: > > Increased readability of code. > > > MAJOR DISADVANTAGE: > > The number parsers in the Java compiler would have to be adjusted to parse and ignore the underscores. This is a small amount of effort, but nonzero. There might also be some small performance impact. > > If someone were to use this feature inappropriately, it could result in difficult to read code. > > > ALTERNATIVES: > > Do without separators in numbers, or use some other character for them. > > > EXAMPLES > > > SIMPLE EXAMPLE: Show the simplest possible program utilizing the new feature. > > int phoneNumber = 555_555_1212; > > > ADVANCED EXAMPLE: > > long creditCardNumber = 1234_5678_9012_3456L; > long socialSecurityNumbers = 999_99_9999L; > float monetaryAmount = 12_345_132.12; > long hexBytes = 0xFF_EC_DE_5E; > long hexWords = 0xFFEC_DE5E; > long maxLong = 0x7fff_ffff_ffff_ffffL; > long alsoMaxLong = 9_223_372_036_854_775_807L; > double whyWouldYouEverDoThis = 0x1_.ffff_ffff_ffff_fp10_23; > > (Additionally, if binary literals are ever added to the Java language, the following might also be possible... > byte nybbles = 0b0010_0101; > long bytes = 0b11010010_01101001_10010100_10010010; > int weirdBitfields = 0b000_10_101; > ) > > Note that according to this proposal, underscores can only be placed between digits. They cannot be placed by themselves in positions where a string of digits would normally be expected: > > int x1 = _52; // This is an identifier, not a numeric literal. > int x2 = 5_2; // OK. (Decimal literal) > int x2 = 52_; // Illegal. (Underscores must always be between digits) > int x3 = 5_______2; // OK. (Decimal literal.) > > int x4 = 0_x52; // Illegal. Can't put underscores in the "0x" radix prefix. > int x5 = 0x_52; // Illegal. (Underscores must always be between digits) > int x6 = 0x5_2; // OK. (Hexadecimal literal) > int x6 = 0x52_; // Illegal. (Underscores must always be between digits) > int x6 = 0x_; // Illegal. (Not valid with the underscore removed) > > int x7 = 0_52; // OK. (Octal literal) > int x7 = 05_2; // OK. (Octal literal) > int x8 = 052_; // Illegal. (Underscores must always be between digits) > > > DETAILS > > SPECIFICATION: > > DECIMALS: > > Section 3.10.1 ("Integer Literals") of the Java Language Specification 3rd edition shall be modified like so: > > Underscores: > _ > _ Underscores > > DecimalNumeral: > 0 > NonZeroDigit Underscores_opt DigitsAndUnderscores_opt > > DigitsAndUnderscores: > Digit > DigitsAndUnderscores Underscores_opt Digit > > Digit: > 0 > NonZeroDigit > > NonZeroDigit: one of > 1 2 3 4 5 6 7 8 9 > > HexNumeral: > 0 x HexDigitsAndUnderscores > 0 X HexDigitsAndUnderscores > > HexDigitsAndUnderscores: > HexDigit > HexDigit Underscores_opt HexDigitsAndUnderscores > > HexDigit: one of > 0 1 2 3 4 5 6 7 8 9 a b c d e f A B C D E F > > OctalNumeral: > 0 OctalDigitsAndUnderscores > > OctalDigitsAndUnderscores: > OctalDigit > OctalDigit Underscores_opt OctalDigitsAndUnderscores > > OctalDigit: one of > 0 1 2 3 4 5 6 7 > > Section 3.10.2 ("Floating-Point Literals") would be modified as follows: > > > FloatingPointLiteral: > DecimalFloatingPointLiteral > HexadecimalFloatingPointLiteral > > DecimalFloatingPointLiteral: > DigitsAndUnderscores_opt . DigitsAndUnderscores_opt ExponentPart_opt FloatTypeSuffix_opt > . DigitsAndUnderscores ExponentPartopt FloatTypeSuffix_opt > DigitsAndUnderscores_opt ExponentPart FloatTypeSuffix_opt > DigitsAndUnderscores_opt ExponentPart_opt FloatTypeSuffix > > ExponentPart: > ExponentIndicator SignedInteger > > ExponentIndicator: one of > e E > > SignedInteger: > Sign_opt DigitsAndUnderscores > > Sign: one of > + - > > FloatTypeSuffix: one of > f F d D > > HexadecimalFloatingPointLiteral: > HexSignificand BinaryExponent FloatTypeSuffix_opt > > HexSignificand: > HexNumeral > HexNumeral . > 0x HexDigitsAndUnderscores_opt . HexDigitsAndUnderscores > 0X HexDigitsAndUnderscores_opt . HexDigitsAndUnderscores > > BinaryExponent: > BinaryExponentIndicator SignedInteger > > BinaryExponentIndicator:one of > p P > > > COMPILATION: > > Numbers containing underscores are to be parsed and evaluated by the compiler exactly as if the underscores were not present. The above grammar ensures that removing underscores will not result in an unparseable number. > > A simple strategy for achieving this is that once a number has been parsed by the compiler lexer and determined to be syntactically valid according to the above grammar, then if the number contains any underscores, then all underscores in it may be removed (by something as simple as numberAsString.replaceAll("_","")) before passing the number on to the code that would normally have parsed the number prior to this proposal. > > More performant approaches are certainly possible. > > > TESTING: How can the feature be tested? > > A variety of literals may be generated, of the cross product of each of the following radicies: > > hex, decimal, octal > > with each of the following types: > > byte, char, short, int, long, float, double > > such that for each possible numeric field in the result, that one or more underscores are inserted at the beginning, in the middle, and at the end of the digits. > > Note that the above grammar is specifically designed to disallow any underscores from appearing which are not either preceded by or followed by a digit. > > > LIBRARY SUPPORT: > > Methods such as Integer.decode(String) and Long.decode(String) should probably be updated to ignore underscores in their inputs, since these methods attempt to parse according to Java conventions. > > I suggest that methods such as Integer.parseInt(), Float.parseFloat(), etc. should probably NOT be updated to ignore underscores, since these methods deal with numbers in their pure form, and are more focused and much more widely used. To alter them to ignore underscores would introduce ambiguity in (and have a performance impact on) various parsing code that uses them. > > > REFLECTIVE APIS: > > No changes to reflective APIs are needed. > > > OTHER CHANGES: > > No other changes are needed. > > > MIGRATION: > > Underscores can be inserted into numbers within an existing code base as desired for readability. > > > COMPATIBILITY > > BREAKING CHANGES: > > Since use of underscores within numbers was previously a syntax error, this should not break any existing programs. > > > EXISTING PROGRAMS: > > This feature does not affect the format of class files. It is purely a notational convenience. Hence, interaction with existing class files would not be affected. > > > REFERENCES > > EXISTING BUGS: > > A search of the Bug Database did not find any bug ID's related to this proposal. > > URL FOR PROTOTYPE (optional): > > None. > > > > From howard.lovatt at iee.org Thu May 7 22:51:17 2009 From: howard.lovatt at iee.org (Howard Lovatt) Date: Fri, 8 May 2009 15:51:17 +1000 Subject: PROPOSAL: Abstract enums (version 2) Message-ID: <3dd3f56a0905072251l427e9c8y24098e9233af1d99@mail.gmail.com> Hi, I have had similar issues with enum as those described by Bruce, namely I want to use enum as a means of generating a fixed set of instances of a class. This is why I want any class to be the super class and would also like to have generic parameters. Further it would be nice if you could make a singleton by having a enum with *no* members. These facilities exist in Scala, though not through an enum construct, and I have found them most useful. -- Howard. From Joe.Darcy at Sun.COM Thu May 7 23:39:42 2009 From: Joe.Darcy at Sun.COM (Joseph D. Darcy) Date: Thu, 07 May 2009 23:39:42 -0700 Subject: PROPOSAL: Binary literals (Version 2) In-Reply-To: <38933.1241150350273.JavaMail.root@elwamui-hound.atl.sa.earthlink.net> References: <38933.1241150350273.JavaMail.root@elwamui-hound.atl.sa.earthlink.net> Message-ID: <4A03D3AE.8020504@sun.com> A few comments: There are certainly niche applications where binary literals would be helpful! The literals can be negated as usual. Constraints for the "tiny" versions of Java are not a strong driver for JDK 7 language changes. For example, while JavaCard 2.2.2 did not have String or Integer, the JavaCard 3.0 connected profile has both of those types, amongst other types used to provide JDK 5 language level support. -Joe Derek Foster wrote: > This is a minor revision of my original proposal. It has been revised to add more examples and discussion of the various alternative attempts to solve the problems that this proposal is intended to address. > > > Add binary literals to Java. (Version 2) > > AUTHOR(S): Derek Foster > > OVERVIEW > > In some programming domains, use of binary numbers (typically as bitmasks, bit-shifts, etc.) is very common. In particular, this type of usage may often be needed in low-level programming such as is typical in severely resource constrained devices such as J2ME, JavaCard, or JavaRing, although it can come up in a variety of larger-scale contexts as well, such as programming to match network packet protocols, compression algorithms, encryption algorithms, and so forth. > > However, Java code has traditionally forced programmers to represent numbers in only decimal, octal, or hexadecimal. (In practice, octal is rarely used, and is present mostly for backwards compatibility with C) > > When the data being dealt with is fundamentally bit-oriented, however, using hexadecimal to represent ranges of bits requires an extra degree of mental translation for the programmer, and this can often become a source of errors. For instance, if a technical specification lists specific values in binary (for example, in a compression encoding algorithm or in the specifications for a network protocol, or for communicating with a bitmapped hardware device) then a programmer coding to that specification must translate each key from its binary representation into hexadecimal. Checking to see if this translation has been done correctly is usually accomplished by back-translating the numbers. In most cases, programmers do these translations in their heads, and HOPEFULLY get them right. however, errors can easily creep in. > > Furthermore, in many cases, the binary representations of numbers makes it much more clear what is actually intended. For instance this: > > private static final int BITMASK = 0x1E; > > does not immediately make it clear that the bitmask being declared comprises a single contiguous range of four bits. > > In many cases, it would be more natural for the programmer to be able to write the numbers in binary in the source code, eliminating the need for manual translation entirely. > > > FEATURE SUMMARY: > > In addition to the existing "1" (decimal), "01" (octal) and "0x1" (hexadecimal) form of specifying numeric literals, a new form "0b1" (binary) would be added. > > Note that this is the same syntax as has been used as an extension by the GCC C/C++ compilers for many years, and also is used in the Ruby language, as well as in the Python language. > > > MAJOR ADVANTAGE: > > It is no longer necessary for programmers to translate binary numbers to and from hexadecimal in order to use them in Java programs. > > > MAJOR BENEFIT: > > Code using bitwise operations is more readable and easier to verify against technical specifications that use binary numbers to specify constants. > > > MAJOR DISADVANTAGE: > > Someone might incorrectly think that "0b1" represented the same value as hexadecimal number "0xB1". However, note that this problem has existed for octal/decimal for many years (confusion between "050" and "50") and does not seem to be a major issue. Also, it does not seem to be a major concern in the programming languages in which this construct already exists. (see below) > > > ALTERNATIVES: > > Users could continue to write the numbers as decimal, octal, or hexadecimal, and would continue to have the problems observed in this document. > > Alternately, code could be written to translate at runtime from binary strings, such as: > > int value = Integer.parseInt("00001110", 2) & (Integer.parseInt("00101110", 2) << amount); > > There are several problems with this style of coding: > > * First of all, the code is significantly more verbose than it would be if it were not written to use library calls. The basic purpose of the operation (number & (number << amount)) is obscured by the clutter associated with calling a library routine. This makes the code difficult to read at a glance. > > * There is a significant performance penalty. The call to Integer.parseInt takes significantly more execution time than simply using an integer constant would. This time can be a significant barrier in a resource-constrained device which may have a slow clock speed. Also, if this line of code is occurring in a tight loop (as is common in low-level programming), this extra time may have a dramatic effect on how long it takes to iterate through the loop, since this performance penalty has to be paid each time the line of code is executed, rather than just once, at compile time. > > * Calling a method such as Integer.parseInt at runtime will typically make it impossible for the compiler to inline the value of this constant, since its value has been taken from a runtime method call. Inlining is important, because code that does bitwise parsing is often very low-level code in tight loops that must execute quickly. (This is particularly the case for mobile applications and other applications that run on severely resource-constrained environments, where a JIT compiler like HotSpot is not an option.) > > * Values which are returned from evaluating methods at runtime cannot be used as selectors in 'switch' statements. A Java compiler won't allow code like this: > > switch (foo) { > case Binary.parseInt("000"): doThis(); break; > case Binary.parseInt("001"): doThat(); break; > ... > } > > * Any errors in the string to be parsed (for instance, an extra space, confusion of alphabetic 'O' with numeric '0', etc.) will result in runtime exceptions, rather than compile-time errors as would have occurred in normal parsing. If such a value is declared 'static', this will result in some very ugly exceptions at runtime. Also, the application will then need to be written to handle these errors at runtime, when in principle they could all have been detected at compile time. > > * Classes java.lang.Integer and java.lang.String simply do not exist for a number of low-level Java platforms, such as JavaCard and JavaRing, since these platforms are used for low-level number crunching and do not normally have need of such high-level constructs. [Note: It might be possible for a compiler to synthesize these classes (basically, to pretend they existed at compile time but were optimized away at runtime due to method inlining). However, this would require a substantial effort on behalf of the compiler team and essentially the introduction of a new programming paradigm (the "exists only at compile time" class). The issues of code verbosity as well as how to handle possible exceptions that might be thown by these methods at would remain.] > > * Similarly, throwing of exceptions is often not supported in resource-constrained environments. > > * It is possible to address the code verbosity issue in the above code (by, for instance, creating a library method with a shorter name and taking only one argument), or the performance issue (by creating static named constants with the necessary values), but it is not possible to simultaneously address both issues in Java as it is currently defined. > > > EXAMPLES: > > // An 8-bit 'byte' literal. > byte aByte = (byte)0b00100001; > > // A 16-bit 'short' literal. > short aShort = (short)0b1010000101000101; > > // Some 32-bit 'int' literals. > int anInt1 = 0b10100001010001011010000101000101; > int anInt2 = 0b101; > int anInt3 = 0B101; // The B can be upper or lower case as per the x in "0x45". > > // A 64-bit 'long' literal. Note the "L" suffix. > long aLong = 0b1010000101000101101000010100010110100001010001011010000101000101L; > > SIMPLE EXAMPLE: > > class Foo { > public static void main(String[] args) { > System.out.println("The value 10100001 in decimal is " + 0b10100001); > } > > > ADVANCED EXAMPLE: > > // Boolean constants could be used in code that needs to be > // easily checkable against a specifications document, such > // as this simulator for a hypothetical 8-bit microprocessor: > > public State decodeInstruction(int instruction, State state) { > if ((instruction & 0b11100000) == 0b00000000) { > final int register = instruction & 0b00001111; > switch (instruction & 0b11110000) { > case 0b00000000: return state.nop(); > case 0b00010000: return state.copyAccumTo(register); > case 0b00100000: return state.addToAccum(register); > case 0b00110000: return state.subFromAccum(register); > case 0b01000000: return state.multiplyAccumBy(register); > case 0b01010000: return state.divideAccumBy(register); > case 0b01100000: return state.setAccumFrom(register); > case 0b01110000: return state.returnFromCall(); > default: throw new IllegalArgumentException(); > } > } else { > final int address = instruction & 0b00011111; > switch (instruction & 0b11100000) { > case 0b00100000: return state.jumpTo(address); > case 0b01000000: return state.jumpIfAccumZeroTo(address); > case 0b01000000: return state.jumpIfAccumNonzeroTo(address); > case 0b01100000: return state.setAccumFromMemory(address); > case 0b10100000: return state.writeAccumToMemory(address); > case 0b11000000: return state.callTo(address); > default: throw new IllegalArgumentException(); > } > } > } > > // Binary literals can be used to make a bitmap more readable: > > public static final short[] HAPPY_FACE = { > (short)0b0000011111100000; > (short)0b0000100000010000; > (short)0b0001000000001000; > (short)0b0010000000000100; > (short)0b0100000000000010; > (short)0b1000011001100001; > (short)0b1000011001100001; > (short)0b1000000000000001; > (short)0b1000000000000001; > (short)0b1001000000001001; > (short)0b1000100000010001; > (short)0b0100011111100010; > (short)0b0010000000000100; > (short)0b0001000000001000; > (short)0b0000100000010000; > (short)0b0000011111100000; > } > > // Binary literals can make relationships > // among data more apparent than they would > // be in hex or octal. > // > // For instance, what does the following > // array contain? In hexadecimal, it's hard to tell: > public static final int[] phases = { > 0x31, 0x62, 0xC4, 0x89, 0x13, 0x26, 0x4C, 0x98 > } > > // In binary, it's obvious that a number is being > // rotated left one bit at a time. > public static final int[] phases = { > 0b00110001, > 0b01100010, > 0b11000100, > 0b10001001, > 0b00010011, > 0b00100110, > 0b01001100, > 0b10011000, > } > > > DETAILS > > SPECIFICATION: > > Section 3.10.1 ("Integer Literals") of the JLS3 should be changed to add the following: > > IntegerLiteral: > DecimalIntegerLiteral > HexIntegerLiteral > OctalIntegerLiteral > BinaryIntegerLiteral // Added > > BinaryIntegerLiteral: > BinaryNumeral IntegerTypeSuffix_opt > > BinaryNumeral: > 0 b BinaryDigits > 0 B BinaryDigits > > BinaryDigits: > BinaryDigit > BinaryDigit BinaryDigits > > BinaryDigit: one of > 0 1 > > COMPILATION: > > Binary literals would be compiled to class files in the same fashion as existing decimal, hexadecimal, and octal literals are. No special support or changes to the class file format are needed. > > TESTING: > > The feature can be tested in the same way as existing decimal, hexadecimal, and octal literals are: Create a bunch of constants in source code, including the maximum and minimum positive and negative values for integer and long types, and verify them at runtime to have the correct values. > > > LIBRARY SUPPORT: > > The methods Integer.decode(String) and Long.decode(String) should be modified to parse binary numbers (as specified above) in addition to their existing support for decimal, hexadecimal, and octal numbers. > > > REFLECTIVE APIS: > > No updates to the reflection APIs are needed. > > > OTHER CHANGES: > > No other changes are needed. > > > MIGRATION: > > Individual constants in decimal, hexadecimal, or octal can be updated to binary as a programmer desires. > > > COMPATIBILITY: > > > BREAKING CHANGES: > > This feature would not break any existing programs, since the suggested syntax is currently considerd to be a compile-time error. > > > EXISTING PROGRAMS: > > Class file format does not change, so existing programs can use class files compiled with the new feature without problems. > > > REFERENCES: > > The GCC/G++ compiler, which already supports this syntax (as of version 4.3) as an extension to standard C/C++. > http://gcc.gnu.org/gcc-4.3/changes.html > > The Ruby language, which supports binary literals: > http://wordaligned.org/articles/binary-literals > > The Python language added binary literals in version 2.6: > http://docs.python.org/dev/whatsnew/2.6.html#pep-3127-integer-literal-support-and-syntax > > EXISTING BUGS: > > "Language support for literal numbers in binary and other bases" > http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=5025288 > > URL FOR PROTOTYPE (optional): > > None. > > > From vapor1 at teleport.com Fri May 8 01:47:17 2009 From: vapor1 at teleport.com (Derek Foster) Date: Fri, 8 May 2009 04:47:17 -0400 (EDT) Subject: PROPOSAL: Equivalence operators (formerly titled "Sameness operators") (Version 3) Message-ID: <24994307.1241772437832.JavaMail.root@mswamui-chipeau.atl.sa.earthlink.net> Discussion on the Project Coin mailing list has suggested that the previous version of this proposal's use of the $ character has enough potential to break code (albeit in rare cases, and only in generated code) that it is likely to not be considered feasible for this purpose. The ~ character (also briefly mentioned in the previous version of the proposal) has similar problems. Therefore, this proposal has been altered to use the # character instead, as this does not (as far as I am aware) introduce any potential for code breakage, with @ as a suggested alternative should # not be considered acceptable. Some discussion of how this use of # might impact other JDK 8 proposals (closure proposals, etc.) which might also wish to use the # character has also been added. Equivalence Operators (previously called "Sameness operators") (Version 3) AUTHOR: Derek Foster OVERVIEW Many Java objects implement the Comparable interface, and/or override the Object.equals() method, to provide a way of ordering their instances or detecting whether two instances are equivalent . However, the syntax for using these methods has historically been fairly ugly: // We want to write "if a >= b", but we have to write... if (a.compareTo(B) >= 0) { whatever(); } // We want to write "if a == b", but we have to write... if (a == null ? b == null : a.equals(b)) { whatever(); } The ugliness of these methods has often motivated the creation of special-purpose APIs to simplify the use of classes which implement them, such as the 'Date.before(Date)' and 'Date.after(Date)' methods in java.util.Date. However, these methods are inconsistent from class to class, and often not present. Furthermore, the existing language == and != operators exhibit a strange assymetry between the behavior of objects and that of primitive types that often catches new users of Java by surprise: int i; if (i == 5) { // gets here if the VALUE of i is 5 } String j = new String("abc"); if (j == "abc") { // probably never gets here! Comparing the values of the references, not the values of the strings. } String k = new String("abc"); if (k.equals("abc")) { // gets here if the VALUE of k is "abc". } This behavior often confuses newcomers to Java, and is a common source of bugs even for experienced programmers. This proposal suggests that a new set of relational operators be added to Java which would simplify ordering classes by their declared orderings (as specified by the Comparable class and Object.equals()), while still yielding syntax that is as simple as using the existing >=, <=, ==, and != operators. FEATURE SUMMARY: Adds four new operators to Java: a ## b "equivalent to": a==null ? b==null : a.equals(b), or a == b for primitive types. a !# b "not equivalent to": a==null ? b!=null : !a.equals(b), or a != b for primitive types. a ># b "greater than or equivalent": a.compareTo(b) >= 0, or a >= b for primitive types. a <# b "less than or equivalent": a.compareTo(b) <= 0, or a <= b for primitive types. and adds additional overloadings to existing operators: a < b a.compareTo(b) < 0, or a < b for primitive types. a > b a.compareTo(b) > 0, or a > b for primitive types. Note that this proposal specifies alternatives to the specific operator names chosen. For instance, the proposal could be implemented using @@, !@, >@, and <@ instead of ##, !#, >#, and <#) if the use of '#' is deemed problematic due to possible interference with other uses by future proposals Java language changes. This is discussed in the "ALTERNATIVES" section below. MAJOR ADVANTAGE: Use of new operators for these relational tests would simplify code and make it more clear what relational tests are being made, as well as reducing the opportunity for mistakes (such as accidentally typing a.compareTo(b) >=0 when <=0 was intended). MAJOR BENEFIT: Clearer code due to the use of infix operators instead of using method calls and an extra pair of parentheses, plus possible extra tests (often accidentally omitted) for nullness around calls to Object.equals(Object). Future Java language change proposals involving limited uses of operator overloading for code clarity (for BigInteger, complex number, etc. classes) would no longer run into the iceberg of "but you can't change the behavior of == in a backwards-compatible fashion!" MAJOR DISADVANTAGE: Modifications to the compiler would be required. These do not appear particularly difficult, but would take some effort. ALTERNATIVES: Keep using the Comparable.compareTo and Object.equals methods as they are. It would have been better to define == and != this way in the first place, and use some other operator (perhaps === as in some other languages?) to indicate comparison by object identity. This would have made Java simpler and easier for newcomers to understand. However, that's not how the language is currently defined, and to change the behavior of == now would be a backwards incompatible change. It might be possible to define ## and !# in terms of "Comparator.compareTo(T)" instead of in terms of Object.equals(Object). However, doing so would have been less general purpose (it would only have worked on comparable classes). Although it is possible for the equals and compareTo methods of an object to disagree (for instance, Float's handling of Float.NaN), in practice this rarely occurs in the scenarios for which compareTo is typically used for determining well-ordering (sorting algorithms, etc.). The default set of operators (##, !#, >#, and <#) suggested in this proposal were chosen because the "#" is somewhat similar to an equals sign, and hence has an easy mnemonic meaning of equivalence (as opposed to identity, which is represented by "="). However, the '#' character is highly sought after by writers of language change proposals (such as closures, method pointers, and others), and so is under heavy competition as to its future meaning. Some care might be required to ensure that use of the # character by this proposal would not interfere with some other future desired meaning of the # character. Fortunately, most existing proposals for using the "#" in code have attempted to use it as an infix operator with identifiers on either side rather than as a prefix operator, which reduces the risk of conflicting with this proposal. Also, if the above operators were defined as tokens before any such code exists, it should be easy to ensure that any future use of the # character simply never falls into the pattern of one of these tokens. For instance, the ">#" token is only even potentially ambiguous if there is some meaning assigned to the prefix operator # such that comparisons are legal. For instance, if a closure proposal would make "if (#foo>#bar)" into legal code (defining #foo and #bar in such a way that whatever they represented was meaningful to compare with the ">" operator), then extra whitespace might be needed in some cases to ensure that this wasn't parsed as "if (#foo ># bar)". Alternately, this proposal could be altered to use another character instead of # for its tokens. One good candidate for this would be "@", which is also unused as an operator in Java, but which unfortunately lacks any obvious (to the author of this proposal, anyway) mnemonic to associate it with equality or ordering tests. EXAMPLES SIMPLE EXAMPLE: String getOrdering(String first, String second) { if (first ## second) { System.out.println("They are equal"); } else if (first !# second) { System.out.println("They are not equal"); } else if (first > second) { System.out.println("The first is after the second"); } else if (first ># second) { System.out.println("The first is same as or after the second"); } else if (first < second) { System.out.println("The first is before the second"); } else if (first <# second) { System.out.println("The first is before or the same as the second"); } } ADVANCED EXAMPLE: Really, the simple example pretty much illustrates the feature. DETAILS SPECIFICATION: The following new tokens ## !# ># <# shall be added to section 3.12 of the JLS3. The expression grammar in section 15.20 shall be modified like so: RelationalExpression: ShiftExpression RelationalExpression < ShiftExpression RelationalExpression > ShiftExpression RelationalExpression <= ShiftExpression RelationalExpression >= ShiftExpression RelationalExpression ># ShiftExpression RelationalExpression <# ShiftExpression RelationalExpression instanceof ReferenceType The expression grammar in section 15.21 shall be modified like so: EqualityExpression: RelationalExpression EqualityExpression == RelationalExpression EqualityExpression != RelationalExpression EqualityExpression ## RelationalExpression EqualityExpression !# RelationalExpression Semantically, the behavior of these new operators is as follows: ## and !# operators: Evaluation of these operators shall occur exactly as they do for the == and != operators, as specified in section 15.21 of the JLS3 ("Equality Operators"), with the exception that for the purposes of these operators, section 15.21.3 ("Reference equality operators == and !=") shall be disregarded and replaced with: If the operands of a sameness operator are both of either reference type or the null type, then the operation is object equivalence. The behavior described below is for the ## operator. The !# operator shall behave identically except that it shall return false when the ## operator would return true, and vice versa. The procedure for evaluating the ## operator is as follows: If both operands are null, then the result shall be 'true'. Otherwise, if the left operand is null and the right operand is not null, then the result shall be 'false'. Otherwise, the return value shall be the value of the expression "left.equals(right)", evaluated using the java.lang.Object.equals(Object) method. >, >#, <, and <# operators: Evaluation of these operators shall occur exactly as it does for corresponding >, >=, <, and <= operators, in section 15.20.1 of the JLS3 ("Numerical Comparison Operators <, <=, >, and >=") with the exception of the following. The text "The type of each of the operands of a numerical comparison operator must be a type that is convertible (?5.1.8) to a primitive numeric type, or a compile-time error occurs." shall be replaced with the text "If the type of both of the operands of a numerical comparison operator is a type that is convertible (?5.1.8) to a primitive numeric type, the following algorithm is used to evaluate the operator. Otherwise, the operation is object ordering (See ?15.20.1.1)" A new section 15.20.1.1 shall be added consisting of the following text: If one or both operands of a relational operator cannot be converted to primitive numeric types, then boxing conversions shall be used to convert both operands to object types. After this conversion, if the type of the left operand does not extend the raw type java.lang.Comparable, and also does not extend java.lang.Comparable for some type T which is equal to or a supertype of the type of the right operand, then a compiler error shall be reported. Otherwise, the result of the comparison shall be evaluated at runtime as follows: If the left operand is null, a NullPointerException shall be thrown. Otherwise, the method left.compareTo(right) shall be called. The following table shall be used to determine the result of the operator evaluation, based on the value returned from this method: left.compareTo(right) <0 ==0 >0 > false false true < true false false ># false true true <# true true false COMPILATION: Compilation of the example given above would be desugared as follows: if (first==null ? second==null : first.equals(second)) { System.out.println("They are equal"); } else if (first==null ? second != null : !first.equals(second)) { System.out.println("They are not equal"); } else if (first.compareTo(second) > 0) { System.out.println("The first is after the second"); } else if (first.compareTo(second) >= 0) { System.out.println("The first is same as or after the second"); } else if (first.compareTo(second) < 0) { System.out.println("The first is before the second"); } else if (first.compareTo(second) <= 0) { System.out.println("The first is before or the same as the second"); } TESTING: The feature can be tested by ensuring, first of all that the new operators return the same results as existing operators when invoked on operands which are both convertible to numeric primitive types. Secondly, that the new operators return the same results as their desugaring equivalents when invoked in circumstances where one or both operands are not convertible to numeric primitive types. Thirdly, that the relational operators throw NullPointerExceptions when the leftmost operation is null. Fourthly, that compiler errors are reported exactly in the cases when the desugared equivalents of the operators would not compile. LIBRARY SUPPORT: No library changes are needed for this feature. REFLECTIVE APIS: No changes to reflective APIs are needed for this feature. OTHER CHANGES: No other parts of the platform need to be updated. MIGRATION: A tool such as Eclipse or IntelliJ Idea might identify for the users existing calls to .compareTo or .equals which could be converted to use the new operators, and could offer to perform the change automatically at the user's request. Or a user could simply refactor code to use the new operators as desired. COMPATIBILITY BREAKING CHANGES: The current version of this proposal should not break any previously valid code. EXISTING PROGRAMS: This change should not create incompatibilities with existing source or class files. REFERENCES EXISTING BUGS: There are a variety of proposals in the Bug Database related to various people's desires to support operator overloading for certain built-in mathematical classes such as BigInteger. A couple of these proposals are listed below. "Add [], -, +, *, / operators to core classes as appropriate" (related) http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=5099780 "BigInteger should support autoboxing" http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6407464 Also, see discussion on the Project Coin mailing list regarding the proposal "Draft proposal: allow the use of relational operators on Comparable classes," particularly with regards to why that proposal was withdrawn (namely, inability to make the == and != operators work properly on Comparable classes). http://mail.openjdk.java.net/pipermail/coin-dev/2009-March/000361.html URL FOR PROTOTYPE (optional): None. From mthornton at optrak.co.uk Fri May 8 03:05:17 2009 From: mthornton at optrak.co.uk (Mark Thornton) Date: Fri, 08 May 2009 11:05:17 +0100 Subject: PROPOSAL: Equivalence operators (formerly titled "Sameness operators") (Version 3) In-Reply-To: <24994307.1241772437832.JavaMail.root@mswamui-chipeau.atl.sa.earthlink.net> References: <24994307.1241772437832.JavaMail.root@mswamui-chipeau.atl.sa.earthlink.net> Message-ID: <4A0403DD.3080208@optrak.co.uk> Derek Foster wrote: > and adds additional overloadings to existing operators: > a < b a.compareTo(b) < 0, or a < b for primitive types. > > If 'a' is Float (or Double) and 'b' is float (double), then you have to unbox 'a' to apply the primitive comparison and not box 'b' and apply .compareTo. Boxing 'b' to apply compareTo would be a breaking change. Mark Thornton From tim at peierls.net Fri May 8 04:34:30 2009 From: tim at peierls.net (Tim Peierls) Date: Fri, 8 May 2009 07:34:30 -0400 Subject: PROPOSAL: Abstract enums (version 2) In-Reply-To: <3dd3f56a0905072251l427e9c8y24098e9233af1d99@mail.gmail.com> References: <3dd3f56a0905072251l427e9c8y24098e9233af1d99@mail.gmail.com> Message-ID: <63b4e4050905080434j112605fch6b30baa9328fdff3@mail.gmail.com> On Fri, May 8, 2009 at 1:51 AM, Howard Lovatt wrote: > Further it would be nice if you could make a singleton by having a enum > with *no* members. I don't understand what you mean here. A one element enum makes a great singleton. (Effective Java 2nd ed., Item 3.) --tim From vapor1 at teleport.com Fri May 8 14:38:11 2009 From: vapor1 at teleport.com (Derek Foster) Date: Fri, 8 May 2009 17:38:11 -0400 (EDT) Subject: PROPOSAL: Equivalence operators (formerly titled Message-ID: <9424230.1241818691348.JavaMail.root@mswamui-chipeau.atl.sa.earthlink.net> Hi, Mark. Thanks for your comments. The proposal already does what you suggest, although I agree it is not clear from the section you quoted (which was only intended to be a brief feature summary). If you look in the specification section, you will find that in a case like "a < b" where a is Float and b is float, that since both types are convertible to a primitive type, that this conversion will be done before the operation is attempted (possibly triggering a NullPointerException on unboxing), yielding the same results as would occur in Java now. In some ways, I think it would be nice to have the ># and <# operators return true if both of their operands are null, even if both operands are typed as boxed primitives. This would be more similar to how ## and !# work and would be consistent for all operators if you assume that null "is equivalent to" null. I am considering changing the proposal to allow this. (Currently this operation would provoke a NullPointerException during unboxing, according to proposal version 3 and before). < and > would not be affected by this, of course. Comments? Derek -----Original Message----- >From: Mark Thornton >Sent: May 8, 2009 3:05 AM >To: Derek Foster >Cc: Project Coin >Subject: Re: PROPOSAL: Equivalence operators (formerly titled "Sameness operators") (Version 3) > >Derek Foster wrote: >> and adds additional overloadings to existing operators: >> a < b a.compareTo(b) < 0, or a < b for primitive types. >> >> >If 'a' is Float (or Double) and 'b' is float (double), then you have to >unbox 'a' to apply the primitive comparison and not box 'b' and apply >.compareTo. Boxing 'b' to apply compareTo would be a breaking change. > >Mark Thornton From Joe.Darcy at Sun.COM Fri May 8 15:21:41 2009 From: Joe.Darcy at Sun.COM (Joe Darcy) Date: Fri, 08 May 2009 15:21:41 -0700 Subject: PROPOSAL: String parameters compile time validation (early beta) In-Reply-To: <49CC797C.3030905@adres.pl> References: <28bca0ff0903261350w1b12327cne9938ab7502a210d@mail.gmail.com> <49CBF17C.1050708@adres.pl> <142223BF-521F-4308-8FD8-DC754A4B5D04@zwitserloot.com> <49CC797C.3030905@adres.pl> Message-ID: <4A04B075.20709@sun.com> On 03/27/09 12:00 AM, Artur Biesiadowski wrote: > Reinier Zwitserloot wrote: > >> The idea is simply to have a literal syntax for regexps, where the >> compiler will actually put the binary representation of a compiled >> pattern in the .class source. As I mentioned, this has very >> significant speed savings, because compiling a regexp is more >> expensive than applying one, especially for complex regexps that are >> performance sensitive. >> >> I don't understand your argument about casting. Right now, you get >> compile-time checking on e.g. the bounds of an integer, but if you >> cast, you get that check at runtime (or, actually, the bits are just >> cut off, but you get the point). >> >> The regexp literal notation would literally have the type 'Pattern'. >> You can try to cast a string to this, but that would obviously fail, >> and the compiler will in fact error when you try, because String is >> not a subtype of Pattern. If you want to turn a string into a pattern, >> you'd use Pattern.compile. So: >> >> Pattern x = /a*a+a*a+/; >> Pattern y = Pattern.compile("a*a+a*a+"); >> > > > I think that we are talking about different things. As far as I > understood OP, he wants to have kind of typedef String which accepts > only certain values. It is not about compile-time Patterns, which are > just a side requirement. Main topic is to have something like > > @Regexp("JustDigits","[0-9]+"); > > void setPhoneNumber(@Regexp("JustDigits") String phoneNumber) > > > Now, you can call it from the code like > > obj.setPhoneNumber("12345") > > and compile would do a static check if 12345 is fitting "[0-9]+" regexp, > but you probably would also like to do > > String number = someField.getText(); > obj.setPhoneNumber(number); > > which is not safe. We would need to have something like > > String number = someField.getText(); > @Regexp("JustDigits") String reallyNumber = > @Regexp("JustDigits").check(number); > obj.setPhoneNumber(reallyNumber); > > Actually, when I think about static code checks like in the first case, > I don't think it could be pulled out if this crosses class boundary - > you could recompile receiver class, changing the regexp contents and the > safety would fail (unless regexp would be included into method signature > by contents). > > Regards, > Artur Biesiadowski > > Catching up on email, one can imagine schemes to validate extra-linguistic aspects of annotation values like "this string must be a regular expression" or "this integer must be in the range 0 to 10, inclusive" and JSR 308 is working on enabling a new class of compile-time checkers; however, I don't think any further language support for such idea, including AOP style injection of additional runtime checks, is appropriate for Project Coin. -Joe -Joe From Joe.Darcy at Sun.COM Fri May 8 17:16:58 2009 From: Joe.Darcy at Sun.COM (Joe Darcy) Date: Fri, 08 May 2009 17:16:58 -0700 Subject: PROPOSAL: Auto-assignment Parameters In-Reply-To: References: Message-ID: <4A04CB7A.5060309@sun.com> Hello. Catching up on email replies, while the this.foo = foo; pattern in constructors is verbose and a bit silly, given the existence of pretty tooling to check for errors, I don't think this situation rises to the level of a problem needing language support. -Joe On 03/24/09 06:07 PM, Mark Mahieu wrote: > HTML version + prototype available at http://slm888.com/javac > > > > Auto-assignment Parameters v0.1 > > > AUTHOR(S): > > Mark Mahieu > > > OVERVIEW > > FEATURE SUMMARY: Should be suitable as a summary in a language tutorial. > > An additional form of constructor parameter which provides automatic > assignment of the parameter's value to an instance field. These parameters > are implicitly declared as final to prevent unintentional assignments to the > wrong variable in the constructor body. > > > MAJOR ADVANTAGE: What makes the proposal a favorable change? > > Reduces the likelihood of some common coding errors relating to assignment > of fields in a constructor, including those where: > > * a field is assigned to itself > * the parameter is assigned instead of the field > * the assignment to the field is missing entirely > > These and other errors are often caused by typos or code refactoring. > > > MAJOR BENEFIT: Why is the platform better if the proposal is adopted? > > A programmer's intent is more clearly expressed for the extremely common > case of assigning a constructor parameter directly to an instance field with > the same name. > > > MAJOR DISADVANTAGE: There is always a cost. > > As with any sugar which enables a more concise way of expressing an existing > idiom, programmers may be tempted to use it even when the original form > would be more appropriate. > > > ALTERNATIVES: Can the benefits and advantages be had some way without a > language change? > > IDEs and tools such as FindBugs are good at warning about the kind of errors > mentioned above, however since the code in question is usually still valid > to the compiler, they are limited in what action they can take by default. > > A language change can combine the ability to avoid these errors entirely > with a more expressive idiom, resulting in an increased signal to noise > ratio for readers of that code. > > > > EXAMPLES > > SIMPLE EXAMPLE: Show the simplest possible program utilizing the new > feature. > > class C { > int i; > C(int this.i) {} > } > > > ADVANCED EXAMPLE: Show advanced usage(s) of the feature. > > > class Proposal { > > private final String name; > private final String author; > private boolean suitableForCoin; > private Integer score; > > public Proposal(String this.name, > String this.author, > boolean this.suitableForCoin, > int this.score) { > > if (name.equals(?Auto-assignment Parameters?)) { > suitableForCoin = true; // final so compile-time error > } > } > > // rest of class ... > } > > > > DETAILS > > > SPECIFICATION: Describe how the proposal affects the grammar, type system, > and meaning of expressions and statements in the Java Programming Language > as well as any other known impacts. > > The syntactic grammar is modified to include auto-assignment parameters for > constructors: > > ConstructorDeclaratorRest: > ConstructorParameters [throws QualifiedIdentifierList] > MethodBody > > ConstructorParameters: > ( [ConstructorParameterDecls] ) > > ConstructorParameterDecls: > [final] [Annotations] Type ConstructorParameterDeclsRest > > ConstructorParameterDeclsRest: > ConstructorParameterId [ , ConstructorParameterDecls] > ... ConstructorParameterId > > ConstructorParameterId: > VariableDeclaratorId > this . VariableDeclaratorId > super . VariableDeclaratorId > > An auto-assignment parameter is a formal parameter (JLSv3 ?8.4.1) which > specifies an instance field instead of an identifier. Its value is > automatically assigned to the specified field. It may only be used in a > constructor. > > The automatic assignment takes place after any explicit or implicit > invocation of another constructor, and before any statements in the body of > the constructor. A constructor which declares n auto-assignment parameters > will perform n such automatic assignments, in the order that the parameters > are declared. > > The parameter has the same name (JLSv3 ?6.2) as the field to which it is > assigned; replacing each auto-assignment parameter with a normal formal > parameter with the same name would yield a constructor with an identical > signature. As with a normal parameter, the parameter's name is entered into > the scope of the constructor body (JLSv3 ?6.3), and therefore shadows the > field (JLSv3 ?6.3.1) within that scope. > > It is a compile-time error if the field is not accessible from the > constructor in which the parameter appears. > > It is a compile-time error if the declared type of the parameter is not > assignment compatible (JLSv3 ?5.2) with the field to which it is > automatically assigned. > > If an unboxing conversion is required by an automatic assignment, any > NullPointerException thrown as a result (JLSv3 ?5.1.8) will contain the name > of the field on which the conversion failed, which may be retrieved by > calling getMessage() on the exception. > > Auto-assignment parameters are implicitly final, and follow the standard > rules for final variables (JLSv3 ?4.12.4). Explicitly declaring an > auto-assignment parameter as final has no effect, and does not cause a > compilation error. > > Auto-assignment parameters follow the standard definite assignment rules for > formal parameters (JLSv3 ?16.3). > > An auto-assignment parameter may be annotated. > > If an auto-assignment parameter is the last parameter in the list, and > refers to a field of array type, it may be a variable arity parameter. > > > > COMPILATION: How would the feature be compiled to class files? Show how the > simple and advanced examples would be compiled. Compilation can be expressed > as at least one of a desugaring to existing source constructs and a > translation down to bytecode. If a new bytecode is used or the semantics of > an existing bytecode are changed, describe those changes, including how they > impact verification. Also discuss any new class file attributes that are > introduced. Note that there are many downstream tools that consume class > files and that they may to be updated to support the proposal! > > Desugaring of the following class: > > class Foo { > int value; > Foo(Integer this.value) { > System.out.println(value); > } > } > > would result in (unboxing desugaring omitted): > > class Foo { > int value; > Foo(final Integer value) { > super(); > if (value == null) > throw new NullPointerException("value"); > this.value = value; > System.out.println(value); > } > } > > No changes to the classfile format are required. Tools which consume class > files see the constructor signature as though it had been written using > normal formal parameters. > > > TESTING: How can the feature be tested? > > An initial set of jtreg tests is included in the prototype. > > > LIBRARY SUPPORT: Are any supporting libraries needed for the feature? > > No > > > REFLECTIVE APIS: Do any of the various and sundry reflection APIs need to be > updated? This list of reflective APIs includes but is not limited to core > reflection (java.lang.Class and java.lang.reflect.*), javax.lang.model.*, > the doclet API, and JPDA. > > com.sun.source.tree.VariableTree would require an additional method which > returns the auto-assigned field. > > > OTHER CHANGES: Do any other parts of the platform need be updated too? > Possibilities include but are not limited to JNI, serialization, and output > of the javadoc tool. > > No > > > MIGRATION: Sketch how a code base could be converted, manually or > automatically, to use the new feature. > > Assignment statements in constructors for which all of the following are > true can be considered suitable for conversion: > * the lhs of the assignment is a non-static field > * the rhs is a parameter with the same name as the field > * there are no other assignments to the parameter anywhere in the > constructor > * there are no assignments to, or other uses of the field before the > assignment statement in question (including invoked constructors) > > Such statements can be converted by: > 1) replacing the parameter with an auto-assignment parameter (prefixing > the existing parameter's identifier with 'this.'), and > 2) removing the assignment statement > > > > COMPATIBILITY > > BREAKING CHANGES: Are any previously valid programs now invalid? If so, list > one. > > No > > > EXISTING PROGRAMS: How do source and class files of earlier platform > versions interact with the feature? Can any new overloadings occur? Can any > new overriding occur? > > The semantics of existing class files and legal source files are unchanged > by this feature. > > > > REFERENCES > > EXISTING BUGS: Please include a list of any existing Sun bug ids related to > this proposal. > > http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6582394 > (uses a 'setter' method rather than a constructor in its example) > > FindBugs bug patterns - http://findbugs.sourceforge.net/bugDescriptions.html > * Self assignment of field (SA_FIELD_SELF_ASSIGNMENT) > * Self comparison of field with itself (SA_FIELD_SELF_COMPARISON) > * Nonsensical self computation involving a field (e.g., x & x) > (SA_FIELD_SELF_COMPUTATION) > * Self assignment of local variable (SA_LOCAL_SELF_ASSIGNMENT) > * Nonsensical self computation involving a variable (e.g., x & x) > (SA_LOCAL_SELF_COMPUTATION) > * Uninitialized read of field in constructor (UR_UNINIT_READ) > * Unwritten field (UWF_UNWRITTEN_FIELD) > * Dead store to local variable (DLS_DEAD_LOCAL_STORE) > * Dead store of null to local variable (DLS_DEAD_LOCAL_STORE_OF_NULL) > > > > URL FOR PROTOTYPE (optional): > > http://slm888.com/javac > > > > DESIGN ALTERNATIVES: > > The following variations have been explored and are worth mentioning: > > * Allow auto-assignment parameters on all non-abstract methods. > This may be especially useful on the extremely common 'setter' methods > in 'value object' classes. > > * Remove the requirement for (or even disallow) the type to be specified on > auto-assignment parameters. > Experimentation with this idea suggests that it may work quite well for > constructors, further emphasising the difference in intent and semantics > from those of normal parameters. However, it may not work so well in > combination with auto-assignment parameters on all non-abstract methods, and > requires a change to the order in which javac compiles classes (can still > pass jtreg tests). > > * Allow an alternative name to be specified. > This adds additional complexity to support a fractional percentage of > cases, which could continue to use the existing coding pattern. > > From vapor1 at teleport.com Fri May 8 18:10:00 2009 From: vapor1 at teleport.com (Derek Foster) Date: Fri, 8 May 2009 21:10:00 -0400 (EDT) Subject: PROPOSAL: Sameness operators (version 2) Message-ID: <9325162.1241831400775.JavaMail.root@mswamui-chipeau.atl.sa.earthlink.net> Hi, Mark. In case this wasn't clear from my previous replies... the intent (as specified in the proposal's "specification" section) is that the < and > operators will operate exactly the same as they currently do for values that are convertible to primitive types, so as to avoid introduction of any breaking changes. Therefore, unboxing conversion will first occur before comparison occurs. Derek -----Original Message----- >From: Mark Thornton >Sent: May 1, 2009 3:38 AM >To: Derek Foster >Cc: Project Coin >Subject: Re: PROPOSAL: Sameness operators (version 2) > >Derek Foster wrote: >> and adds additional overloadings to existing operators: >> a < b a.compareTo(b) < 0, or a < b for primitive types. >> a > b a.compareTo(b) > 0, or a > b for primitive types. >> >> >0f < Float.NaN is false > >Float.valueOf(0).compareTo(Float.valueOf(Float.NaN)) < 0 is true > >With Float objects, would the values be unboxed and then compared using >the existing '<' operator or left boxed and compared using compareTo? If >the former, then casting to Comparable would change the result, while >the second alternative would change the current result (obtained via >autounboxing). > >Mark Thornton > From mthornton at optrak.co.uk Sat May 9 01:33:27 2009 From: mthornton at optrak.co.uk (Mark Thornton) Date: Sat, 09 May 2009 09:33:27 +0100 Subject: PROPOSAL: Equivalence operators (formerly titled In-Reply-To: <9424230.1241818691348.JavaMail.root@mswamui-chipeau.atl.sa.earthlink.net> References: <9424230.1241818691348.JavaMail.root@mswamui-chipeau.atl.sa.earthlink.net> Message-ID: <4A053FD7.304@optrak.co.uk> Derek Foster wrote: > Hi, Mark. > > Thanks for your comments. > > The proposal already does what you suggest, although I agree it is not clear from the section you quoted (which was only intended to be a brief feature summary). If you look in the specification section, you will find that in a case like "a < b" where a is Float and b is float, that since both types are convertible to a primitive type, that this conversion will be done before the operation is attempted (possibly triggering a NullPointerException on unboxing), yielding the same results as would occur in Java now. > > In some ways, I think it would be nice to have the ># and <# operators return true if both of their operands are null, even if both operands are typed as boxed primitives. This would be more similar to how ## and !# work and would be consistent for all operators if you assume that null "is equivalent to" null. I am considering changing the proposal to allow this. (Currently this operation would provoke a NullPointerException during unboxing, according to proposal version 3 and before). < and > would not be affected by this, of course. Comments? > > Derek > My first thought was that managing null with ># and <# was attractive and nicely consistent with ## and #!, but then <, > don't just return false but throw a NullPointerException. Why can't we overload >= and <= instead in the same way as < and > (i.e. only apply to Comparable types which are NOT convertable to primitives). Then ##, #! handle null, based on equals() <=, >=, <, > For primitives or primitive wrappers behave as now and throw NullPointerException with null wrapper values <=, >=, <, > For Comparable types other than primitive wrappers, based on compareTo, throw NullPointerException Regards, Mark Thornton From vilya.harvey at gmail.com Sat May 9 04:14:50 2009 From: vilya.harvey at gmail.com (Vilya Harvey) Date: Sat, 9 May 2009 12:14:50 +0100 Subject: PROPOSAL: Equivalence operators (formerly titled In-Reply-To: <4A053FD7.304@optrak.co.uk> References: <9424230.1241818691348.JavaMail.root@mswamui-chipeau.atl.sa.earthlink.net> <4A053FD7.304@optrak.co.uk> Message-ID: <6aef848f0905090414w42e2973xc5bb2b3aeab5899f@mail.gmail.com> Hiya 2009/5/9 Mark Thornton : > Why can't we overload >= and <= instead in the same way as < and > (i.e. > only apply to Comparable types which are NOT convertable to primitives). This is exactly what I proposed a few months ago. I ended up withdrawing the proposal because it gives you a strange-looking asymmetry with == and !=. You can't == or != to be based on Comparable because it would break way too much code, but without changing them, you end up with statements like this being valid: if (a < b) ... else if (a > b) ... else if (a == b) ... else ... There's also the possibility of the operators causing a ClassCastException to watch out for, as well as a NullPointerException. I still like the idea myself, but it certainly has the potential to be confusing. Hope that helps, Vil. From markmahieu at googlemail.com Sat May 9 15:22:18 2009 From: markmahieu at googlemail.com (Mark Mahieu) Date: Sat, 9 May 2009 23:22:18 +0100 Subject: PROPOSAL: Auto-assignment Parameters In-Reply-To: <4A04CB7A.5060309@sun.com> References: <4A04CB7A.5060309@sun.com> Message-ID: <67E5C1AD-13D0-4451-A927-A63FCCA7D1B7@googlemail.com> Hi Joe, Ok, thanks for taking the time to look at it. Mark On 9 May 2009, at 01:16, Joe Darcy wrote: > Hello. > > Catching up on email replies, while the > > this.foo = foo; > > pattern in constructors is verbose and a bit silly, given the > existence of pretty tooling to check for errors, I don't think this > situation rises to the level of a problem needing language support. > > -Joe > > On 03/24/09 06:07 PM, Mark Mahieu wrote: >> HTML version + prototype available at http://slm888.com/javac >> >> >> >> Auto-assignment Parameters v0.1 >> >> >> AUTHOR(S): >> >> Mark Mahieu >> >> >> OVERVIEW >> >> FEATURE SUMMARY: Should be suitable as a summary in a language >> tutorial. >> >> An additional form of constructor parameter which provides automatic >> assignment of the parameter's value to an instance field. These >> parameters >> are implicitly declared as final to prevent unintentional >> assignments to the >> wrong variable in the constructor body. >> >> >> MAJOR ADVANTAGE: What makes the proposal a favorable change? >> >> Reduces the likelihood of some common coding errors relating to >> assignment >> of fields in a constructor, including those where: >> >> * a field is assigned to itself >> * the parameter is assigned instead of the field >> * the assignment to the field is missing entirely >> >> These and other errors are often caused by typos or code refactoring. >> >> >> MAJOR BENEFIT: Why is the platform better if the proposal is adopted? >> >> A programmer's intent is more clearly expressed for the extremely >> common >> case of assigning a constructor parameter directly to an instance >> field with >> the same name. >> >> >> MAJOR DISADVANTAGE: There is always a cost. >> >> As with any sugar which enables a more concise way of expressing >> an existing >> idiom, programmers may be tempted to use it even when the original >> form >> would be more appropriate. >> >> >> ALTERNATIVES: Can the benefits and advantages be had some way >> without a >> language change? >> >> IDEs and tools such as FindBugs are good at warning about the kind >> of errors >> mentioned above, however since the code in question is usually >> still valid >> to the compiler, they are limited in what action they can take by >> default. >> >> A language change can combine the ability to avoid these errors >> entirely >> with a more expressive idiom, resulting in an increased signal to >> noise >> ratio for readers of that code. >> >> >> >> EXAMPLES >> >> SIMPLE EXAMPLE: Show the simplest possible program utilizing the new >> feature. >> >> class C { >> int i; >> C(int this.i) {} >> } >> >> >> ADVANCED EXAMPLE: Show advanced usage(s) of the feature. >> >> >> class Proposal { >> >> private final String name; >> private final String author; >> private boolean suitableForCoin; >> private Integer score; >> >> public Proposal(String this.name, >> String this.author, >> boolean this.suitableForCoin, >> int this.score) { >> >> if (name.equals(?Auto-assignment Parameters?)) { >> suitableForCoin = true; // final so compile-time error >> } >> } >> >> // rest of class ... >> } >> >> >> >> DETAILS >> >> >> SPECIFICATION: Describe how the proposal affects the grammar, type >> system, >> and meaning of expressions and statements in the Java Programming >> Language >> as well as any other known impacts. >> >> The syntactic grammar is modified to include auto-assignment >> parameters for >> constructors: >> >> ConstructorDeclaratorRest: >> ConstructorParameters [throws >> QualifiedIdentifierList] >> MethodBody >> >> ConstructorParameters: >> ( [ConstructorParameterDecls] ) >> >> ConstructorParameterDecls: >> [final] [Annotations] Type >> ConstructorParameterDeclsRest >> >> ConstructorParameterDeclsRest: >> ConstructorParameterId [ , >> ConstructorParameterDecls] >> ... ConstructorParameterId >> >> ConstructorParameterId: >> VariableDeclaratorId >> this . VariableDeclaratorId >> super . VariableDeclaratorId >> >> An auto-assignment parameter is a formal parameter (JLSv3 ?8.4.1) >> which >> specifies an instance field instead of an identifier. Its value is >> automatically assigned to the specified field. It may only be >> used in a >> constructor. >> >> The automatic assignment takes place after any explicit or implicit >> invocation of another constructor, and before any statements in >> the body of >> the constructor. A constructor which declares n auto-assignment >> parameters >> will perform n such automatic assignments, in the order that the >> parameters >> are declared. >> >> The parameter has the same name (JLSv3 ?6.2) as the field to which >> it is >> assigned; replacing each auto-assignment parameter with a normal >> formal >> parameter with the same name would yield a constructor with an >> identical >> signature. As with a normal parameter, the parameter's name is >> entered into >> the scope of the constructor body (JLSv3 ?6.3), and therefore >> shadows the >> field (JLSv3 ?6.3.1) within that scope. >> >> It is a compile-time error if the field is not accessible from the >> constructor in which the parameter appears. >> >> It is a compile-time error if the declared type of the parameter >> is not >> assignment compatible (JLSv3 ?5.2) with the field to which it is >> automatically assigned. >> >> If an unboxing conversion is required by an automatic assignment, any >> NullPointerException thrown as a result (JLSv3 ?5.1.8) will >> contain the name >> of the field on which the conversion failed, which may be >> retrieved by >> calling getMessage() on the exception. >> >> Auto-assignment parameters are implicitly final, and follow the >> standard >> rules for final variables (JLSv3 ?4.12.4). Explicitly declaring an >> auto-assignment parameter as final has no effect, and does not >> cause a >> compilation error. >> >> Auto-assignment parameters follow the standard definite assignment >> rules for >> formal parameters (JLSv3 ?16.3). >> >> An auto-assignment parameter may be annotated. >> >> If an auto-assignment parameter is the last parameter in the list, >> and >> refers to a field of array type, it may be a variable arity >> parameter. >> >> >> >> COMPILATION: How would the feature be compiled to class files? >> Show how the >> simple and advanced examples would be compiled. Compilation can be >> expressed >> as at least one of a desugaring to existing source constructs and a >> translation down to bytecode. If a new bytecode is used or the >> semantics of >> an existing bytecode are changed, describe those changes, >> including how they >> impact verification. Also discuss any new class file attributes >> that are >> introduced. Note that there are many downstream tools that consume >> class >> files and that they may to be updated to support the proposal! >> >> Desugaring of the following class: >> >> class Foo { >> int value; >> Foo(Integer this.value) { >> System.out.println(value); >> } >> } >> >> would result in (unboxing desugaring omitted): >> >> class Foo { >> int value; >> Foo(final Integer value) { >> super(); >> if (value == null) >> throw new NullPointerException("value"); >> this.value = value; >> System.out.println(value); >> } >> } >> >> No changes to the classfile format are required. Tools which >> consume class >> files see the constructor signature as though it had been written >> using >> normal formal parameters. >> >> >> TESTING: How can the feature be tested? >> >> An initial set of jtreg tests is included in the prototype. >> >> >> LIBRARY SUPPORT: Are any supporting libraries needed for the feature? >> >> No >> >> >> REFLECTIVE APIS: Do any of the various and sundry reflection APIs >> need to be >> updated? This list of reflective APIs includes but is not limited >> to core >> reflection (java.lang.Class and java.lang.reflect.*), >> javax.lang.model.*, >> the doclet API, and JPDA. >> >> com.sun.source.tree.VariableTree would require an additional >> method which >> returns the auto-assigned field. >> >> >> OTHER CHANGES: Do any other parts of the platform need be updated >> too? >> Possibilities include but are not limited to JNI, serialization, >> and output >> of the javadoc tool. >> >> No >> >> >> MIGRATION: Sketch how a code base could be converted, manually or >> automatically, to use the new feature. >> >> Assignment statements in constructors for which all of the >> following are >> true can be considered suitable for conversion: >> * the lhs of the assignment is a non-static field >> * the rhs is a parameter with the same name as the field >> * there are no other assignments to the parameter anywhere in >> the >> constructor >> * there are no assignments to, or other uses of the field >> before the >> assignment statement in question (including invoked constructors) >> >> Such statements can be converted by: >> 1) replacing the parameter with an auto-assignment parameter >> (prefixing >> the existing parameter's identifier with 'this.'), and >> 2) removing the assignment statement >> >> >> >> COMPATIBILITY >> >> BREAKING CHANGES: Are any previously valid programs now invalid? >> If so, list >> one. >> >> No >> >> >> EXISTING PROGRAMS: How do source and class files of earlier platform >> versions interact with the feature? Can any new overloadings >> occur? Can any >> new overriding occur? >> >> The semantics of existing class files and legal source files are >> unchanged >> by this feature. >> >> >> >> REFERENCES >> >> EXISTING BUGS: Please include a list of any existing Sun bug ids >> related to >> this proposal. >> >> http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6582394 >> (uses a 'setter' method rather than a constructor in its example) >> >> FindBugs bug patterns - http://findbugs.sourceforge.net/ >> bugDescriptions.html >> * Self assignment of field (SA_FIELD_SELF_ASSIGNMENT) >> * Self comparison of field with itself (SA_FIELD_SELF_COMPARISON) >> * Nonsensical self computation involving a field (e.g., x & x) >> (SA_FIELD_SELF_COMPUTATION) >> * Self assignment of local variable (SA_LOCAL_SELF_ASSIGNMENT) >> * Nonsensical self computation involving a variable (e.g., x & x) >> (SA_LOCAL_SELF_COMPUTATION) >> * Uninitialized read of field in constructor (UR_UNINIT_READ) >> * Unwritten field (UWF_UNWRITTEN_FIELD) >> * Dead store to local variable (DLS_DEAD_LOCAL_STORE) >> * Dead store of null to local variable (DLS_DEAD_LOCAL_STORE_OF_NULL) >> >> >> >> URL FOR PROTOTYPE (optional): >> >> http://slm888.com/javac >> >> >> >> DESIGN ALTERNATIVES: >> >> The following variations have been explored and are worth mentioning: >> >> * Allow auto-assignment parameters on all non-abstract methods. >> This may be especially useful on the extremely common 'setter' >> methods >> in 'value object' classes. >> >> * Remove the requirement for (or even disallow) the type to be >> specified on >> auto-assignment parameters. >> Experimentation with this idea suggests that it may work quite >> well for >> constructors, further emphasising the difference in intent and >> semantics >> from those of normal parameters. However, it may not work so well in >> combination with auto-assignment parameters on all non-abstract >> methods, and >> requires a change to the order in which javac compiles classes >> (can still >> pass jtreg tests). >> >> * Allow an alternative name to be specified. >> This adds additional complexity to support a fractional >> percentage of >> cases, which could continue to use the existing coding pattern. >> >> > From howard.lovatt at iee.org Sat May 9 15:40:02 2009 From: howard.lovatt at iee.org (Howard Lovatt) Date: Sun, 10 May 2009 08:40:02 +1000 Subject: PROPOSAL: Abstract enums (version 2) In-Reply-To: <63b4e4050905080434j112605fch6b30baa9328fdff3@mail.gmail.com> References: <3dd3f56a0905072251l427e9c8y24098e9233af1d99@mail.gmail.com> <63b4e4050905080434j112605fch6b30baa9328fdff3@mail.gmail.com> Message-ID: <3dd3f56a0905091540p70f98e24hf359e4bf1845f439@mail.gmail.com> Yes a single element enum is a great singleton. Instead of: I was proposing shorter syntax, e.g.: enum Singleton { INSTANCE; void method() { ... } ... } I was proposing shorter syntax, e.g.: enum Singleton { // No INSTANCE void method() { ... } ... } Usage: Singleton.method(); Note usage without reference to INSTANCE. To make this really powerful you need to be able to extend an arbitrary class. I should have given an example to prevent the confusion - my fault :( -- Howard. 2009/5/8 Tim Peierls : > On Fri, May 8, 2009 at 1:51 AM, Howard Lovatt wrote: >> >> Further it would?be nice if you could make a singleton by having a enum >> with *no*?members. > > I don't understand what you mean here. A one element enum makes a great > singleton. (Effective Java 2nd ed., Item 3.) > --tim > ______________________________________________________________________ > This email has been scanned by the MessageLabs Email Security System. > For more information please visit http://www.messagelabs.com/email > ______________________________________________________________________ > -- -- Howard. From Thomas.Hawtin at Sun.COM Mon May 11 04:25:48 2009 From: Thomas.Hawtin at Sun.COM (Tom Hawtin) Date: Mon, 11 May 2009 12:25:48 +0100 Subject: PROPOSAL: Abstract enums (version 2) In-Reply-To: <3dd3f56a0905091540p70f98e24hf359e4bf1845f439@mail.gmail.com> References: <3dd3f56a0905072251l427e9c8y24098e9233af1d99@mail.gmail.com> <63b4e4050905080434j112605fch6b30baa9328fdff3@mail.gmail.com> <3dd3f56a0905091540p70f98e24hf359e4bf1845f439@mail.gmail.com> Message-ID: <4A080B3C.5040106@sun.com> Howard Lovatt wrote: > Yes a single element enum is a great singleton. Instead of: "Great singleton" is probably an oxymoron. > enum Singleton { > // No INSTANCE > void method() { ... } > ... > } I think for grammatical reasons you'll need to retain the semicolon. > Usage: > > Singleton.method(); If you add static to the method declaration, you are already there. Of couse still have the problem that you have introduced a load of inappropriate methods via enum. Tom Hawtin From howard.lovatt at iee.org Mon May 11 19:41:16 2009 From: howard.lovatt at iee.org (Howard Lovatt) Date: Tue, 12 May 2009 12:41:16 +1000 Subject: PROPOSAL: Abstract enums (version 2) Message-ID: <3dd3f56a0905111941w29fc3ec9wac0d1f5a7ba664d4@mail.gmail.com> Tom Hawtin wrote: >> Yes a single element enum is a great singleton. Instead of: > > "Great singleton" is probably an oxymoron. I find a limited set of instances, enums, useful and the singleton is just the limit of that concept. >> enum Singleton { >> ?// No INSTANCE >> ?void method() { ... } >> ?... >> } > > I think for grammatical reasons you'll need to retain the semicolon. Can you expand on this, you are probably right if looked at the grammar closely but I can't see where the problem is from a quick look - I would be interested to know where the problem is. >> Usage: >> >> Singleton.method(); > > If you add static to the method declaration, you are already there. Of couse still have the problem that you have introduced a load > of inappropriate methods via enum. I am wanting the enum to conform to an arbitrary, or at least near arbitrary, interface and/or abstract class. Therefore these need to be instance methods, not statics. As an aside, this is how Scala and Fortress are able to deal with statics in a strictly OO manor by having a singleton, which in the case of these two languages uses the object keyword to make exactly one instance of the class. I am proposing a similar solution for Java, but utilising an extension of the enum construct. You can't have a static and an instance method with the same signature, therefore I don't think the call Singleton.method() will be confusing to people or the compiler. -- Howard. From tim at peierls.net Mon May 11 21:30:03 2009 From: tim at peierls.net (Tim Peierls) Date: Tue, 12 May 2009 00:30:03 -0400 Subject: PROPOSAL: Abstract enums (version 2) In-Reply-To: <3dd3f56a0905111941w29fc3ec9wac0d1f5a7ba664d4@mail.gmail.com> References: <3dd3f56a0905111941w29fc3ec9wac0d1f5a7ba664d4@mail.gmail.com> Message-ID: <63b4e4050905112130t90e07f7i96f4782f0e0f2bcb@mail.gmail.com> It just doesn't seem worth the pain of a language change to me. If I were ever really at a loss for a name for the singleton instance, I could go minimal. enum SingletonEnum { _; void method() { System.out.println("method called"); } public static void main(String... args) { SingletonEnum._.method(); } } Or "THE", or "IT". But usually there's a natural name: // Socratic singletons enum Good { KNOWLEDGE; ... } enum Evil { IGNORANCE; ... } --tim On Mon, May 11, 2009 at 10:41 PM, Howard Lovatt wrote: > Tom Hawtin wrote: > >> Yes a single element enum is a great singleton. Instead of: > > > > "Great singleton" is probably an oxymoron. > > I find a limited set of instances, enums, useful and the singleton is > just the limit of that concept. > > >> enum Singleton { > >> // No INSTANCE > >> void method() { ... } > >> ... > >> } > > > > I think for grammatical reasons you'll need to retain the semicolon. > > Can you expand on this, you are probably right if looked at the > grammar closely but I can't see where the problem is from a quick look > - I would be interested to know where the problem is. > > >> Usage: > >> > >> Singleton.method(); > > > > If you add static to the method declaration, you are already there. Of > couse still have the problem that you have introduced a load > > of inappropriate methods via enum. > > I am wanting the enum to conform to an arbitrary, or at least near > arbitrary, interface and/or abstract class. Therefore these need to be > instance methods, not statics. As an aside, this is how Scala and > Fortress are able to deal with statics in a strictly OO manor by > having a singleton, which in the case of these two languages uses the > object keyword to make exactly one instance of the class. I am > proposing a similar solution for Java, but utilising an extension of > the enum construct. > > You can't have a static and an instance method with the same > signature, therefore I don't think the call Singleton.method() will be > confusing to people or the compiler. > > -- Howard. > > From howard.lovatt at iee.org Mon May 11 22:08:22 2009 From: howard.lovatt at iee.org (Howard Lovatt) Date: Tue, 12 May 2009 15:08:22 +1000 Subject: PROPOSAL: Abstract enums (version 2) In-Reply-To: <63b4e4050905112130t90e07f7i96f4782f0e0f2bcb@mail.gmail.com> References: <3dd3f56a0905111941w29fc3ec9wac0d1f5a7ba664d4@mail.gmail.com> <63b4e4050905112130t90e07f7i96f4782f0e0f2bcb@mail.gmail.com> Message-ID: <3dd3f56a0905112208m4cd0728dk8c88402c96e86b9d@mail.gmail.com> Hi Tim, 2009/5/12 Tim Peierls : > It just doesn't seem worth the pain of a language change to me. If I were > ever really at a loss for a name for the singleton instance, I could go > minimal. > enum SingletonEnum { > ?? ?_; > ?? ?void method() { System.out.println("method called"); } > ?? ?public static void main(String... args) { > ?? ? ? ?SingletonEnum._.method(); > ?? ?} > } > Or "THE", or "IT". But usually there's a natural name: > // Socratic singletons > enum Good { KNOWLEDGE; ... } > enum Evil { IGNORANCE; ... } I was probably in your camp until I started to use Scala and I found the object construct and the concept of a closed set of instances most useful. Since using a Scala a bit I think the construct is worth while. Have you used Scala or some other language with this construct? -- Howard. From tim at peierls.net Tue May 12 06:05:18 2009 From: tim at peierls.net (Tim Peierls) Date: Tue, 12 May 2009 09:05:18 -0400 Subject: PROPOSAL: Abstract enums (version 2) In-Reply-To: <3dd3f56a0905112208m4cd0728dk8c88402c96e86b9d@mail.gmail.com> References: <3dd3f56a0905111941w29fc3ec9wac0d1f5a7ba664d4@mail.gmail.com> <63b4e4050905112130t90e07f7i96f4782f0e0f2bcb@mail.gmail.com> <3dd3f56a0905112208m4cd0728dk8c88402c96e86b9d@mail.gmail.com> Message-ID: <63b4e4050905120605l33081192h5506a38415e34a95@mail.gmail.com> I'm saying I am not in favor of a change to the Java language that would make Foo.bar() a shorthand for something like Foo.$synthetic$.bar() when Foo is an enum with no members. I think it would encourage people to write confusing and hard to maintain code in exchange for the minor and doubtful benefit of slightly more compact code. What if your singleton turned out not to be a singleton? If you had implemented it as an enum with one member, no problem: just add another member. If you had implemented it as an enum with no members, you'd have to go back and change all uses of that enum. --tim On Tue, May 12, 2009 at 1:08 AM, Howard Lovatt wrote: > Hi Tim, > > 2009/5/12 Tim Peierls : > > It just doesn't seem worth the pain of a language change to me. If I were > > ever really at a loss for a name for the singleton instance, I could go > > minimal. > > enum SingletonEnum { > > _; > > void method() { System.out.println("method called"); } > > public static void main(String... args) { > > SingletonEnum._.method(); > > } > > } > > Or "THE", or "IT". But usually there's a natural name: > > // Socratic singletons > > enum Good { KNOWLEDGE; ... } > > enum Evil { IGNORANCE; ... } > > I was probably in your camp until I started to use Scala and I found > the object construct and the concept of a closed set of instances most > useful. Since using a Scala a bit I think the construct is worth > while. Have you used Scala or some other language with this construct? > > -- Howard. > From howard.lovatt at iee.org Tue May 12 17:35:17 2009 From: howard.lovatt at iee.org (Howard Lovatt) Date: Wed, 13 May 2009 10:35:17 +1000 Subject: PROPOSAL: Abstract enums (version 2) In-Reply-To: <63b4e4050905120605l33081192h5506a38415e34a95@mail.gmail.com> References: <3dd3f56a0905111941w29fc3ec9wac0d1f5a7ba664d4@mail.gmail.com> <63b4e4050905112130t90e07f7i96f4782f0e0f2bcb@mail.gmail.com> <3dd3f56a0905112208m4cd0728dk8c88402c96e86b9d@mail.gmail.com> <63b4e4050905120605l33081192h5506a38415e34a95@mail.gmail.com> Message-ID: <3dd3f56a0905121735q4516de9fu21b1a1d8dbcb5448@mail.gmail.com> On a pragmatic point, I doubt if the proposal will go anywhere since no one is supporting it except me :( The point you make about wanting to change from a singleton to a number of instances in the future might be valid, but I haven't personally had this problem in using Scala and I haven't heard of others having problems in Scala. The main enhancement I would find useful is to be able to extend an arbitrary abstract class when making an enum. The present proposal of a special abstract enum wouldn't help my use cases much. Therefore I don't thing the Singleton variation is that important. 2009/5/12 Tim Peierls : > I'm saying I am not in favor of a change to the Java language that would > make Foo.bar() a shorthand for something like Foo.$synthetic$.bar() when Foo > is an enum with no members. I think it would encourage people to write > confusing and hard to maintain code in exchange for the minor and doubtful > benefit of slightly more compact code. What if your singleton turned out not > to be a singleton? If you had implemented it as an enum with one member, no > problem: just add another member. If you had implemented it as an enum with > no members, you'd have to go back and change all uses of that enum. > --tim > > On Tue, May 12, 2009 at 1:08 AM, Howard Lovatt > wrote: >> >> Hi Tim, >> >> 2009/5/12 Tim Peierls : >> > It just doesn't seem worth the pain of a language change to me. If I >> > were >> > ever really at a loss for a name for the singleton instance, I could go >> > minimal. >> > enum SingletonEnum { >> > ?? ?_; >> > ?? ?void method() { System.out.println("method called"); } >> > ?? ?public static void main(String... args) { >> > ?? ? ? ?SingletonEnum._.method(); >> > ?? ?} >> > } >> > Or "THE", or "IT". But usually there's a natural name: >> > // Socratic singletons >> > enum Good { KNOWLEDGE; ... } >> > enum Evil { IGNORANCE; ... } >> >> I was probably in your camp until I started to use Scala and I found >> the object construct and the concept of a closed set of instances most >> useful. Since using a Scala a bit I think the construct is worth >> while. Have you used Scala or some other language with this construct? >> >> ?-- Howard. > > > ______________________________________________________________________ > This email has been scanned by the MessageLabs Email Security System. > For more information please visit http://www.messagelabs.com/email > ______________________________________________________________________ > -- -- Howard. From Joe.Darcy at Sun.COM Tue May 12 17:47:04 2009 From: Joe.Darcy at Sun.COM (Joe Darcy) Date: Tue, 12 May 2009 17:47:04 -0700 Subject: PROPOSAL: Unchecked Exceptions as Subclasses of Checked Exceptions In-Reply-To: <56957.69.239.104.86.1237951010.squirrel@69.239.104.86> References: <56957.69.239.104.86.1237951010.squirrel@69.239.104.86> Message-ID: <4A0A1888.1010103@sun.com> Catching up on proposal email, I agree with the observation from Reinier Zwitserloot that there would be adverse behavioral compatibility consequences for this change since a common idiom for checking for a throwable that was not a checked exception would fail. Additionally, I don't find the motivating example very compelling. Regards, -Joe Alan Snyder wrote: > Unchecked Exceptions as Subclasses of Checked Exceptions > > > AUTHOR: Alan Snyder > > OVERVIEW > > FEATURE SUMMARY: > > This proposal would allow the definition of an unchecked exception class > that extends a checked exception class. > > MAJOR ADVANTAGE: > > Unchecked exception classes are useful when an exception must be thrown > through an existing interface > that does not declare any checked exceptions or an appropriate checked > exception. > If one can define both an unchecked exception class and a > corresponding checked exception class such that the unchecked exception > class extends the checked exception class, > then the unchecked exception will be caught by a try statement that > catches the checked exception. > > MAJOR BENEFIT: > > Programs do not have to explictly catch both the unchecked and checked > exceptions. Most developers need > only be aware of the checked exception. > > MAJOR DISADVANTAGE: > > A new marker interface (or equivalent) must be defined and the definition > of unchecked exceptions changed. > > ALTERNATIVES: > > The alternative is to always explicitly catch both the unchecked and > checked exceptions, which introduces > a likely source of programming errors. > > EXAMPLE: > > This proposal uses a marker interface as an alternative way (besides > subclassing RuntimeException and Error) > of indicating that an exception class defines an unchecked exception. > > The following would define a checked exception and an unchecked exception > that extends the checked exception: > > public class TheCheckedException extends Exception {}; > > public class TheUncheckedException extends TheCheckedException implements > UncheckedException {}; > > There is no advanced usage. > > DETAILS > > SPECIFICATION: > > The JLS would be changed to add one more way to define an unchecked > exception. > > JLS 11.2 > The unchecked exceptions classes are the class RuntimeException and its > subclasses, and the class Error and its subclasses. > All other exception classes are checked exception classes. > > would become > > The unchecked exceptions classes are the class RuntimeException and its > subclasses, the class Error and its subclasses, > and those subclasses of Exception that implement the UncheckedException > interface. > All other exception classes are checked exception classes. > > JLS 11.5 > The subclasses of Exception other than RuntimeException are all checked > exception classes. > > would become > > The subclasses of Exception other than RuntimeException are checked > exception classes, unless they implement the UncheckedException interface. > > The marker interface UncheckedException would have to be defined in some > java package, with java.lang being the obvious choice. > > COMPILATION: > > The compiler would have to be extended to recognize the new category of > unchecked exceptions. > > I'm not aware of other changes. > > COMPATIBILITY > > The major compatibility issue arises from the introduction of a new name > in the class name space. That could potentially cause a program > to fail to compile if it imported a class with the name UncheckedException > using a wild card import statement. > > There could also be programs that examine the class hierarchy using > reflection that would not recognize some exception classes as being > unchecked. > > > From Joe.Darcy at Sun.COM Tue May 12 18:00:19 2009 From: Joe.Darcy at Sun.COM (Joe Darcy) Date: Tue, 12 May 2009 18:00:19 -0700 Subject: PROPOSAL: Improved Support for Optional Object Behaviors at Runtime In-Reply-To: <61117.69.239.104.86.1238094535.squirrel@69.239.104.86> References: <61117.69.239.104.86.1238094535.squirrel@69.239.104.86> Message-ID: <4A0A1BA3.7050801@sun.com> Catching up on proposal email, while adding a non-final method to Object would be binary compatible, it would have source compatibility effects of unknown magnitude. Adding methods to Object should only be done in extreme circumstances I don't see the problem being addressed as being sufficiently serious to contemplate changing Object as a solution. -Joe Alan Snyder wrote: > Improved Support for Optional Object Behaviors at Runtime > > > AUTHOR: Alan Snyder > > OVERVIEW > > FEATURE SUMMARY: > > This proposal would add a method to class Object to allow runtime access > to optional object behaviors. > > MAJOR ADVANTAGE: > > As designs evolve and become more complex, it is useful to split out > separable chunks of behavior whose support by an object might be optional. > In current Java, the universally applicable technique for testing for and > making use of optional behavior is the type cast. The type cast is limited > by its tight coupling with the type hierarchy; as a result, because Java > has single class inheritance, a class can not support an optional behavior > defined by another class that is not already in its class hierarchy. In > addition, because type casts cannot be simulated by an object, it is not > compatible with delegation. For an object implemented by delegation to > support optional behaviors using type casts, there would need to be one > delegating class for each possible combination of optional behaviors. > > This proposal defines a method on class Object that can be used in place > of type casts to test for and access optional behaviors. This proposal is > not constrained by the type hierarchy of the target object, because it > permits the optional behavior to be implemented using a different (but > related) object. In addition, the determination of the available behaviors > can be made dynamically. Specifically, this proposal allows a class > implemented using delegation to mimic the set of optional behaviors > supported by its delegate, even if the delegate is replaceable. > > MAJOR BENEFIT: > > By adding a method to class Object, this feature can be supported by any > class, even existing Java platform classes, with no additional changes to > their class hierarchies. Because the feature is universally available, the > use of type casts for this purpose can be deprecated. > > This technique can be used to simply interfaces, or avoid making them more > complex. > > MAJOR DISADVANTAGE: > > Any change to class Object freaks people out. This is the only change I > can think of that is so obviously universal that it deserves to be in > class Object. > > ALTERNATIVES: > > One alternative is to define this method in a new interface. This > disadvantage of defining a new interface is that existing classes and > interfaces would not support the method without themselves being changed. > The other alternative is to add this method to classes and interfaces on > an as needed basis. Either alternative forces programmers to use type > casts in those cases where this method was not available. Also, new > implementations of unchanged classes and interfaces would not be able to > support this feature for existing clients of those classes and interfaces. > > EXAMPLE: > > Suppose a program wants to test an object "o" at runtime for an optional > behavior defined by a class or interface "T". In current Java, the program > could write: > > try { > T t = (T) o; > ... use t ... > } catch (ClassCastException ex) { > } > > Using the proposed feature, the program would write: > > T t = o.getExtension(T.class); > if (t != null) { > ... use t ... > } > > The following examples are all hypothetical, but plausible to varying > degrees. Note that many of them use instances of existing platform > classes. > > // Test a list to see if it is observable, and get access > // to the observable methods. > > Observable o = list.getExtension(Observable.class); > > // Test a file to see if supports metadata, and get access > // to the metadata methods. > > FileMetadata fm = file.getExtension(FileMetadata.class); > > // Test file metadata to see if Mac OS file metadata is > // supported. Note that the file might be on another > // machine, so this call might succeed even on a non-Mac system. > > MacOSFileMetadata mfm = fm.getExtension(MacOSFileMetadata.class); > > // Test a file to see if it supports the new File API. > // Note that using this approach the new File API does > // not have to be an extension of the old API. > > java.nio.File nf = file.getExtension(java.nio.File.class); > > // Test a file to see if it is a directory, and get access to > // the directory methods. > > Directory dir = file.getExtension(Directory.class); > > // Test a file to see if it is a symlink, and get access to > // the symlink methods. > > Symlink s = file.getExtension(Symlink.class); > > // Test a file to see if it a directory and whether it provides > // read and update access to the directory contents using the > // List API (!). > > List fs = (List) file.getExtension(List.class); > > DETAILS > > The default definition in class Object would be: > > public T getExtension(Class c) > { > try { > return (T) this; > } catch (ClassCastException ex) { > return null; > } > } > > Thus, if not overridden, the method has the same effect as the type cast. > Thus it can be used in place of type casts even on instances of existing > classes. > > Once this method is in place, programmers should be discouraged from using > type casts for the purpose of testing for optional behavior. > > SPECIFICATION: > > JLS 4.3.2 would be changed to define this method. > > I'm not aware of other changes. > > MIGRATION: > > It would be advisable to convert appropriate type casts to invocations of > this method in existing code. > > Once this method is available in class Object, other Java platform classes > and APIs can be changed to take advantage of it. > > COMPATIBILITY > > BREAKING CHANGES: > > No matter what name is chosen for this method, some existing program could > fail to compile if it defines a method with the same name and signature > but (say) a different return type. Methods with class parameters are > presumably uncommon. > > According to JLS 13.4.12, binary compatibility should not be broken > because the method is public. > > EXISTING PROGRAMS: > > Existing classes automatically support this method to the same extent that > they current support type casts for accessing optional behavior. > > > From schulz at e-Spirit.de Tue May 12 23:00:13 2009 From: schulz at e-Spirit.de (Schulz, Stefan) Date: Wed, 13 May 2009 08:00:13 +0200 Subject: PROPOSAL: Improved Support for Optional Object Behaviors atRuntime In-Reply-To: <4A0A1BA3.7050801@sun.com> References: <61117.69.239.104.86.1238094535.squirrel@69.239.104.86> <4A0A1BA3.7050801@sun.com> Message-ID: <7D2077BFF677D2429DDDEE095D9A48AC1130C575@osiris2.e-spirit.de> I think this is an unfortunate decision, as the proposal would have provided an API-based alternative to language constructs like multiple inheritance, mixins, and delegation, none of which will be possible to add to Java in a reasonable way. The suggestion I had with using some SuperTypeToken instead of classes directly (if it had been taken into the proposal) would have raised no compatibility issues, either, as the signature would have been new and unique, and it further would have allowed parameterized classes as well. The main question to me is, whether this is a language change issue at all, as it only touches API. Any recommendation about filing this proposal to the respective API change project? (If I remember correctly, Joe mentioned such a project to be set up. Although, I could not find it up to now.) Stefan > -----Original Message----- > From: coin-dev-bounces at openjdk.java.net > [mailto:coin-dev-bounces at openjdk.java.net] On Behalf Of Joe Darcy > Sent: Wednesday, May 13, 2009 3:00 AM > To: Alan Snyder > Cc: coin-dev at openjdk.java.net > Subject: Re: PROPOSAL: Improved Support for Optional Object > Behaviors atRuntime > > Catching up on proposal email, while adding a non-final > method to Object > would be binary compatible, it would have source > compatibility effects > of unknown magnitude. Adding methods to Object should only > be done in > extreme circumstances I don't see the problem being addressed > as being > sufficiently serious to contemplate changing Object as a solution. > > -Joe > > Alan Snyder wrote: > > Improved Support for Optional Object Behaviors at Runtime > > > > > > AUTHOR: Alan Snyder > > > > OVERVIEW > > > > FEATURE SUMMARY: > > > > This proposal would add a method to class Object to allow > runtime access > > to optional object behaviors. > > > > MAJOR ADVANTAGE: > > > > As designs evolve and become more complex, it is useful to split out > > separable chunks of behavior whose support by an object > might be optional. > > In current Java, the universally applicable technique for > testing for and > > making use of optional behavior is the type cast. The type > cast is limited > > by its tight coupling with the type hierarchy; as a result, > because Java > > has single class inheritance, a class can not support an > optional behavior > > defined by another class that is not already in its class > hierarchy. In > > addition, because type casts cannot be simulated by an > object, it is not > > compatible with delegation. For an object implemented by > delegation to > > support optional behaviors using type casts, there would > need to be one > > delegating class for each possible combination of optional > behaviors. > > > > This proposal defines a method on class Object that can be > used in place > > of type casts to test for and access optional behaviors. > This proposal is > > not constrained by the type hierarchy of the target object, > because it > > permits the optional behavior to be implemented using a > different (but > > related) object. In addition, the determination of the > available behaviors > > can be made dynamically. Specifically, this proposal allows a class > > implemented using delegation to mimic the set of optional behaviors > > supported by its delegate, even if the delegate is replaceable. > > > > MAJOR BENEFIT: > > > > By adding a method to class Object, this feature can be > supported by any > > class, even existing Java platform classes, with no > additional changes to > > their class hierarchies. Because the feature is universally > available, the > > use of type casts for this purpose can be deprecated. > > > > This technique can be used to simply interfaces, or avoid > making them more > > complex. > > > > MAJOR DISADVANTAGE: > > > > Any change to class Object freaks people out. This is the > only change I > > can think of that is so obviously universal that it > deserves to be in > > class Object. > > > > ALTERNATIVES: > > > > One alternative is to define this method in a new interface. This > > disadvantage of defining a new interface is that existing > classes and > > interfaces would not support the method without themselves > being changed. > > The other alternative is to add this method to classes and > interfaces on > > an as needed basis. Either alternative forces programmers > to use type > > casts in those cases where this method was not available. Also, new > > implementations of unchanged classes and interfaces would > not be able to > > support this feature for existing clients of those classes > and interfaces. > > > > EXAMPLE: > > > > Suppose a program wants to test an object "o" at runtime > for an optional > > behavior defined by a class or interface "T". In current > Java, the program > > could write: > > > > try { > > T t = (T) o; > > ... use t ... > > } catch (ClassCastException ex) { > > } > > > > Using the proposed feature, the program would write: > > > > T t = o.getExtension(T.class); > > if (t != null) { > > ... use t ... > > } > > > > The following examples are all hypothetical, but plausible > to varying > > degrees. Note that many of them use instances of existing platform > > classes. > > > > // Test a list to see if it is observable, and get access > > // to the observable methods. > > > > Observable o = list.getExtension(Observable.class); > > > > // Test a file to see if supports metadata, and get access > > // to the metadata methods. > > > > FileMetadata fm = file.getExtension(FileMetadata.class); > > > > // Test file metadata to see if Mac OS file metadata is > > // supported. Note that the file might be on another > > // machine, so this call might succeed even on a non-Mac system. > > > > MacOSFileMetadata mfm = > fm.getExtension(MacOSFileMetadata.class); > > > > // Test a file to see if it supports the new File API. > > // Note that using this approach the new File API does > > // not have to be an extension of the old API. > > > > java.nio.File nf = file.getExtension(java.nio.File.class); > > > > // Test a file to see if it is a directory, and get access to > > // the directory methods. > > > > Directory dir = file.getExtension(Directory.class); > > > > // Test a file to see if it is a symlink, and get access to > > // the symlink methods. > > > > Symlink s = file.getExtension(Symlink.class); > > > > // Test a file to see if it a directory and whether it provides > > // read and update access to the directory contents using the > > // List API (!). > > > > List fs = (List) file.getExtension(List.class); > > > > DETAILS > > > > The default definition in class Object would be: > > > > public T getExtension(Class c) > > { > > try { > > return (T) this; > > } catch (ClassCastException ex) { > > return null; > > } > > } > > > > Thus, if not overridden, the method has the same effect as > the type cast. > > Thus it can be used in place of type casts even on > instances of existing > > classes. > > > > Once this method is in place, programmers should be > discouraged from using > > type casts for the purpose of testing for optional behavior. > > > > SPECIFICATION: > > > > JLS 4.3.2 would be changed to define this method. > > > > I'm not aware of other changes. > > > > MIGRATION: > > > > It would be advisable to convert appropriate type casts to > invocations of > > this method in existing code. > > > > Once this method is available in class Object, other Java > platform classes > > and APIs can be changed to take advantage of it. > > > > COMPATIBILITY > > > > BREAKING CHANGES: > > > > No matter what name is chosen for this method, some > existing program could > > fail to compile if it defines a method with the same name > and signature > > but (say) a different return type. Methods with class parameters are > > presumably uncommon. > > > > According to JLS 13.4.12, binary compatibility should not be broken > > because the method is public. > > > > EXISTING PROGRAMS: > > > > Existing classes automatically support this method to the > same extent that > > they current support type casts for accessing optional behavior. > > > > > > > > > > From Joe.Darcy at Sun.COM Tue May 12 23:53:06 2009 From: Joe.Darcy at Sun.COM (Joseph D. Darcy) Date: Tue, 12 May 2009 23:53:06 -0700 Subject: PROPOSAL: Improved Support for Optional Object Behaviors atRuntime In-Reply-To: <7D2077BFF677D2429DDDEE095D9A48AC1130C575@osiris2.e-spirit.de> References: <61117.69.239.104.86.1238094535.squirrel@69.239.104.86> <4A0A1BA3.7050801@sun.com> <7D2077BFF677D2429DDDEE095D9A48AC1130C575@osiris2.e-spirit.de> Message-ID: <4A0A6E52.100@sun.com> Schulz, Stefan wrote: > I think this is an unfortunate decision, as the proposal would have provided an API-based alternative to language constructs like multiple inheritance, mixins, and delegation, none of which will be possible to add to Java in a reasonable way. The And people are free to use that pattern in their own APIs without burdening all Java programmers and programs with a new method on java.lang.Object. > suggestion I had with using some SuperTypeToken instead of classes directly (if it had been taken into the proposal) would have raised no compatibility issues, either, as the signature would have been new and unique, and it further would have allowed parameterized classes as well. > > The main question to me is, whether this is a language change issue at all, as it only touches API. Changes to Object are special, but there is less of a language change component per se. > Any recommendation about filing this proposal to the respective API change project? (If I remember correctly, Joe mentioned such a project to be set up. Although, I could not find it up to now.) > There are plans for a separate process for API changes in JDK 7, but that has not been spun-up yet: http://mail.openjdk.java.net/pipermail/jdk7-dev/2009-February/000411.html -Joe > Stefan > > >> -----Original Message----- >> From: coin-dev-bounces at openjdk.java.net >> [mailto:coin-dev-bounces at openjdk.java.net] On Behalf Of Joe Darcy >> Sent: Wednesday, May 13, 2009 3:00 AM >> To: Alan Snyder >> Cc: coin-dev at openjdk.java.net >> Subject: Re: PROPOSAL: Improved Support for Optional Object >> Behaviors atRuntime >> >> Catching up on proposal email, while adding a non-final >> method to Object >> would be binary compatible, it would have source >> compatibility effects >> of unknown magnitude. Adding methods to Object should only >> be done in >> extreme circumstances I don't see the problem being addressed >> as being >> sufficiently serious to contemplate changing Object as a solution. >> >> -Joe >> >> Alan Snyder wrote: >> >>> Improved Support for Optional Object Behaviors at Runtime >>> >>> >>> AUTHOR: Alan Snyder >>> >>> OVERVIEW >>> >>> FEATURE SUMMARY: >>> >>> This proposal would add a method to class Object to allow >>> >> runtime access >> >>> to optional object behaviors. >>> >>> MAJOR ADVANTAGE: >>> >>> As designs evolve and become more complex, it is useful to split out >>> separable chunks of behavior whose support by an object >>> >> might be optional. >> >>> In current Java, the universally applicable technique for >>> >> testing for and >> >>> making use of optional behavior is the type cast. The type >>> >> cast is limited >> >>> by its tight coupling with the type hierarchy; as a result, >>> >> because Java >> >>> has single class inheritance, a class can not support an >>> >> optional behavior >> >>> defined by another class that is not already in its class >>> >> hierarchy. In >> >>> addition, because type casts cannot be simulated by an >>> >> object, it is not >> >>> compatible with delegation. For an object implemented by >>> >> delegation to >> >>> support optional behaviors using type casts, there would >>> >> need to be one >> >>> delegating class for each possible combination of optional >>> >> behaviors. >> >>> This proposal defines a method on class Object that can be >>> >> used in place >> >>> of type casts to test for and access optional behaviors. >>> >> This proposal is >> >>> not constrained by the type hierarchy of the target object, >>> >> because it >> >>> permits the optional behavior to be implemented using a >>> >> different (but >> >>> related) object. In addition, the determination of the >>> >> available behaviors >> >>> can be made dynamically. Specifically, this proposal allows a class >>> implemented using delegation to mimic the set of optional behaviors >>> supported by its delegate, even if the delegate is replaceable. >>> >>> MAJOR BENEFIT: >>> >>> By adding a method to class Object, this feature can be >>> >> supported by any >> >>> class, even existing Java platform classes, with no >>> >> additional changes to >> >>> their class hierarchies. Because the feature is universally >>> >> available, the >> >>> use of type casts for this purpose can be deprecated. >>> >>> This technique can be used to simply interfaces, or avoid >>> >> making them more >> >>> complex. >>> >>> MAJOR DISADVANTAGE: >>> >>> Any change to class Object freaks people out. This is the >>> >> only change I >> >>> can think of that is so obviously universal that it >>> >> deserves to be in >> >>> class Object. >>> >>> ALTERNATIVES: >>> >>> One alternative is to define this method in a new interface. This >>> disadvantage of defining a new interface is that existing >>> >> classes and >> >>> interfaces would not support the method without themselves >>> >> being changed. >> >>> The other alternative is to add this method to classes and >>> >> interfaces on >> >>> an as needed basis. Either alternative forces programmers >>> >> to use type >> >>> casts in those cases where this method was not available. Also, new >>> implementations of unchanged classes and interfaces would >>> >> not be able to >> >>> support this feature for existing clients of those classes >>> >> and interfaces. >> >>> EXAMPLE: >>> >>> Suppose a program wants to test an object "o" at runtime >>> >> for an optional >> >>> behavior defined by a class or interface "T". In current >>> >> Java, the program >> >>> could write: >>> >>> try { >>> T t = (T) o; >>> ... use t ... >>> } catch (ClassCastException ex) { >>> } >>> >>> Using the proposed feature, the program would write: >>> >>> T t = o.getExtension(T.class); >>> if (t != null) { >>> ... use t ... >>> } >>> >>> The following examples are all hypothetical, but plausible >>> >> to varying >> >>> degrees. Note that many of them use instances of existing platform >>> classes. >>> >>> // Test a list to see if it is observable, and get access >>> // to the observable methods. >>> >>> Observable o = list.getExtension(Observable.class); >>> >>> // Test a file to see if supports metadata, and get access >>> // to the metadata methods. >>> >>> FileMetadata fm = file.getExtension(FileMetadata.class); >>> >>> // Test file metadata to see if Mac OS file metadata is >>> // supported. Note that the file might be on another >>> // machine, so this call might succeed even on a non-Mac system. >>> >>> MacOSFileMetadata mfm = >>> >> fm.getExtension(MacOSFileMetadata.class); >> >>> // Test a file to see if it supports the new File API. >>> // Note that using this approach the new File API does >>> // not have to be an extension of the old API. >>> >>> java.nio.File nf = file.getExtension(java.nio.File.class); >>> >>> // Test a file to see if it is a directory, and get access to >>> // the directory methods. >>> >>> Directory dir = file.getExtension(Directory.class); >>> >>> // Test a file to see if it is a symlink, and get access to >>> // the symlink methods. >>> >>> Symlink s = file.getExtension(Symlink.class); >>> >>> // Test a file to see if it a directory and whether it provides >>> // read and update access to the directory contents using the >>> // List API (!). >>> >>> List fs = (List) file.getExtension(List.class); >>> >>> DETAILS >>> >>> The default definition in class Object would be: >>> >>> public T getExtension(Class c) >>> { >>> try { >>> return (T) this; >>> } catch (ClassCastException ex) { >>> return null; >>> } >>> } >>> >>> Thus, if not overridden, the method has the same effect as >>> >> the type cast. >> >>> Thus it can be used in place of type casts even on >>> >> instances of existing >> >>> classes. >>> >>> Once this method is in place, programmers should be >>> >> discouraged from using >> >>> type casts for the purpose of testing for optional behavior. >>> >>> SPECIFICATION: >>> >>> JLS 4.3.2 would be changed to define this method. >>> >>> I'm not aware of other changes. >>> >>> MIGRATION: >>> >>> It would be advisable to convert appropriate type casts to >>> >> invocations of >> >>> this method in existing code. >>> >>> Once this method is available in class Object, other Java >>> >> platform classes >> >>> and APIs can be changed to take advantage of it. >>> >>> COMPATIBILITY >>> >>> BREAKING CHANGES: >>> >>> No matter what name is chosen for this method, some >>> >> existing program could >> >>> fail to compile if it defines a method with the same name >>> >> and signature >> >>> but (say) a different return type. Methods with class parameters are >>> presumably uncommon. >>> >>> According to JLS 13.4.12, binary compatibility should not be broken >>> because the method is public. >>> >>> EXISTING PROGRAMS: >>> >>> Existing classes automatically support this method to the >>> >> same extent that >> >>> they current support type casts for accessing optional behavior. >>> >>> >>> >>> >> >> >> From schulz at e-Spirit.de Wed May 13 00:46:16 2009 From: schulz at e-Spirit.de (Schulz, Stefan) Date: Wed, 13 May 2009 09:46:16 +0200 Subject: PROPOSAL: Improved Support for Optional Object Behaviors atRuntime In-Reply-To: <4A0A6E52.100@sun.com> References: <7D2077BFF677D2429DDDEE095D9A48AC1130C575@osiris2.e-spirit.de> <4A0A6E52.100@sun.com> Message-ID: <7D2077BFF677D2429DDDEE095D9A48AC1130C599@osiris2.e-spirit.de> Joe wrote: > Schulz, Stefan wrote: > And people are free to use that pattern in their own APIs without > burdening all Java programmers and programs with a new method on > java.lang.Object. Well, the reasons why this is not really a desired way to go are discussed in the alternative section of the proposal. A non-general API would force to use instanceof and casts before using the API, which is counterproductive with respect to its intend. > There are plans for a separate process for API changes in JDK 7, but > that has not been spun-up yet: > http://mail.openjdk.java.net/pipermail/jdk7-dev/2009-February/ > 000411.html Thanks for the hint. :) Alan: Are you up to re-file the proposal in case of such a process is set up? If so, let me know, whether you think the proposal would benefit of my suggestions wrt. SuperTypeToken. Cheers, Stefan > >> -----Original Message----- > >> From: coin-dev-bounces at openjdk.java.net > >> [mailto:coin-dev-bounces at openjdk.java.net] On Behalf Of Joe Darcy > >> Sent: Wednesday, May 13, 2009 3:00 AM > >> To: Alan Snyder > >> Cc: coin-dev at openjdk.java.net > >> Subject: Re: PROPOSAL: Improved Support for Optional Object > >> Behaviors atRuntime > >> > >> Catching up on proposal email, while adding a non-final > >> method to Object > >> would be binary compatible, it would have source > >> compatibility effects > >> of unknown magnitude. Adding methods to Object should only > >> be done in > >> extreme circumstances I don't see the problem being addressed > >> as being > >> sufficiently serious to contemplate changing Object as a solution. > >> > >> -Joe > >> > >> Alan Snyder wrote: > >> > >>> Improved Support for Optional Object Behaviors at Runtime > >>> > >>> > >>> AUTHOR: Alan Snyder > >>> > >>> OVERVIEW > >>> > >>> FEATURE SUMMARY: > >>> > >>> This proposal would add a method to class Object to allow > >>> > >> runtime access > >> > >>> to optional object behaviors. > >>> > >>> MAJOR ADVANTAGE: > >>> > >>> As designs evolve and become more complex, it is useful > to split out > >>> separable chunks of behavior whose support by an object > >>> > >> might be optional. > >> > >>> In current Java, the universally applicable technique for > >>> > >> testing for and > >> > >>> making use of optional behavior is the type cast. The type > >>> > >> cast is limited > >> > >>> by its tight coupling with the type hierarchy; as a result, > >>> > >> because Java > >> > >>> has single class inheritance, a class can not support an > >>> > >> optional behavior > >> > >>> defined by another class that is not already in its class > >>> > >> hierarchy. In > >> > >>> addition, because type casts cannot be simulated by an > >>> > >> object, it is not > >> > >>> compatible with delegation. For an object implemented by > >>> > >> delegation to > >> > >>> support optional behaviors using type casts, there would > >>> > >> need to be one > >> > >>> delegating class for each possible combination of optional > >>> > >> behaviors. > >> > >>> This proposal defines a method on class Object that can be > >>> > >> used in place > >> > >>> of type casts to test for and access optional behaviors. > >>> > >> This proposal is > >> > >>> not constrained by the type hierarchy of the target object, > >>> > >> because it > >> > >>> permits the optional behavior to be implemented using a > >>> > >> different (but > >> > >>> related) object. In addition, the determination of the > >>> > >> available behaviors > >> > >>> can be made dynamically. Specifically, this proposal > allows a class > >>> implemented using delegation to mimic the set of optional > behaviors > >>> supported by its delegate, even if the delegate is replaceable. > >>> > >>> MAJOR BENEFIT: > >>> > >>> By adding a method to class Object, this feature can be > >>> > >> supported by any > >> > >>> class, even existing Java platform classes, with no > >>> > >> additional changes to > >> > >>> their class hierarchies. Because the feature is universally > >>> > >> available, the > >> > >>> use of type casts for this purpose can be deprecated. > >>> > >>> This technique can be used to simply interfaces, or avoid > >>> > >> making them more > >> > >>> complex. > >>> > >>> MAJOR DISADVANTAGE: > >>> > >>> Any change to class Object freaks people out. This is the > >>> > >> only change I > >> > >>> can think of that is so obviously universal that it > >>> > >> deserves to be in > >> > >>> class Object. > >>> > >>> ALTERNATIVES: > >>> > >>> One alternative is to define this method in a new interface. This > >>> disadvantage of defining a new interface is that existing > >>> > >> classes and > >> > >>> interfaces would not support the method without themselves > >>> > >> being changed. > >> > >>> The other alternative is to add this method to classes and > >>> > >> interfaces on > >> > >>> an as needed basis. Either alternative forces programmers > >>> > >> to use type > >> > >>> casts in those cases where this method was not available. > Also, new > >>> implementations of unchanged classes and interfaces would > >>> > >> not be able to > >> > >>> support this feature for existing clients of those classes > >>> > >> and interfaces. > >> > >>> EXAMPLE: > >>> > >>> Suppose a program wants to test an object "o" at runtime > >>> > >> for an optional > >> > >>> behavior defined by a class or interface "T". In current > >>> > >> Java, the program > >> > >>> could write: > >>> > >>> try { > >>> T t = (T) o; > >>> ... use t ... > >>> } catch (ClassCastException ex) { > >>> } > >>> > >>> Using the proposed feature, the program would write: > >>> > >>> T t = o.getExtension(T.class); > >>> if (t != null) { > >>> ... use t ... > >>> } > >>> > >>> The following examples are all hypothetical, but plausible > >>> > >> to varying > >> > >>> degrees. Note that many of them use instances of existing platform > >>> classes. > >>> > >>> // Test a list to see if it is observable, and get access > >>> // to the observable methods. > >>> > >>> Observable o = list.getExtension(Observable.class); > >>> > >>> // Test a file to see if supports metadata, and get access > >>> // to the metadata methods. > >>> > >>> FileMetadata fm = file.getExtension(FileMetadata.class); > >>> > >>> // Test file metadata to see if Mac OS file metadata is > >>> // supported. Note that the file might be on another > >>> // machine, so this call might succeed even on a non-Mac system. > >>> > >>> MacOSFileMetadata mfm = > >>> > >> fm.getExtension(MacOSFileMetadata.class); > >> > >>> // Test a file to see if it supports the new File API. > >>> // Note that using this approach the new File API does > >>> // not have to be an extension of the old API. > >>> > >>> java.nio.File nf = file.getExtension(java.nio.File.class); > >>> > >>> // Test a file to see if it is a directory, and get access to > >>> // the directory methods. > >>> > >>> Directory dir = file.getExtension(Directory.class); > >>> > >>> // Test a file to see if it is a symlink, and get access to > >>> // the symlink methods. > >>> > >>> Symlink s = file.getExtension(Symlink.class); > >>> > >>> // Test a file to see if it a directory and whether it provides > >>> // read and update access to the directory contents using the > >>> // List API (!). > >>> > >>> List fs = (List) file.getExtension(List.class); > >>> > >>> DETAILS > >>> > >>> The default definition in class Object would be: > >>> > >>> public T getExtension(Class c) > >>> { > >>> try { > >>> return (T) this; > >>> } catch (ClassCastException ex) { > >>> return null; > >>> } > >>> } > >>> > >>> Thus, if not overridden, the method has the same effect as > >>> > >> the type cast. > >> > >>> Thus it can be used in place of type casts even on > >>> > >> instances of existing > >> > >>> classes. > >>> > >>> Once this method is in place, programmers should be > >>> > >> discouraged from using > >> > >>> type casts for the purpose of testing for optional behavior. > >>> > >>> SPECIFICATION: > >>> > >>> JLS 4.3.2 would be changed to define this method. > >>> > >>> I'm not aware of other changes. > >>> > >>> MIGRATION: > >>> > >>> It would be advisable to convert appropriate type casts to > >>> > >> invocations of > >> > >>> this method in existing code. > >>> > >>> Once this method is available in class Object, other Java > >>> > >> platform classes > >> > >>> and APIs can be changed to take advantage of it. > >>> > >>> COMPATIBILITY > >>> > >>> BREAKING CHANGES: > >>> > >>> No matter what name is chosen for this method, some > >>> > >> existing program could > >> > >>> fail to compile if it defines a method with the same name > >>> > >> and signature > >> > >>> but (say) a different return type. Methods with class > parameters are > >>> presumably uncommon. > >>> > >>> According to JLS 13.4.12, binary compatibility should not > be broken > >>> because the method is public. > >>> > >>> EXISTING PROGRAMS: > >>> > >>> Existing classes automatically support this method to the > >>> > >> same extent that > >> > >>> they current support type casts for accessing optional behavior. > >>> > >>> > >>> > >>> > >> > >> > >> > > > From Maurizio.Cimadamore at Sun.COM Wed May 13 09:49:34 2009 From: Maurizio.Cimadamore at Sun.COM (Maurizio Cimadamore) Date: Wed, 13 May 2009 17:49:34 +0100 Subject: Notes on implementing concise calls to constructors with type parameters Message-ID: <4A0AFA1E.8020109@sun.com> Hi I'm working at the implementation of the coin item 'concise calls to constructors with type parameters'[1][4]. I've been following the previous emails about this subject and I noted that the proposed implementation strategy is essentially to mimick the diamond notation by providing synthetic factory methods. As already noted[2] this approach has some complications: * Generic constructors that declare their own type variables * accessibility modifiers * var-args * boxing/unboxing conversion I came out with an alternate implementation[3] strategy which makes use of the javac's ForAll type: *) When a call to a constructor exploiting the diamond operator is found (e.g. new ArrayList<>()) the type of the new expression should be a ForAll - in this particular example, a type F type where the F.tvars = E (type variable declared by ArrayList) and where F.qtype = ArrayList. *) When javac checks the new expression actual type against the expected type E (e.g. List) simply re-use Infer.instantiateExpr(F, E), where F is the ForAll type calculated as above and E is the expected type. Javac will apply 15.12.2.8 in order to infer all the type variables in F exploiting (i) info about the expected type E and (ii) type-variables (non -recursive) declared bounds. In this very simple case javac will infer E to be String and the 'new' expression would type-check without problems. This approach has the advantage of not requiring additional synthetic code/type/symbol to be generated on the fly by javac. The main difference between my implementation strategy and the proposed one (exploiting synthetic factory methods) is that my implementation performs only a single round of inference, in particular the one described in JLS3 15.12.2.8; the implementation strategy requiring synthetic factory methods is slightly more powerful as it can run a full inference round (JLS3 15.12.2.7 followed by 15.12.2.8). In terms of Java code this means that, given the following code: class Foo { ... Foo(X x) { ... } ... } Foo foo = new Foo<>("Hello!"); my implementation infers Foo while an implementation through static factories will be able to infer Foo (because it would take into account inference from actual constructor parameters as well). Maurizio [1] http://mail.openjdk.java.net/pipermail/coin-dev/2009-February/000009.html [2] http://mail.openjdk.java.net/pipermail/coin-dev/2009-March/000075.html [3] http://cr.openjdk.java.net/~mcimadamore/6840638/webrev.0/ [4] http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6840638 From neal at gafter.com Wed May 13 10:47:53 2009 From: neal at gafter.com (Neal Gafter) Date: Wed, 13 May 2009 10:47:53 -0700 Subject: Notes on implementing concise calls to constructors with type parameters In-Reply-To: <4A0AFA1E.8020109@sun.com> References: <4A0AFA1E.8020109@sun.com> Message-ID: <15e8b9d20905131047n30080d8cp588a5e9baefc3f80@mail.gmail.com> Maurizio- When I discussed the proposed implementation (and specification) strategy with Joe Darcy, I did NOT propose to actually generate any code for synthetic static factories. Rather, the strategy is for the compiler to *imagine *the existence of a static method *for the purposes of type inference only*. The method would not be added to the class or otherwise preserved in the resulting class file or internal symbol table. Once type inference is done, these synthetic methods are discarded. As you know, symbols and types are lightweight objects that are created and discarded frequently by the compiler, so this strategy is not likely to introduce any extraordinary performance overhead. In the rare case of generic constructors, the synthetic factory method would have additional type parameters for the constructor's own type parameters. There are some subtle issues in handling syntax like *new Name<>() * but those issues arise in any strategy. Accessibility and var-args can similarly be copied from the underlying constructor. I agree that your technique has almost the same effect as the one I proposed, except that you fail to use the constructor arguments as input to type inference. I consider that a severe disadvantage. It will result in a continued need for static factory methods just to get type inference. Cheers, Neal On Wed, May 13, 2009 at 9:49 AM, Maurizio Cimadamore < Maurizio.Cimadamore at sun.com> wrote: > Hi > I'm working at the implementation of the coin item 'concise calls to > constructors with type parameters'[1][4]. I've been following the > previous emails about this subject and I noted that the proposed > implementation strategy is essentially to mimick the diamond notation by > providing synthetic factory methods. As already noted[2] this approach > has some complications: > > * Generic constructors that declare their own type variables > * accessibility modifiers > * var-args > * boxing/unboxing conversion > > I came out with an alternate implementation[3] strategy which makes use > of the javac's ForAll type: > > *) When a call to a constructor exploiting the diamond operator is found > (e.g. new ArrayList<>()) the type of the new expression should be a > ForAll - in this particular example, a type F type where the F.tvars = E > (type variable declared by ArrayList) and where F.qtype = ArrayList. > > *) When javac checks the new expression actual type against the expected > type E (e.g. List) simply re-use Infer.instantiateExpr(F, E), > where F is the ForAll type calculated as above and E is the expected > type. Javac will apply 15.12.2.8 in order to infer all the type > variables in F exploiting (i) info about the expected type E and (ii) > type-variables (non -recursive) declared bounds. In this very simple > case javac will infer E to be String and the 'new' expression would > type-check without problems. > > This approach has the advantage of not requiring additional synthetic > code/type/symbol to be generated on the fly by javac. > > The main difference between my implementation strategy and the proposed > one (exploiting synthetic factory methods) is that my implementation > performs only a single round of inference, in particular the one > described in JLS3 15.12.2.8; the implementation strategy requiring > synthetic factory methods is slightly more powerful as it can run a full > inference round (JLS3 15.12.2.7 followed by 15.12.2.8). In terms of Java > code this means that, given the following code: > > class Foo { > ... > Foo(X x) { ... } > ... > } > > Foo foo = new Foo<>("Hello!"); > > my implementation infers Foo while an implementation through > static factories will be able to infer Foo (because it would > take into account inference from actual constructor parameters as well). > > Maurizio > > [1] > http://mail.openjdk.java.net/pipermail/coin-dev/2009-February/000009.html > [2] http://mail.openjdk.java.net/pipermail/coin-dev/2009-March/000075.html > [3] http://cr.openjdk.java.net/~mcimadamore/6840638/webrev.0/ > [4] http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6840638 > > From neal at gafter.com Wed May 13 10:52:33 2009 From: neal at gafter.com (Neal Gafter) Date: Wed, 13 May 2009 10:52:33 -0700 Subject: Notes on implementing concise calls to constructors with type parameters In-Reply-To: <15e8b9d20905131047n30080d8cp588a5e9baefc3f80@mail.gmail.com> References: <4A0AFA1E.8020109@sun.com> <15e8b9d20905131047n30080d8cp588a5e9baefc3f80@mail.gmail.com> Message-ID: <15e8b9d20905131052y15353616xd1d5b69e230dd57@mail.gmail.com> I should add that the ForAll type doesn't exist in the JLS, so the specification will have to be done using general type inference. Once it is done that way, the fact that the argument types are ignored in type inference will seem quite strange. On Wed, May 13, 2009 at 10:47 AM, Neal Gafter wrote: > Maurizio- > > When I discussed the proposed implementation (and specification) strategy > with Joe Darcy, I did NOT propose to actually generate any code for > synthetic static factories. Rather, the strategy is for the compiler to *imagine > *the existence of a static method *for the purposes of type inference only > *. The method would not be added to the class or otherwise preserved in > the resulting class file or internal symbol table. Once type inference is > done, these synthetic methods are discarded. As you know, symbols and types > are lightweight objects that are created and discarded frequently by the > compiler, so this strategy is not likely to introduce any extraordinary > performance overhead. > > In the rare case of generic constructors, the synthetic factory method > would have additional type parameters for the constructor's own type > parameters. There are some subtle issues in handling syntax like > > *new Name<>() > * > > but those issues arise in any strategy. Accessibility and var-args can > similarly be copied from the underlying constructor. > > I agree that your technique has almost the same effect as the one I > proposed, except that you fail to use the constructor arguments as input to > type inference. I consider that a severe disadvantage. It will result in a > continued need for static factory methods just to get type inference. > > Cheers, > Neal > > > On Wed, May 13, 2009 at 9:49 AM, Maurizio Cimadamore < > Maurizio.Cimadamore at sun.com> wrote: > >> Hi >> I'm working at the implementation of the coin item 'concise calls to >> constructors with type parameters'[1][4]. I've been following the >> previous emails about this subject and I noted that the proposed >> implementation strategy is essentially to mimick the diamond notation by >> providing synthetic factory methods. As already noted[2] this approach >> has some complications: >> >> * Generic constructors that declare their own type variables >> * accessibility modifiers >> * var-args >> * boxing/unboxing conversion >> >> I came out with an alternate implementation[3] strategy which makes use >> of the javac's ForAll type: >> >> *) When a call to a constructor exploiting the diamond operator is found >> (e.g. new ArrayList<>()) the type of the new expression should be a >> ForAll - in this particular example, a type F type where the F.tvars = E >> (type variable declared by ArrayList) and where F.qtype = ArrayList. >> >> *) When javac checks the new expression actual type against the expected >> type E (e.g. List) simply re-use Infer.instantiateExpr(F, E), >> where F is the ForAll type calculated as above and E is the expected >> type. Javac will apply 15.12.2.8 in order to infer all the type >> variables in F exploiting (i) info about the expected type E and (ii) >> type-variables (non -recursive) declared bounds. In this very simple >> case javac will infer E to be String and the 'new' expression would >> type-check without problems. >> >> This approach has the advantage of not requiring additional synthetic >> code/type/symbol to be generated on the fly by javac. >> >> The main difference between my implementation strategy and the proposed >> one (exploiting synthetic factory methods) is that my implementation >> performs only a single round of inference, in particular the one >> described in JLS3 15.12.2.8; the implementation strategy requiring >> synthetic factory methods is slightly more powerful as it can run a full >> inference round (JLS3 15.12.2.7 followed by 15.12.2.8). In terms of Java >> code this means that, given the following code: >> >> class Foo { >> ... >> Foo(X x) { ... } >> ... >> } >> >> Foo foo = new Foo<>("Hello!"); >> >> my implementation infers Foo while an implementation through >> static factories will be able to infer Foo (because it would >> take into account inference from actual constructor parameters as well). >> >> Maurizio >> >> [1] >> http://mail.openjdk.java.net/pipermail/coin-dev/2009-February/000009.html >> [2] >> http://mail.openjdk.java.net/pipermail/coin-dev/2009-March/000075.html >> [3] http://cr.openjdk.java.net/~mcimadamore/6840638/webrev.0/ >> [4] http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6840638 >> >> > From Ulf.Zibis at gmx.de Wed May 13 10:58:38 2009 From: Ulf.Zibis at gmx.de (Ulf Zibis) Date: Wed, 13 May 2009 19:58:38 +0200 Subject: Notes on implementing concise calls to constructors with type parameters In-Reply-To: <4A0AFA1E.8020109@sun.com> References: <4A0AFA1E.8020109@sun.com> Message-ID: <4A0B0A4E.30908@gmx.de> BTW 1 question: Is there any difference in writing: List l = new ArrayList(); or: List l = new ArrayList(); I guess not, so why using 2nd writing. thanks, Ulf From neal at gafter.com Wed May 13 11:00:52 2009 From: neal at gafter.com (Neal Gafter) Date: Wed, 13 May 2009 11:00:52 -0700 Subject: Notes on implementing concise calls to constructors with type parameters In-Reply-To: <4A0B0A4E.30908@gmx.de> References: <4A0AFA1E.8020109@sun.com> <4A0B0A4E.30908@gmx.de> Message-ID: <15e8b9d20905131100h49023210kb3d5edc578b78987@mail.gmail.com> The first creates a raw ArrayList, and then invokes the unchecked conversion (and generating the required warning from the compiler). The second form is typesafe. On Wed, May 13, 2009 at 10:58 AM, Ulf Zibis wrote: > BTW 1 question: > > Is there any difference in writing: > List l = new ArrayList(); > or: > List l = new ArrayList(); > > I guess not, so why using 2nd writing. > > thanks, > > Ulf > > > > From reinier at zwitserloot.com Wed May 13 17:28:02 2009 From: reinier at zwitserloot.com (Reinier Zwitserloot) Date: Thu, 14 May 2009 02:28:02 +0200 Subject: Notes on implementing concise calls to constructors with type parameters In-Reply-To: <4A0B0A4E.30908@gmx.de> References: <4A0AFA1E.8020109@sun.com> <4A0B0A4E.30908@gmx.de> Message-ID: <518ACAAF-26E0-4F6A-BDE1-80BD74509EC3@zwitserloot.com> Here's a crazy idea: Why don't we deprecate raw types for constructors? I know what you're saying: Deprecate stuff? in the core? we don't do that in java land! But I think it'll work out fine. All this means is: A constructor call with no generics information, on a type where generics information is expected, is no longer the raw type. It is the 'infer me please' type, entirely analogous to the diamond notation. Here's the trick, though: This inference system can infer 'raw', no problem. The following code: List foo = new ArrayList(); has a raw List on the LHS (no changes in the type system, just constructor calls), and thus the RHS would infer to new ArrayList(). The following: List foo = new ArrayList(); currently results in a raw list on the RHS, then raw-to-generified conversion (which gives you a warning) to make the ArrayList fit in the required List type. After this change, this would work differently: the RHS is now ArrayList with the notion that the generics need to be inferred, just like they would for static methods. In this case, String is inferred, and the warning goes away. This boils down to: - no code that used to compile fine will now compile with errors or warnings. - warnings that used to exist will either still exist, or go away, or become a different warning. It's not 100% backwards compatible though, there's this one extremely rare case where you run into trouble. Behold this monstrosity: import java.util.List; import java.util.ArrayList; public class Foo { public static void overloaded(Object x) { System.out.println("overloaded(Object) called."); } public static void overloaded(Number x) { System.out.println("overloaded(Number) called."); } public static void main(String[] args) { overloaded(getList().get(0)); overloaded(new TestList().get(0)); } //these methods are ugly but that's because they are contrived use cases. @SuppressWarnings("unchecked") public static List getList() { List x = new ArrayList(); x.add(1); return x; } @SuppressWarnings("unchecked") public static class TestList extends ArrayList {{ List x = this; x.add(1); }} } The raw type of TestList will end up calling the Object version, but the generics inference of the static method infers Number, due to the type bound. Showstopper? No problem. Just add a rule that says: If the constructor expression is used in a place where the inference engine cannot make an unambiguous decision, instead of inferring the lower bound of the generics parameter (the Foo in extends Foo), always infer Object. I find the empty diamond notation very ugly; feels like a hack just to ensure backwards compatibility. I think we can do better. --Reinier Zwitserloot On May 13, 2009, at 19:58, Ulf Zibis wrote: > BTW 1 question: > > Is there any difference in writing: > List l = new ArrayList(); > or: > List l = new ArrayList(); > > I guess not, so why using 2nd writing. > > thanks, > > Ulf > > > From neal at gafter.com Wed May 13 20:27:23 2009 From: neal at gafter.com (Neal Gafter) Date: Wed, 13 May 2009 20:27:23 -0700 Subject: Notes on implementing concise calls to constructors with type parameters In-Reply-To: <518ACAAF-26E0-4F6A-BDE1-80BD74509EC3@zwitserloot.com> References: <4A0AFA1E.8020109@sun.com> <4A0B0A4E.30908@gmx.de> <518ACAAF-26E0-4F6A-BDE1-80BD74509EC3@zwitserloot.com> Message-ID: <15e8b9d20905132027v276bbdc0kb5962c4ee86b7c3a@mail.gmail.com> On Wed, May 13, 2009 at 5:28 PM, Reinier Zwitserloot < reinier at zwitserloot.com> wrote: > This boils down to: > > > - no code that used to compile fine will now compile with errors or > warnings. > - warnings that used to exist will either still exist, or go away, > or become a different warning. This is all very hand-wavy. It isn't clear to me that one can come up with a straightforward inference algorithm that has these desired properties. The one I outlined certainly doesn't have this property. Can you please be more specific about the inference algorithm you have in mind, and how we'd demonstrate its soundness? Showstopper? No problem. Just add a rule that says: If the constructor > expression is used in a place where the inference engine cannot make > an unambiguous decision, instead of inferring the lower bound of the > generics parameter (the Foo in extends Foo), always infer Object. It isn't clear to me precisely where this rule fits into the current inference algorithm, or into whatever inference algorithm you have in mind, without changing the results of inference in many other situations. Can you please be more precise about where in the inference process this rule is to be invoked? Regards, Neal From howard.lovatt at iee.org Wed May 13 20:41:13 2009 From: howard.lovatt at iee.org (Howard Lovatt) Date: Thu, 14 May 2009 13:41:13 +1000 Subject: Notes on implementing concise calls to constructors with type parameters Message-ID: <3dd3f56a0905132041r67710789if86d4e942987a039@mail.gmail.com> The suggestion from Reinier that: List foo = new ArrayList(); infers ArrayList, seems like a good idea to me (for one thing it is consistent with how you use generic static methods and as Ulf pointed out people already write this and suffer the warnings). Also the present system, because or erasure, isn't type safe as it stands, e.g.: final List ls = new ArrayList(); final List lr = ( List ) ls; lr.add( 1 ); System.out.println( " ls = " + ls ); and Reinier's change would if anything increase type safety. Even if there are some minor incompatibilities, it would be worth it. I am not a fan of the <> syntax, it looks ugly and if anything implies raw type to me rather than inferred type. A further suggestion along Reinier's lines, allow: ArrayList foo = new(); to be equivalent to: ArrayList foo = new ArrayList(); -- Howard. From neal at gafter.com Wed May 13 21:15:22 2009 From: neal at gafter.com (Neal Gafter) Date: Wed, 13 May 2009 21:15:22 -0700 Subject: Notes on implementing concise calls to constructors with type parameters In-Reply-To: <3dd3f56a0905132041r67710789if86d4e942987a039@mail.gmail.com> References: <3dd3f56a0905132041r67710789if86d4e942987a039@mail.gmail.com> Message-ID: <15e8b9d20905132115r58bfe6a7naa6952e5f94c1392@mail.gmail.com> Like Reiner, I suppose you have in mind a specification that would result in the behavior you want without any undesireable side-effects. I look forward to seeing that spec. Until then, there isn't really much to comment on. Regards, Neal On Wed, May 13, 2009 at 8:41 PM, Howard Lovatt wrote: > The suggestion from Reinier that: > > List foo = new ArrayList(); > > infers ArrayList, seems like a good idea to me (for one thing > it is consistent with how you use generic static methods and as Ulf > pointed out people already write this and suffer the warnings). Also > the present system, because or erasure, isn't type safe as it stands, > e.g.: > > final List ls = new ArrayList(); > final List lr = ( List ) ls; > lr.add( 1 ); > System.out.println( " ls = " + ls ); > > and Reinier's change would if anything increase type safety. > > Even if there are some minor incompatibilities, it would be worth it. > I am not a fan of the <> syntax, it looks ugly and if anything implies > raw type to me rather than inferred type. A further suggestion along > Reinier's lines, allow: > > ArrayList foo = new(); > > to be equivalent to: > > ArrayList foo = new ArrayList(); > > > -- Howard. > > From mark at talios.com Wed May 13 21:18:42 2009 From: mark at talios.com (Mark Derricutt) Date: Thu, 14 May 2009 16:18:42 +1200 Subject: Notes on implementing concise calls to constructors with type parameters In-Reply-To: <3dd3f56a0905132041r67710789if86d4e942987a039@mail.gmail.com> References: <3dd3f56a0905132041r67710789if86d4e942987a039@mail.gmail.com> Message-ID: If you were going to use this syntax, why not be somewhat consistent with the dynamic language folk and go for: def foo = new ArrayList(); Visually I find it more logical to read it this way. On Thu, May 14, 2009 at 3:41 PM, Howard Lovatt wrote: > ArrayList foo = new(); -- Discouragement is a dissatisfaction with the past, a distaste for the present, and a distrust of the future - Maree De Jong, Life NZ. blog: http://www.talios.com podcast: http://www.illegalargument.com skype / twitter: talios Sent from Auckland, Auk, New Zealand From Joe.Darcy at Sun.COM Wed May 13 21:42:18 2009 From: Joe.Darcy at Sun.COM (Joseph D. Darcy) Date: Wed, 13 May 2009 21:42:18 -0700 Subject: Notes on implementing concise calls to constructors with type parameters In-Reply-To: References: <3dd3f56a0905132041r67710789if86d4e942987a039@mail.gmail.com> Message-ID: <4A0BA12A.7020605@sun.com> Mark Derricutt wrote: > If you were going to use this syntax, why not be somewhat consistent with > the dynamic language folk and go for: > > def foo = new ArrayList(); > Java is not a dynamic language; I find declaring the full type on the left hand side (e.g. "List") and initializing with the implementation type but without repeating the type parameter (e.g. "new ArrayList<>()") to be easy to read and more in keeping with the design of Java. -Joe > > Visually I find it more logical to read it this way. > > On Thu, May 14, 2009 at 3:41 PM, Howard Lovatt wrote: > > >> ArrayList foo = new(); >> > > > > From Maurizio.Cimadamore at Sun.COM Thu May 14 02:00:47 2009 From: Maurizio.Cimadamore at Sun.COM (Maurizio Cimadamore) Date: Thu, 14 May 2009 10:00:47 +0100 Subject: Notes on implementing concise calls to constructors with type parameters In-Reply-To: <15e8b9d20905131047n30080d8cp588a5e9baefc3f80@mail.gmail.com> References: <4A0AFA1E.8020109@sun.com> <15e8b9d20905131047n30080d8cp588a5e9baefc3f80@mail.gmail.com> Message-ID: <4A0BDDBF.1010206@sun.com> Neal Gafter wrote: > Maurizio- > > When I discussed the proposed implementation (and specification) strategy > with Joe Darcy, I did NOT propose to actually generate any code for > synthetic static factories. Rather, the strategy is for the compiler > to *imagine > *the existence of a static method *for the purposes of type inference only*. > Neal I know that you weren't proposing to generate actual code for static factories. > I agree that your technique has almost the same effect as the one I > proposed, except that you fail to use the constructor arguments as input to > type inference. I consider that a severe disadvantage. It will result in a > continued need for static factory methods just to get type inference. > Let me start by saying that all the examples I found in this thread exploits inference from the return type. But there's a more compelling reason for which I think my solution is pragmatically a good idea: it doesn't alter the way in which method (constructor) resolution is performed. That is, after the the site has been inferred (from the assignment context) standard method resolution can be applied to resolve the constructor to be called in a straightforward way. The second advantage is that the inferred type is always somehow mandated by the declared type which, given the fact that Java is a strongly typed language I consider it to be a good side-effect, e.g.: List ln = new ArrayList<>(1); This would be inferred to ArrayList with my proposal; with your proposal the above code will be flagged with an error, as the inferred type ArrayList (which I agree is more specific) is not compatible with the expected type List. The only alternative would be to use a wildcard in the LHS. In other words I think that my strategy is less powerful (as stated in the previous mail - no secret about that :-) ) but that leads to more predictable results - e.g. in terms of refactoring existing code, users can most of the time just drop the generics in the RHS, replacing them with the diamond notation, and the semantics won't change. With your approach this simple refactoring could lead to compile-time errors. Regarding the fact that ForAll is not present in the JLS - I totally agree - they are not part of the JLS whatsoever. In fact this is an 'implementation' strategy. The JLS should find an alternate way to specify the behavior of the diamond notation - but it doesn't seem - it should simply reformulate 15.12.2.8 so that it can be applied to class type variables as well as to method type variables. Maurizio > Cheers, > Neal > > On Wed, May 13, 2009 at 9:49 AM, Maurizio Cimadamore < > Maurizio.Cimadamore at sun.com> wrote: > > >> Hi >> I'm working at the implementation of the coin item 'concise calls to >> constructors with type parameters'[1][4]. I've been following the >> previous emails about this subject and I noted that the proposed >> implementation strategy is essentially to mimick the diamond notation by >> providing synthetic factory methods. As already noted[2] this approach >> has some complications: >> >> * Generic constructors that declare their own type variables >> * accessibility modifiers >> * var-args >> * boxing/unboxing conversion >> >> I came out with an alternate implementation[3] strategy which makes use >> of the javac's ForAll type: >> >> *) When a call to a constructor exploiting the diamond operator is found >> (e.g. new ArrayList<>()) the type of the new expression should be a >> ForAll - in this particular example, a type F type where the F.tvars = E >> (type variable declared by ArrayList) and where F.qtype = ArrayList. >> >> *) When javac checks the new expression actual type against the expected >> type E (e.g. List) simply re-use Infer.instantiateExpr(F, E), >> where F is the ForAll type calculated as above and E is the expected >> type. Javac will apply 15.12.2.8 in order to infer all the type >> variables in F exploiting (i) info about the expected type E and (ii) >> type-variables (non -recursive) declared bounds. In this very simple >> case javac will infer E to be String and the 'new' expression would >> type-check without problems. >> >> This approach has the advantage of not requiring additional synthetic >> code/type/symbol to be generated on the fly by javac. >> >> The main difference between my implementation strategy and the proposed >> one (exploiting synthetic factory methods) is that my implementation >> performs only a single round of inference, in particular the one >> described in JLS3 15.12.2.8; the implementation strategy requiring >> synthetic factory methods is slightly more powerful as it can run a full >> inference round (JLS3 15.12.2.7 followed by 15.12.2.8). In terms of Java >> code this means that, given the following code: >> >> class Foo { >> ... >> Foo(X x) { ... } >> ... >> } >> >> Foo foo = new Foo<>("Hello!"); >> >> my implementation infers Foo while an implementation through >> static factories will be able to infer Foo (because it would >> take into account inference from actual constructor parameters as well). >> >> Maurizio >> >> [1] >> http://mail.openjdk.java.net/pipermail/coin-dev/2009-February/000009.html >> [2] http://mail.openjdk.java.net/pipermail/coin-dev/2009-March/000075.html >> [3] http://cr.openjdk.java.net/~mcimadamore/6840638/webrev.0/ >> [4] http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6840638 >> >> >> > > From Maurizio.Cimadamore at Sun.COM Thu May 14 02:17:47 2009 From: Maurizio.Cimadamore at Sun.COM (Maurizio Cimadamore) Date: Thu, 14 May 2009 10:17:47 +0100 Subject: Notes on implementing concise calls to constructors with type parameters In-Reply-To: <4A0BDDBF.1010206@sun.com> References: <4A0AFA1E.8020109@sun.com> <15e8b9d20905131047n30080d8cp588a5e9baefc3f80@mail.gmail.com> <4A0BDDBF.1010206@sun.com> Message-ID: <4A0BE1BB.9050906@sun.com> > List ln = new ArrayList<>(1); > > This would be inferred to ArrayList with my proposal; with your > proposal the above code will be flagged with an error, as the inferred > type ArrayList (which I agree is more specific) is not > compatible with the expected type List. The only alternative > would be to use a wildcard in the LHS. > Whoops! This example is obviously wrong as no such constructor is defined in ArrayList. Instead what I meant was: class Foo { Foo(X x) { ... } ... } Foo fn = new Foo<>(); the above statement compiles iff Foo<> is inferred as Foo. Maurizio From david.goodenough at linkchoose.co.uk Thu May 14 02:20:59 2009 From: david.goodenough at linkchoose.co.uk (David Goodenough) Date: Thu, 14 May 2009 10:20:59 +0100 Subject: Notes on implementing concise calls to constructors with type parameters In-Reply-To: <4A0BA12A.7020605@sun.com> References: <3dd3f56a0905132041r67710789if86d4e942987a039@mail.gmail.com> <4A0BA12A.7020605@sun.com> Message-ID: <200905141021.00722.david.goodenough@linkchoose.co.uk> On Thursday 14 May 2009, Joseph D. Darcy wrote: > Mark Derricutt wrote: > > If you were going to use this syntax, why not be somewhat consistent with > > the dynamic language folk and go for: > > > > def foo = new ArrayList(); > > Java is not a dynamic language; I find declaring the full type on the > left hand side (e.g. "List") and initializing with the > implementation type but without repeating the type parameter (e.g. "new > ArrayList<>()") to be easy to read and more in keeping with the design > of Java. The logic of that suggests that in the case where you are instanciating a new one of what is declared that one could use the notation:- HashTable table = new; which would imply:- Hashtable table = new Hashtable(); Obviously is can not be done in the case of the lhs being Abstract, but in that there is less repitition. Maybe a step to far, but is removes another repeat. David > > -Joe > > > Visually I find it more logical to read it this way. > > > > On Thu, May 14, 2009 at 3:41 PM, Howard Lovatt wrote: > >> ArrayList foo = new(); From neal at gafter.com Thu May 14 03:55:19 2009 From: neal at gafter.com (Neal Gafter) Date: Thu, 14 May 2009 03:55:19 -0700 Subject: Notes on implementing concise calls to constructors with type parameters In-Reply-To: <4A0BDDBF.1010206@sun.com> References: <4A0AFA1E.8020109@sun.com> <15e8b9d20905131047n30080d8cp588a5e9baefc3f80@mail.gmail.com> <4A0BDDBF.1010206@sun.com> Message-ID: <15e8b9d20905140355h501d60b1y4e90fdf841fd4fa9@mail.gmail.com> On Thu, May 14, 2009 at 2:00 AM, Maurizio Cimadamore < Maurizio.Cimadamore at sun.com> wrote: > Let me start by saying that all the examples I found in this thread > exploits inference from the return type. If you're looking for an example, given *class X {* * public X(T t) { ... }* *}* *void f(X xs) ...* the code *f(new X<>("foo"))* works with my formulation of inference, and doesn't with yours. See also http://gafter.blogspot.com/2006/09/failure-of-imagination-in-language_17.html But there's a more compelling reason for which I think my solution is > pragmatically a good idea: it doesn't alter the way in which method > (constructor) resolution is performed. That is, after the the site has been > inferred (from the assignment context) standard method resolution can be > applied to resolve the constructor to be called in a straightforward way. Why is it an advantage to do type inference separately and before method (constructor) resolution, when in every other context type inference is done *as part of *overload resolution? I would think that it makes more sense to be consistent with the way things are already done. > The second advantage is that the inferred type is always somehow mandated > by the declared type which, given the fact that Java is a strongly typed > language I consider it to be a good side-effect Yes, assuming the "diamond" construct is only to be used on the right-hand-side of an assignment. But I think it's wrong to make language constructs non-orthogonal. > Regarding the fact that ForAll is not present in the JLS - I totally agree > - they are not part of the JLS whatsoever. In fact this is an > 'implementation' strategy. The JLS should find an alternate way to specify > the behavior of the diamond notation - but it doesn't seem - it should > simply reformulate 15.12.2.8 so that it can be applied to class type > variables as well as to method type variables. Um, that's the section on method (constructor) overload resolution. That's what I was proposing, however, if I understand what you're suggesting, it would be done separately and preceding overload resolution. It would therefore require a separate new section to specify the desired behavior. Cheers, Neal From Maurizio.Cimadamore at Sun.COM Thu May 14 04:28:36 2009 From: Maurizio.Cimadamore at Sun.COM (Maurizio Cimadamore) Date: Thu, 14 May 2009 12:28:36 +0100 Subject: Notes on implementing concise calls to constructors with type parameters In-Reply-To: <15e8b9d20905140355h501d60b1y4e90fdf841fd4fa9@mail.gmail.com> References: <4A0AFA1E.8020109@sun.com> <15e8b9d20905131047n30080d8cp588a5e9baefc3f80@mail.gmail.com> <4A0BDDBF.1010206@sun.com> <15e8b9d20905140355h501d60b1y4e90fdf841fd4fa9@mail.gmail.com> Message-ID: <4A0C0064.3020709@sun.com> > > Yes, assuming the "diamond" construct is only to be used on the > right-hand-side of an assignment. But I think it's wrong to make > language constructs non-orthogonal. It seems to me that the "diamond" construct has always had this restricted-ness right from the beginning. See the original draft: http://mail.openjdk.java.net/pipermail/coin-dev/2009-February/000009.html Btw - allowing inference in method invocation context is rather complex - a slight variation of your example fails to compile with both approaches; given the following method declaration:* void f(List xs) ...* the following method call *f(new ArrayList<>())* won't type-check. I'm not saying that the algorithm doesn't exist, but it seems way too far from what the original draft looked like. The bottom-line is: if we just consider inference in assignment context (and I think we should - at least if we want to keep this change 'small' ;-) ), there's no substantial difference between my proposal and yours. cheers Maurizio From Ulf.Zibis at gmx.de Thu May 14 04:39:07 2009 From: Ulf.Zibis at gmx.de (Ulf Zibis) Date: Thu, 14 May 2009 13:39:07 +0200 Subject: Notes on implementing concise calls to constructors with type parameters In-Reply-To: <4A0BA12A.7020605@sun.com> References: <3dd3f56a0905132041r67710789if86d4e942987a039@mail.gmail.com> <4A0BA12A.7020605@sun.com> Message-ID: <4A0C02DB.4020305@gmx.de> Am 14.05.2009 06:42, Joseph D. Darcy schrieb: > Mark Derricutt wrote: > >> If you were going to use this syntax, why not be somewhat consistent with >> the dynamic language folk and go for: >> >> def foo = new ArrayList(); >> >> > > Java is not a dynamic language; I find declaring the full type on the > left hand side (e.g. "List") and initializing with the > implementation type but without repeating the type parameter (e.g. "new > ArrayList<>()") to be easy to read and more in keeping with the design > of Java. > > -Joe > > +1 -Ulf From Maurizio.Cimadamore at Sun.COM Thu May 14 04:43:42 2009 From: Maurizio.Cimadamore at Sun.COM (Maurizio Cimadamore) Date: Thu, 14 May 2009 12:43:42 +0100 Subject: Notes on implementing concise calls to constructors with type parameters In-Reply-To: <15e8b9d20905140355h501d60b1y4e90fdf841fd4fa9@mail.gmail.com> References: <4A0AFA1E.8020109@sun.com> <15e8b9d20905131047n30080d8cp588a5e9baefc3f80@mail.gmail.com> <4A0BDDBF.1010206@sun.com> <15e8b9d20905140355h501d60b1y4e90fdf841fd4fa9@mail.gmail.com> Message-ID: <4A0C03EE.7030000@sun.com> > Why is it an advantage to do type inference separately and before method > (constructor) resolution, when in every other context type inference is done > *as part of *overload resolution? I would think that it makes more sense to > be consistent with the way things are already done. > > I guess that what worries me is that with your approach you are not just inferring a method signature given a site - you are also inferring the site's type, which by 15.12.2 is supposed to be fully known when overload resolution is applied. Quoting from the beginning of 15.12.2: "The second step searches the type determined in the previous step for member methods". With my approach, when you reach 15.12.2 (e.g. from 15.9.3 - choosing the constructor and its arguments) you already have a type to search for member constructors (because I would apply return-type inference during 15.9.1). With your approach such type is simply unknown (only the erased type can be known) - and it might depend on what you discover later on when performing overload resolution. This leads to subtle differences in e.g. how errors are handled; e.g. if you do: Foo fs = Foo<>(1); I would expect the compiler to complain because init(Integer) cannot be found inside Foo. With your approach things do differently: first the compiler infers that Foo is created, then it reports an error in the assignment, as Foo cannot be assigned to Foo. Again, with my approach what you get is essentially the same error you would have get by replacing Foo<> with Foo. Maurizio From howard.lovatt at iee.org Thu May 14 05:43:47 2009 From: howard.lovatt at iee.org (Howard Lovatt) Date: Thu, 14 May 2009 22:43:47 +1000 Subject: Notes on implementing concise calls to constructors with type parameters In-Reply-To: <15e8b9d20905132115r58bfe6a7naa6952e5f94c1392@mail.gmail.com> References: <3dd3f56a0905132041r67710789if86d4e942987a039@mail.gmail.com> <15e8b9d20905132115r58bfe6a7naa6952e5f94c1392@mail.gmail.com> Message-ID: <3dd3f56a0905140543v63603bd4qed2a149fc06cb0ce@mail.gmail.com> Neal, The conceptual algorithm that I suggest is text substitution of the missing items. It is a conceptual algorithm, I am not saying the compiler has to literally do this, just that the compiler does this or the equivalent of this. As an example consider an abstract form of the proposed declaration for a simple, i.e. not a complete specification but an example, local variable declaration: typeLHS [] name = new [typeRHS] [] ( ... ); The proposed algorithm is that if typeRHS is missing then typeLHS is substituted and if genericParametersRHS is missing and genericParametersLHSis present then genericParametersLHS is substituted. The following concrete example illustrates what is proposed. The example below names the variable using 4 letters, the first is e which stands for type Ex, the second is optional and if present is s which stands for generic parameter String, the next letter is e if the RHS specifies the type, and the last letter is s if the RHS specifies String. The last three letters are optional and if absent an _ is used. This naming convention allows naming of the examples. private static class Ex { Ex() {} } // Translation // Original Ex e___ = new Ex(); // Ex e___ = new(); Ex e__s = new Ex(); // Ex e__s = new(); Ex e_e_ = new Ex(); // Ex e_e_ = new Ex(); Ex e_es = new Ex(); // Ex e_es = new Ex(); Ex es__ = new Ex(); // Ex es__ = new(); Ex es_s = new Ex(); // Ex es_s = new(); Ex ese_ = new Ex(); // Ex ese_ = new Ex(); Ex eses = new Ex(); // Ex eses = new Ex(); Hopefully this is sufficiently detailed to enable you to comment. -- Howard. 2009/5/14 Neal Gafter : > Like Reiner, I suppose you have in mind a specification that would result in > the behavior you want without any undesireable side-effects. I look forward > to seeing that spec. Until then, there isn't really much to comment on. > > Regards, > Neal > > On Wed, May 13, 2009 at 8:41 PM, Howard Lovatt > wrote: >> >> The suggestion from Reinier that: >> >> List foo = new ArrayList(); >> >> infers ArrayList, seems like a good idea to me (for one thing >> it is consistent with how you use generic static methods and as Ulf >> pointed out people already write this and suffer the warnings). Also >> the present system, because or erasure, isn't type safe as it stands, >> e.g.: >> >> final List ls = new ArrayList(); >> final List lr = ( List ) ls; >> lr.add( 1 ); >> System.out.println( " ls = " + ls ); >> >> and Reinier's change would if anything increase type safety. >> >> Even if there are some minor incompatibilities, it would be worth it. >> I am not a fan of the <> syntax, it looks ugly and if anything implies >> raw type to me rather than inferred type. A further suggestion along >> Reinier's lines, allow: >> >> ArrayList foo = new(); >> >> to be equivalent to: >> >> ArrayList foo = new ArrayList(); >> >> >> -- Howard. >> > > > ______________________________________________________________________ > This email has been scanned by the MessageLabs Email Security System. > For more information please visit http://www.messagelabs.com/email > ______________________________________________________________________ > -- -- Howard. From Ulf.Zibis at gmx.de Thu May 14 06:53:55 2009 From: Ulf.Zibis at gmx.de (Ulf Zibis) Date: Thu, 14 May 2009 15:53:55 +0200 Subject: Notes on implementing concise calls to constructors with type parameters In-Reply-To: <15e8b9d20905131100h49023210kb3d5edc578b78987@mail.gmail.com> References: <4A0AFA1E.8020109@sun.com> <4A0B0A4E.30908@gmx.de> <15e8b9d20905131100h49023210kb3d5edc578b78987@mail.gmail.com> Message-ID: <4A0C2273.7020404@gmx.de> Hm, precisely I meant, if there is any difference in the instantiated object, and it's behaviour. Is it? I think, LHS defines precisely the variables type, it's typesafe usage and methodical behaviour, regardless which constructor of which type instantiated it, so typesafety only matters for later usage of the variable as typesafeness of RHS doesn't matter after that code line, and we can define the shortcut as legal, to avoid the compiler warning. -Ulf Am 13.05.2009 20:00, Neal Gafter schrieb: > The first creates a raw ArrayList, and then invokes the unchecked > conversion (and generating the required warning from the compiler). > > The second form is typesafe. > > On Wed, May 13, 2009 at 10:58 AM, Ulf Zibis > wrote: > > BTW 1 question: > > Is there any difference in writing: > List l = new ArrayList(); > or: > List l = new ArrayList(); > > I guess not, so why using 2nd writing. > > thanks, > > Ulf > > > > From Ulf.Zibis at gmx.de Thu May 14 07:00:25 2009 From: Ulf.Zibis at gmx.de (Ulf Zibis) Date: Thu, 14 May 2009 16:00:25 +0200 Subject: Notes on implementing concise calls to constructors with type parameters In-Reply-To: <15e8b9d20905140355h501d60b1y4e90fdf841fd4fa9@mail.gmail.com> References: <4A0AFA1E.8020109@sun.com> <15e8b9d20905131047n30080d8cp588a5e9baefc3f80@mail.gmail.com> <4A0BDDBF.1010206@sun.com> <15e8b9d20905140355h501d60b1y4e90fdf841fd4fa9@mail.gmail.com> Message-ID: <4A0C23F9.4030209@gmx.de> Am 14.05.2009 12:55, Neal Gafter schrieb: > On Thu, May 14, 2009 at 2:00 AM, Maurizio Cimadamore < > Maurizio.Cimadamore at sun.com> wrote: > > >> Let me start by saying that all the examples I found in this thread >> exploits inference from the return type. >> > > > If you're looking for an example, given > > *class X {* > * public X(T t) { ... }* > *}* > > *void f(X xs) ...* > > the code > > *f(new X<>("foo"))* > This is the only case, where I think, that typed constructors make sense, as making things clear, but it should only be mandatory, if otherwise syntax is ambiguous. For normal cases, I agree Howard: I'm not a fan of the <> syntax. In above case, we can see parameter definition of f in same semantics as normal type definition, so f(new X("foo")) should suffice. What should the code f(new X<>("foo")) mean, if we have? : class X { public X(String s) { ... } public X(int i) { ... } } I only see need for typed constructors in case of anonymous instantiation (here Comparator): SortedSet> valueSorted = new TreeSet(new Comparator>() { public int compare(Map.Entry e1, Map.Entry e2) { return (e1.getValue() < e2.getValue()) ? -1 : (e1.getValue() > e2.getValue()) ? 1 : ((e1.getKey()&0xFF) < (e2.getKey()&0xFF)) ? -1 : ((e1.getKey()&0xFF) > (e2.getKey()&0xFF)) ? 1 : 0; } }); -Ulf From Maurizio.Cimadamore at Sun.COM Thu May 14 07:43:16 2009 From: Maurizio.Cimadamore at Sun.COM (Maurizio Cimadamore) Date: Thu, 14 May 2009 15:43:16 +0100 Subject: Notes on implementing concise calls to constructors with type parameters In-Reply-To: <4A0C2273.7020404@gmx.de> References: <4A0AFA1E.8020109@sun.com> <4A0B0A4E.30908@gmx.de> <15e8b9d20905131100h49023210kb3d5edc578b78987@mail.gmail.com> <4A0C2273.7020404@gmx.de> Message-ID: <4A0C2E04.8000504@sun.com> Ulf Zibis wrote: > Hm, precisely I meant, if there is any difference in the instantiated > object, and it's behaviour. Is it? > The instantiated object will be similar but given the class: class Cell { X x; Cell(X x) {this.x = x;} } the following code is unsafe: Cell cs = new Cell(1); //unchecked warning String s = cs.x; //CCE at runtime while the following is safe: Cell cs = new Cell<>(1); //compile-time error!! String s = cs.x; Maurizio > I think, LHS defines precisely the variables type, it's typesafe usage > and methodical behaviour, regardless which constructor of which type > instantiated it, so typesafety only matters for later usage of the > variable as typesafeness of RHS doesn't matter after that code line, and > we can define the shortcut as legal, to avoid the compiler warning. > > -Ulf > > > Am 13.05.2009 20:00, Neal Gafter schrieb: > >> The first creates a raw ArrayList, and then invokes the unchecked >> conversion (and generating the required warning from the compiler). >> >> The second form is typesafe. >> >> On Wed, May 13, 2009 at 10:58 AM, Ulf Zibis > > wrote: >> >> BTW 1 question: >> >> Is there any difference in writing: >> List l = new ArrayList(); >> or: >> List l = new ArrayList(); >> >> I guess not, so why using 2nd writing. >> >> thanks, >> >> Ulf >> >> >> >> >> > > > From Ulf.Zibis at gmx.de Thu May 14 08:34:00 2009 From: Ulf.Zibis at gmx.de (Ulf Zibis) Date: Thu, 14 May 2009 17:34:00 +0200 Subject: Notes on implementing concise calls to constructors with type parameters In-Reply-To: <4A0C2E04.8000504@sun.com> References: <4A0AFA1E.8020109@sun.com> <4A0B0A4E.30908@gmx.de> <15e8b9d20905131100h49023210kb3d5edc578b78987@mail.gmail.com> <4A0C2273.7020404@gmx.de> <4A0C2E04.8000504@sun.com> Message-ID: <4A0C39E8.2090802@gmx.de> Am 14.05.2009 16:43, Maurizio Cimadamore schrieb: > Ulf Zibis wrote: >> Hm, precisely I meant, if there is any difference in the instantiated >> object, and it's behaviour. Is it? >> > The instantiated object will be similar but given the class: > > class Cell { > X x; > Cell(X x) {this.x = x;} > } > > the following code is unsafe: > > Cell cs = new Cell(1); //unchecked warning > String s = cs.x; //CCE at runtime Thanks very much for this. Now I understand. I didn't know, that compiler would allow 1. line. IMHO this should be rejected as error from compiler side, or is there any reason, why not? -Ulf From neal at gafter.com Thu May 14 08:53:22 2009 From: neal at gafter.com (Neal Gafter) Date: Thu, 14 May 2009 08:53:22 -0700 Subject: Notes on implementing concise calls to constructors with type parameters In-Reply-To: <4A0C0064.3020709@sun.com> References: <4A0AFA1E.8020109@sun.com> <15e8b9d20905131047n30080d8cp588a5e9baefc3f80@mail.gmail.com> <4A0BDDBF.1010206@sun.com> <15e8b9d20905140355h501d60b1y4e90fdf841fd4fa9@mail.gmail.com> <4A0C0064.3020709@sun.com> Message-ID: <15e8b9d20905140853m532e3393odbd71b64250fb645@mail.gmail.com> On Thu, May 14, 2009 at 4:28 AM, Maurizio Cimadamore < Maurizio.Cimadamore at sun.com> wrote: > Yes, assuming the "diamond" construct is only to be used on the >> right-hand-side of an assignment. But I think it's wrong to make language >> constructs non-orthogonal. >> > It seems to me that the "diamond" construct has always had this > restricted-ness right from the beginning. See the original draft: > > http://mail.openjdk.java.net/pipermail/coin-dev/2009-February/000009.html > Noted. That's why I got involved - to get this corrected by designing the construct to be orthogonal to assignment. Your approach isn't an implementation of this specification - not even close. Btw - allowing inference in method invocation context is rather complex - a > slight variation of your example fails to compile with both approaches; > given the following method declaration:* Saying it fails and saying it is complex are two different things. Yes, it fails just as it would using static factories, and for exactly the same reason. It's because the specification is so *simple* by relying on the existing inference algorithm. I'm not suggesting that change until and unless it changes for type inference on ordinary method invocations as well. Another advantage of my proposed approach is that "fixing" type inference for other contexts, as I believe we are likely to do later, would automatically fix the diamond operator for those contexts as well without any additional specification effort. > The bottom-line is: if we just consider inference in assignment context > (and I think we should - at least if we want to keep this change 'small' > ;-) ), there's no substantial difference between my proposal and yours. Inferring type arguments based on the type of value parameters *is *a substantial difference. Keeping the spec small is an admirable goal (it isn't clear that your approach would result in a smaller spec), but it shouldn't be done at the cost of internal language consistency. Given that neither approach has even a draft specification, perhaps they should be considered out of scope for project coin. From neal at gafter.com Thu May 14 09:19:43 2009 From: neal at gafter.com (Neal Gafter) Date: Thu, 14 May 2009 09:19:43 -0700 Subject: Notes on implementing concise calls to constructors with type parameters In-Reply-To: <4A0C03EE.7030000@sun.com> References: <4A0AFA1E.8020109@sun.com> <15e8b9d20905131047n30080d8cp588a5e9baefc3f80@mail.gmail.com> <4A0BDDBF.1010206@sun.com> <15e8b9d20905140355h501d60b1y4e90fdf841fd4fa9@mail.gmail.com> <4A0C03EE.7030000@sun.com> Message-ID: <15e8b9d20905140919n33120cbboce744f11177fa1c7@mail.gmail.com> On Thu, May 14, 2009 at 4:43 AM, Maurizio Cimadamore < Maurizio.Cimadamore at sun.com> wrote: > > Why is it an advantage to do type inference separately and before method >> (constructor) resolution, when in every other context type inference is >> done >> *as part of *overload resolution? I would think that it makes more sense >> to >> be consistent with the way things are already done. >> >> >> > I guess that what worries me is that with your approach you are not just > inferring a method signature given a site - you are also inferring the > site's type, which by 15.12.2 is supposed to be fully known when overload > resolution is applied. Quoting from the beginning of 15.12.2: > > "The second step searches the type determined in the previous step for > member methods". > > With my approach, when you reach 15.12.2 (e.g. from 15.9.3 - choosing the > constructor and its arguments) you already have a type to search for member > constructors (because I would apply return-type inference during 15.9.1). > With your approach such type is simply unknown (only the erased type can be > known) - and it might depend on what you discover later on when performing > overload resolution. 15.9.1 doesn't need, refer to, or use the class's type parameters. Neither does 15.9.2 care about the type parameters. They aren't used until 15.9.3, and that defers to the rules for method invocation (15.12) for inference. That's precisely where I suggest the fix belongs - in the *way* that it defers to 15.12. This leads to subtle differences in e.g. how errors are handled; e.g. if you > do: > > Foo fs = Foo<>(1); > > I would expect the compiler to complain because init(Integer) cannot be > found inside Foo. With your approach things do differently: first > the compiler infers that Foo is created, then it reports an error > in the assignment, as Foo cannot be assigned to Foo. Again, > with my approach what you get is essentially the same error you would have > get by replacing Foo<> with Foo. I have confidence in your ability to write clear diagnostics that would apply to the assignment context as well as other contexts. From neal at gafter.com Thu May 14 09:32:23 2009 From: neal at gafter.com (Neal Gafter) Date: Thu, 14 May 2009 09:32:23 -0700 Subject: Notes on implementing concise calls to constructors with type parameters In-Reply-To: <3dd3f56a0905140543v63603bd4qed2a149fc06cb0ce@mail.gmail.com> References: <3dd3f56a0905132041r67710789if86d4e942987a039@mail.gmail.com> <15e8b9d20905132115r58bfe6a7naa6952e5f94c1392@mail.gmail.com> <3dd3f56a0905140543v63603bd4qed2a149fc06cb0ce@mail.gmail.com> Message-ID: <15e8b9d20905140932g33fbcd7atd6c6e28f95211cb4@mail.gmail.com> On Thu, May 14, 2009 at 5:43 AM, Howard Lovatt wrote: > Hopefully this is sufficiently detailed to enable you to comment. > This proposal is completely non-orthogonal and ignores the relationship between the type parameters of the types on the right-hand-side (typically a class) and the left-hand side (typically an interface). *Assuming *there is a one-to-one relationship is bad design, even though it is most frequently the case; the compiler knows the relationships between the types and should use it. The proposal change the meaning of existing code (with respect to raw types). It isn't clear how to make this proposal orthogonal to be used elsewhere than a variable declaration. I suspect specifying this approach would result in a more complex specification than either the approach I've been advocating or the approach Maurizio has been implementing. From Ulf.Zibis at gmx.de Thu May 14 10:39:26 2009 From: Ulf.Zibis at gmx.de (Ulf Zibis) Date: Thu, 14 May 2009 19:39:26 +0200 Subject: Notes on implementing concise calls to constructors with type parameters In-Reply-To: <4A0C2E04.8000504@sun.com> References: <4A0AFA1E.8020109@sun.com> <4A0B0A4E.30908@gmx.de> <15e8b9d20905131100h49023210kb3d5edc578b78987@mail.gmail.com> <4A0C2273.7020404@gmx.de> <4A0C2E04.8000504@sun.com> Message-ID: <4A0C574E.4030305@gmx.de> Am 14.05.2009 16:43, Maurizio Cimadamore schrieb: > Ulf Zibis wrote: >> Hm, precisely I meant, if there is any difference in the instantiated >> object, and it's behaviour. Is it? >> > The instantiated object will be similar but given the class: > > class Cell { > X x; > Cell(X x) {this.x = x;} > } > > the following code is unsafe: > > Cell cs = new Cell(1); //unchecked warning > String s = cs.x; //CCE at runtime Again: Why couldn't compiler reject this as error, or is there any reason, why not? -Ulf From howard.lovatt at gmail.com Thu May 14 14:17:46 2009 From: howard.lovatt at gmail.com (Howard Lovatt) Date: Fri, 15 May 2009 07:17:46 +1000 Subject: Notes on implementing concise calls to constructors with type parameters In-Reply-To: <15e8b9d20905140932g33fbcd7atd6c6e28f95211cb4@mail.gmail.com> References: <3dd3f56a0905132041r67710789if86d4e942987a039@mail.gmail.com> <15e8b9d20905132115r58bfe6a7naa6952e5f94c1392@mail.gmail.com> <3dd3f56a0905140543v63603bd4qed2a149fc06cb0ce@mail.gmail.com> <15e8b9d20905140932g33fbcd7atd6c6e28f95211cb4@mail.gmail.com> Message-ID: <29AB5062-DC0C-4CEF-AE14-9B333F722FB0@gmail.com> Hi Neal, Comments in text below. On 15/05/2009, at 2:32 AM, Neal Gafter wrote: > On Thu, May 14, 2009 at 5:43 AM, Howard Lovatt > wrote: > Hopefully this is sufficiently detailed to enable you to comment. > > This proposal is completely non-orthogonal and ignores the > relationship between the type parameters of the types on the right- > hand-side (typically a class) and the left-hand side (typically an > interface). Assuming there is a one-to-one relationship is bad > design, even though it is most frequently the case; the compiler > knows the relationships between the types and should use it. The advantage of the proposed algorithm is that it is for both the compiler and programmer. For example if someone writes: List l = new(); Then this is equivalent too and will generate the same error message as: List l = new List(); So I don't see a problem with this, it is identical to current Java. If you want an symmetric declaration then you need to specify the asymmetry, e.g.: List ls = new ArrayList(); Becomes: List ls = new ArrayList(); I will come back to this example below. > The proposal change the meaning of existing code (with respect to > raw types). The change in the raw types is as given above for the ArrayList example. I don't think that this change will be a bad thing because at present: List ls = new ArrayList(); Is almost certainly a typo or a lazy bit of coding and therefore the change will fix these problems rather than break code. Other uses of raw types, e.g.: List l = new ArrayList(); Are unchanged. > It isn't clear how to make this proposal orthogonal to be used > elsewhere than a variable declaration. I don't see this. For example the type declaration of a method parameter can be considered like the LHS of a declaration. If generic parameters are infered then you might have to specify them as you do at present - i.e. no change. > I suspect specifying this approach would result in a more complex > specification than either the approach I've been advocating or the > approach Maurizio has been implementing. I think the great advantage of this approach is that it is easy to describe and easy to understand - because it is sytax sugar only. > > > ______________________________________________________________________ > This email has been scanned by the MessageLabs Email Security System. > For more information please visit http://www.messagelabs.com/email > ______________________________________________________________________ From Ulf.Zibis at gmx.de Thu May 14 14:26:30 2009 From: Ulf.Zibis at gmx.de (Ulf Zibis) Date: Thu, 14 May 2009 23:26:30 +0200 Subject: Notes on implementing concise calls to constructors with type parameters In-Reply-To: <29AB5062-DC0C-4CEF-AE14-9B333F722FB0@gmail.com> References: <3dd3f56a0905132041r67710789if86d4e942987a039@mail.gmail.com> <15e8b9d20905132115r58bfe6a7naa6952e5f94c1392@mail.gmail.com> <3dd3f56a0905140543v63603bd4qed2a149fc06cb0ce@mail.gmail.com> <15e8b9d20905140932g33fbcd7atd6c6e28f95211cb4@mail.gmail.com> <29AB5062-DC0C-4CEF-AE14-9B333F722FB0@gmail.com> Message-ID: <4A0C8C86.4040608@gmx.de> +1 especially: List ls = new ArrayList(); -Ulf Am 14.05.2009 23:17, Howard Lovatt schrieb: > Hi Neal, > > Comments in text below. > > On 15/05/2009, at 2:32 AM, Neal Gafter wrote: > > >> On Thu, May 14, 2009 at 5:43 AM, Howard Lovatt >> wrote: >> Hopefully this is sufficiently detailed to enable you to comment. >> >> This proposal is completely non-orthogonal and ignores the >> relationship between the type parameters of the types on the right- >> hand-side (typically a class) and the left-hand side (typically an >> interface). Assuming there is a one-to-one relationship is bad >> design, even though it is most frequently the case; the compiler >> knows the relationships between the types and should use it. >> > > The advantage of the proposed algorithm is that it is for both the > compiler and programmer. For example if someone writes: > > List l = new(); > > Then this is equivalent too and will generate the same error message as: > > List l = new List(); > > So I don't see a problem with this, it is identical to current Java. > > If you want an symmetric declaration then you need to specify the > asymmetry, e.g.: > > List ls = new ArrayList(); > > Becomes: > > List ls = new ArrayList(); > > I will come back to this example below. > > >> The proposal change the meaning of existing code (with respect to >> raw types). >> > > The change in the raw types is as given above for the ArrayList > example. I don't think that this change will be a bad thing because at > present: > > List ls = new ArrayList(); > > Is almost certainly a typo or a lazy bit of coding and therefore the > change will fix these problems rather than break code. > > Other uses of raw types, e.g.: > > List l = new ArrayList(); > > Are unchanged. > > >> It isn't clear how to make this proposal orthogonal to be used >> elsewhere than a variable declaration. >> > > I don't see this. For example the type declaration of a method > parameter can be considered like the LHS of a declaration. If generic > parameters are infered then you might have to specify them as you do > at present - i.e. no change. > > >> I suspect specifying this approach would result in a more complex >> specification than either the approach I've been advocating or the >> approach Maurizio has been implementing. >> > > I think the great advantage of this approach is that it is easy to > describe and easy to understand - because it is sytax sugar only. > > >> ______________________________________________________________________ >> This email has been scanned by the MessageLabs Email Security System. >> For more information please visit http://www.messagelabs.com/email >> ______________________________________________________________________ >> > > > From Ulf.Zibis at gmx.de Thu May 14 14:31:47 2009 From: Ulf.Zibis at gmx.de (Ulf Zibis) Date: Thu, 14 May 2009 23:31:47 +0200 Subject: Notes on implementing concise calls to constructors with type parameters In-Reply-To: <15e8b9d20905141112y38835adag905e10e4373a8b45@mail.gmail.com> References: <4A0AFA1E.8020109@sun.com> <4A0B0A4E.30908@gmx.de> <15e8b9d20905131100h49023210kb3d5edc578b78987@mail.gmail.com> <4A0C2273.7020404@gmx.de> <4A0C2E04.8000504@sun.com> <4A0C574E.4030305@gmx.de> <15e8b9d20905141112y38835adag905e10e4373a8b45@mail.gmail.com> Message-ID: <4A0C8DC3.2060506@gmx.de> Am 14.05.2009 20:12, Neal Gafter schrieb: > On Thu, May 14, 2009 at 10:39 AM, Ulf Zibis > wrote: > > Am 14.05.2009 16:43, Maurizio Cimadamore schrieb: > > Ulf Zibis wrote: > >> Hm, precisely I meant, if there is any difference in the > instantiated > >> object, and it's behaviour. Is it? > >> > > The instantiated object will be similar but given the class: > > > > class Cell { > > X x; > > Cell(X x) {this.x = x;} > > } > > > > the following code is unsafe: > > > > Cell cs = new Cell(1); //unchecked warning > > String s = cs.x; //CCE at runtime > > > Again: Why couldn't compiler reject this as error, or is there any > reason, why not? > > > The compiler may not reject this because there is no static error > according to the rules of the language as defined by the Java Language > Specification. So no functionality would break, if this accordingly would be upgraded in the Java Language Specification? -Ulf From Alex.Buckley at Sun.COM Thu May 14 15:51:16 2009 From: Alex.Buckley at Sun.COM (Alex Buckley) Date: Thu, 14 May 2009 15:51:16 -0700 Subject: Notes on implementing concise calls to constructors with type parameters Message-ID: <4A0CA064.5060901@sun.com> Ulf, you ask why: Cell cs = new Cell(1); //unchecked warning String s = cs.x; //CCE at runtime cannot be rejected at compile-time, presumably with an error rather than a warning on the assignment. The answer is migration compatibility: it is desirable for new, generified code (Cell cs = ...) to be able to call legacy, ungenerified code (that returns a raw Cell type). There is a potential CCE resulting from this call - as indeed there is anytime raw types are used by generified code - so the language requires a compile-time WARNING when this migration feature is used. There is no conceivable "upgrade" to this behavior in the JLS. For the record, this is nothing to do with erasure/reification. Alex From neal at gafter.com Thu May 14 15:56:18 2009 From: neal at gafter.com (Neal Gafter) Date: Thu, 14 May 2009 15:56:18 -0700 Subject: Notes on implementing concise calls to constructors with type parameters In-Reply-To: <4A0C8DC3.2060506@gmx.de> References: <4A0AFA1E.8020109@sun.com> <4A0B0A4E.30908@gmx.de> <15e8b9d20905131100h49023210kb3d5edc578b78987@mail.gmail.com> <4A0C2273.7020404@gmx.de> <4A0C2E04.8000504@sun.com> <4A0C574E.4030305@gmx.de> <15e8b9d20905141112y38835adag905e10e4373a8b45@mail.gmail.com> <4A0C8DC3.2060506@gmx.de> Message-ID: <15e8b9d20905141556l2f15bc92n695cb51e3073c15e@mail.gmail.com> On Thu, May 14, 2009 at 2:31 PM, Ulf Zibis wrote: > So no functionality would break, if this accordingly would be upgraded in > the Java Language Specification? I have no way to tell without knowing what specification change you have in mind. From Ulf.Zibis at gmx.de Thu May 14 16:00:32 2009 From: Ulf.Zibis at gmx.de (Ulf Zibis) Date: Fri, 15 May 2009 01:00:32 +0200 Subject: Notes on implementing concise calls to constructors with type parameters In-Reply-To: <4A0CA064.5060901@sun.com> References: <4A0CA064.5060901@sun.com> Message-ID: <4A0CA290.2080403@gmx.de> Am 15.05.2009 00:51, Alex Buckley schrieb: > Ulf, you ask why: > > Cell cs = new Cell(1); //unchecked warning > String s = cs.x; //CCE at runtime > > cannot be rejected at compile-time, presumably with an error rather than > a warning on the assignment. > > The answer is migration compatibility: My guess is, that this problem could be managed by javac option "-source 1.7", but I'm not sure if there are some reasons against this. -Ulf From Ulf.Zibis at gmx.de Thu May 14 16:07:32 2009 From: Ulf.Zibis at gmx.de (Ulf Zibis) Date: Fri, 15 May 2009 01:07:32 +0200 Subject: Notes on implementing concise calls to constructors with type parameters In-Reply-To: <15e8b9d20905141556l2f15bc92n695cb51e3073c15e@mail.gmail.com> References: <4A0AFA1E.8020109@sun.com> <4A0B0A4E.30908@gmx.de> <15e8b9d20905131100h49023210kb3d5edc578b78987@mail.gmail.com> <4A0C2273.7020404@gmx.de> <4A0C2E04.8000504@sun.com> <4A0C574E.4030305@gmx.de> <15e8b9d20905141112y38835adag905e10e4373a8b45@mail.gmail.com> <4A0C8DC3.2060506@gmx.de> <15e8b9d20905141556l2f15bc92n695cb51e3073c15e@mail.gmail.com> Message-ID: <4A0CA434.4080801@gmx.de> Am 15.05.2009 00:56, Neal Gafter schrieb: > On Thu, May 14, 2009 at 2:31 PM, Ulf Zibis > wrote: > > So no functionality would break, if this accordingly would be > upgraded in the Java Language Specification? > > > I have no way to tell without knowing what specification change you > have in mind. > I mean, to determine Cell cs = new Cell(1); //unchecked warning as error from compiler side. My guess is, that this problem could be managed by javac option "-source 1.7", to remain compatible, but I'm not sure if there are some reasons against this. -Ulf From neal at gafter.com Thu May 14 16:11:51 2009 From: neal at gafter.com (Neal Gafter) Date: Thu, 14 May 2009 16:11:51 -0700 Subject: Notes on implementing concise calls to constructors with type parameters In-Reply-To: <4A0CA434.4080801@gmx.de> References: <4A0AFA1E.8020109@sun.com> <4A0B0A4E.30908@gmx.de> <15e8b9d20905131100h49023210kb3d5edc578b78987@mail.gmail.com> <4A0C2273.7020404@gmx.de> <4A0C2E04.8000504@sun.com> <4A0C574E.4030305@gmx.de> <15e8b9d20905141112y38835adag905e10e4373a8b45@mail.gmail.com> <4A0C8DC3.2060506@gmx.de> <15e8b9d20905141556l2f15bc92n695cb51e3073c15e@mail.gmail.com> <4A0CA434.4080801@gmx.de> Message-ID: <15e8b9d20905141611nd217748q5723b86b19fed339@mail.gmail.com> This cannot be an error unless the Java Language Specification requires it to be an error. The language specification does not currently require it to be an error. I have no idea what change you are proposing to the specification that would result in it being an error. Without knowing that, I cannot evaluate your proposal. On Thu, May 14, 2009 at 4:07 PM, Ulf Zibis wrote: > Am 15.05.2009 00:56, Neal Gafter schrieb: > >> On Thu, May 14, 2009 at 2:31 PM, Ulf Zibis > Ulf.Zibis at gmx.de>> wrote: >> >> So no functionality would break, if this accordingly would be >> upgraded in the Java Language Specification? >> >> >> I have no way to tell without knowing what specification change you have >> in mind. >> >> > I mean, to determine > Cell cs = new Cell(1); //unchecked warning > as error from compiler side. > > My guess is, that this problem could be managed by javac option "-source > 1.7", to remain compatible, but I'm not sure if there are some reasons > against this. > > -Ulf > > > > > From forax at univ-mlv.fr Thu May 14 16:36:43 2009 From: forax at univ-mlv.fr (=?ISO-8859-1?Q?R=E9mi_Forax?=) Date: Fri, 15 May 2009 01:36:43 +0200 Subject: Notes on implementing concise calls to constructors with type parameters In-Reply-To: <15e8b9d20905141611nd217748q5723b86b19fed339@mail.gmail.com> References: <4A0AFA1E.8020109@sun.com> <4A0B0A4E.30908@gmx.de> <15e8b9d20905131100h49023210kb3d5edc578b78987@mail.gmail.com> <4A0C2273.7020404@gmx.de> <4A0C2E04.8000504@sun.com> <4A0C574E.4030305@gmx.de> <15e8b9d20905141112y38835adag905e10e4373a8b45@mail.gmail.com> <4A0C8DC3.2060506@gmx.de> <15e8b9d20905141556l2f15bc92n695cb51e3073c15e@mail.gmail.com> <4A0CA434.4080801@gmx.de> <15e8b9d20905141611nd217748q5723b86b19fed339@mail.gmail.com> Message-ID: <4A0CAB0B.4030706@univ-mlv.fr> Neal Gafter a ?crit : > This cannot be an error unless the Java Language Specification requires it > to be an error. The language specification does not currently require it to > be an error. I have no idea what change you are proposing to the > specification that would result in it being an error. Without knowing that, > I cannot evaluate your proposal. > A declarations of a raw types is an error. R?mi From forax at univ-mlv.fr Thu May 14 16:41:48 2009 From: forax at univ-mlv.fr (=?ISO-8859-1?Q?R=E9mi_Forax?=) Date: Fri, 15 May 2009 01:41:48 +0200 Subject: Notes on implementing concise calls to constructors with type parameters In-Reply-To: <4A0CA064.5060901@sun.com> References: <4A0CA064.5060901@sun.com> Message-ID: <4A0CAC3C.3030209@univ-mlv.fr> Alex Buckley a ?crit : > Ulf, you ask why: > > Cell cs = new Cell(1); //unchecked warning > String s = cs.x; //CCE at runtime > > cannot be rejected at compile-time, presumably with an error rather than > a warning on the assignment. > > The answer is migration compatibility: it is desirable for new, > generified code (Cell cs = ...) to be able to call legacy, > ungenerified code (that returns a raw Cell type). > > There is a potential CCE resulting from this call - as indeed there is > anytime raw types are used by generified code - so the language requires > a compile-time WARNING when this migration feature is used. > > There is no conceivable "upgrade" to this behavior in the JLS. > Re-read section 4.8 of the JLS :) *"It is possible that future versions of the Java programming language will disallow the use of raw types." * So it's seems that someone, one day conceive that. and with javac javac -Xlint:raw -Werror ... > For the record, this is nothing to do with erasure/reification. > > Alex > R?mi From Alex.Buckley at Sun.COM Thu May 14 16:38:04 2009 From: Alex.Buckley at Sun.COM (Alex Buckley) Date: Thu, 14 May 2009 16:38:04 -0700 Subject: Notes on implementing concise calls to constructors with type parameters In-Reply-To: <4A0CA290.2080403@gmx.de> References: <4A0CA064.5060901@sun.com> <4A0CA290.2080403@gmx.de> Message-ID: <4A0CAB5C.8010502@sun.com> Ulf Zibis wrote: > Am 15.05.2009 00:51, Alex Buckley schrieb: >> Ulf, you ask why: >> >> Cell cs = new Cell(1); //unchecked warning >> String s = cs.x; //CCE at runtime >> >> cannot be rejected at compile-time, presumably with an error rather >> than a warning on the assignment. >> >> The answer is migration compatibility: > > My guess is, that this problem could be managed by javac option "-source > 1.7", but I'm not sure if there are some reasons against this. You're effectively suggesting that migration compatibility be dropped in JDK7. A language change of this magnitude is far beyond the scope of Project Coin. Alex From Ulf.Zibis at gmx.de Thu May 14 16:46:41 2009 From: Ulf.Zibis at gmx.de (Ulf Zibis) Date: Fri, 15 May 2009 01:46:41 +0200 Subject: Notes on implementing concise calls to constructors with type parameters In-Reply-To: <4A0CAB5C.8010502@sun.com> References: <4A0CA064.5060901@sun.com> <4A0CA290.2080403@gmx.de> <4A0CAB5C.8010502@sun.com> Message-ID: <4A0CAD61.6040805@gmx.de> Am 15.05.2009 01:38, Alex Buckley schrieb: > Ulf Zibis wrote: >> Am 15.05.2009 00:51, Alex Buckley schrieb: >>> Ulf, you ask why: >>> >>> Cell cs = new Cell(1); //unchecked warning >>> String s = cs.x; //CCE at runtime >>> >>> cannot be rejected at compile-time, presumably with an error rather >>> than a warning on the assignment. >>> >>> The answer is migration compatibility: >> >> My guess is, that this problem could be managed by javac option >> "-source 1.7", but I'm not sure if there are some reasons against this. > > You're effectively suggesting that migration compatibility be dropped > in JDK7. A language change of this magnitude is far beyond the scope > of Project Coin. > > Alex > > Yes, you got it. This is exactly what I wanted to say. This potentially would make constructs like Cell cs = new Cell<>(1) _superfluous_. My additional question was, if anybody has an idea, if that would break some other things, I'm not aware of. -Ulf From Alex.Buckley at Sun.COM Thu May 14 16:50:36 2009 From: Alex.Buckley at Sun.COM (Alex Buckley) Date: Thu, 14 May 2009 16:50:36 -0700 Subject: Notes on implementing concise calls to constructors with type parameters In-Reply-To: <4A0CAC3C.3030209@univ-mlv.fr> References: <4A0CA064.5060901@sun.com> <4A0CAC3C.3030209@univ-mlv.fr> Message-ID: <4A0CAE4C.2010706@sun.com> R?mi Forax wrote: > Re-read section 4.8 of the JLS :) > *"It is possible that future versions of the Java programming language > will disallow the use of raw types." > * > So it's seems that someone, one day conceive that. Is it conceivable to drop raw types and hence migration compatibility? Sure. Is it an upgrade in behavior? Let's ask people still on 1.4 who use raw types. They may have something to say about the increased costs you'd impose on them when they try to upgrade their codebase. Alex From Ulf.Zibis at gmx.de Thu May 14 16:52:00 2009 From: Ulf.Zibis at gmx.de (Ulf Zibis) Date: Fri, 15 May 2009 01:52:00 +0200 Subject: Notes on implementing concise calls to constructors with type parameters In-Reply-To: <15e8b9d20905141611nd217748q5723b86b19fed339@mail.gmail.com> References: <4A0AFA1E.8020109@sun.com> <4A0B0A4E.30908@gmx.de> <15e8b9d20905131100h49023210kb3d5edc578b78987@mail.gmail.com> <4A0C2273.7020404@gmx.de> <4A0C2E04.8000504@sun.com> <4A0C574E.4030305@gmx.de> <15e8b9d20905141112y38835adag905e10e4373a8b45@mail.gmail.com> <4A0C8DC3.2060506@gmx.de> <15e8b9d20905141556l2f15bc92n695cb51e3073c15e@mail.gmail.com> <4A0CA434.4080801@gmx.de> <15e8b9d20905141611nd217748q5723b86b19fed339@mail.gmail.com> Message-ID: <4A0CAEA0.608@gmx.de> Am 15.05.2009 01:11, Neal Gafter schrieb: > This cannot be an error unless the Java Language Specification > requires it to be an error. So my proposal is to change the JLS in a way, that it requires to be an error. Statement: Cell cs = new Cell(1); should be defined as an error for generic type T as parameter of a constructor, if literal/expression is not assignment compatible to the substitution of T on the LHS. > The language specification does not currently require it to be an error. Currently yes. > I have no idea what change you are proposing to the specification > that would result in it being an error. Without knowing that, I > cannot evaluate your proposal. Sorry, I don't get what you are not understanding. Maybe english language problem. -Ulf > > On Thu, May 14, 2009 at 4:07 PM, Ulf Zibis > wrote: > > Am 15.05.2009 00:56, Neal Gafter schrieb: > > On Thu, May 14, 2009 at 2:31 PM, Ulf Zibis >> wrote: > > So no functionality would break, if this accordingly would be > upgraded in the Java Language Specification? > > > I have no way to tell without knowing what specification > change you have in mind. > > > I mean, to determine > > Cell cs = new Cell(1); //unchecked warning > as error from compiler side. > > My guess is, that this problem could be managed by javac option > "-source 1.7", to remain compatible, but I'm not sure if there are > some reasons against this. > > -Ulf > > > > > From Alex.Buckley at Sun.COM Thu May 14 16:57:40 2009 From: Alex.Buckley at Sun.COM (Alex Buckley) Date: Thu, 14 May 2009 16:57:40 -0700 Subject: Notes on implementing concise calls to constructors with type parameters In-Reply-To: <4A0CAD61.6040805@gmx.de> References: <4A0CA064.5060901@sun.com> <4A0CA290.2080403@gmx.de> <4A0CAB5C.8010502@sun.com> <4A0CAD61.6040805@gmx.de> Message-ID: <4A0CAFF4.2020806@sun.com> Ulf Zibis wrote: >>> My guess is, that this problem could be managed by javac option >>> "-source 1.7", but I'm not sure if there are some reasons against this. >> >> You're effectively suggesting that migration compatibility be dropped >> in JDK7. A language change of this magnitude is far beyond the scope >> of Project Coin. >> >> Alex >> > > Yes, you got it. This is exactly what I wanted to say. > This potentially would make constructs like > Cell cs = new Cell<>(1) > _superfluous_. > > My additional question was, if anybody has an idea, if that would break > some other things, I'm not aware of. Obviously dropping raw types has an impact anywhere that type names can be used. Since that's every class, interface, and variable declaration, I'm not sure we need to spend much time calculating how it would affect people moving pre-1.5 code to 1.7 - it obviously stops them cold. There is no point discussing an out-of-scope topic on this list. Alex From Ulf.Zibis at gmx.de Thu May 14 17:00:20 2009 From: Ulf.Zibis at gmx.de (Ulf Zibis) Date: Fri, 15 May 2009 02:00:20 +0200 Subject: Notes on implementing concise calls to constructors with type parameters In-Reply-To: <4A0CAE4C.2010706@sun.com> References: <4A0CA064.5060901@sun.com> <4A0CAC3C.3030209@univ-mlv.fr> <4A0CAE4C.2010706@sun.com> Message-ID: <4A0CB094.6030408@gmx.de> I'm not suggesting to _generally_ disallow raw types, but in the special given context, and only for -source 1.7. -Ulf Am 15.05.2009 01:50, Alex Buckley schrieb: > R?mi Forax wrote: > >> Re-read section 4.8 of the JLS :) >> *"It is possible that future versions of the Java programming language >> will disallow the use of raw types." >> * >> So it's seems that someone, one day conceive that. >> > > Is it conceivable to drop raw types and hence migration compatibility? > Sure. Is it an upgrade in behavior? Let's ask people still on 1.4 who > use raw types. They may have something to say about the increased costs > you'd impose on them when they try to upgrade their codebase. > > Alex > > > From Ulf.Zibis at gmx.de Thu May 14 17:07:45 2009 From: Ulf.Zibis at gmx.de (Ulf Zibis) Date: Fri, 15 May 2009 02:07:45 +0200 Subject: Notes on implementing concise calls to constructors with type parameters In-Reply-To: <4A0CAFF4.2020806@sun.com> References: <4A0CA064.5060901@sun.com> <4A0CA290.2080403@gmx.de> <4A0CAB5C.8010502@sun.com> <4A0CAD61.6040805@gmx.de> <4A0CAFF4.2020806@sun.com> Message-ID: <4A0CB251.9000702@gmx.de> Am 15.05.2009 01:57, Alex Buckley schrieb: > Ulf Zibis wrote: >>>> My guess is, that this problem could be managed by javac option >>>> "-source 1.7", but I'm not sure if there are some reasons against >>>> this. >>> >>> You're effectively suggesting that migration compatibility be >>> dropped in JDK7. A language change of this magnitude is far beyond >>> the scope of Project Coin. >>> >>> Alex >>> >> >> Yes, you got it. This is exactly what I wanted to say. >> This potentially would make constructs like >> Cell cs = new Cell<>(1) >> _superfluous_. >> >> My additional question was, if anybody has an idea, if that would >> break some other things, I'm not aware of. > > Obviously dropping raw types has an impact anywhere that type names > can be used. Since that's every class, interface, and variable > declaration, I'm not sure we need to spend much time calculating how > it would affect people moving pre-1.5 code to 1.7 - it obviously stops > them cold. It should have stopped them more cold in experiencing a consequently occurring CCE at runtime. ;-) -Ulf From Alex.Buckley at Sun.COM Thu May 14 17:08:17 2009 From: Alex.Buckley at Sun.COM (Alex Buckley) Date: Thu, 14 May 2009 17:08:17 -0700 Subject: Notes on implementing concise calls to constructors with type parameters In-Reply-To: <4A0CB094.6030408@gmx.de> References: <4A0CA064.5060901@sun.com> <4A0CAC3C.3030209@univ-mlv.fr> <4A0CAE4C.2010706@sun.com> <4A0CB094.6030408@gmx.de> Message-ID: <4A0CB271.3040308@sun.com> http://blogs.sun.com/darcy/entry/criteria_for_desirable_small_language Dropping raw types at any or all points in the language clearly does not meet either goal of Project Coin, and I'm not going to continue this discussion further. Alex Ulf Zibis wrote: > I'm not suggesting to _generally_ disallow raw types, but in the special > given context, and only for -source 1.7. > > -Ulf > > > Am 15.05.2009 01:50, Alex Buckley schrieb: >> R?mi Forax wrote: >> >>> Re-read section 4.8 of the JLS :) >>> *"It is possible that future versions of the Java programming >>> language will disallow the use of raw types." >>> * >>> So it's seems that someone, one day conceive that. >>> >> >> Is it conceivable to drop raw types and hence migration compatibility? >> Sure. Is it an upgrade in behavior? Let's ask people still on 1.4 who >> use raw types. They may have something to say about the increased >> costs you'd impose on them when they try to upgrade their codebase. >> >> Alex >> >> >> > From Alex.Buckley at Sun.COM Thu May 14 17:15:21 2009 From: Alex.Buckley at Sun.COM (Alex Buckley) Date: Thu, 14 May 2009 17:15:21 -0700 Subject: Notes on implementing concise calls to constructors with type parameters In-Reply-To: <4A0CB251.9000702@gmx.de> References: <4A0CA064.5060901@sun.com> <4A0CA290.2080403@gmx.de> <4A0CAB5C.8010502@sun.com> <4A0CAD61.6040805@gmx.de> <4A0CAFF4.2020806@sun.com> <4A0CB251.9000702@gmx.de> Message-ID: <4A0CB419.5000800@sun.com> Ulf Zibis wrote: >> Obviously dropping raw types has an impact anywhere that type names >> can be used. Since that's every class, interface, and variable >> declaration, I'm not sure we need to spend much time calculating how >> it would affect people moving pre-1.5 code to 1.7 - it obviously stops >> them cold. > > It should have stopped them more cold in experiencing a consequently > occurring CCE at runtime. ;-) Which they knew might happen because of the unchecked warning at the assignment, giving them a chance to identify potential heap pollution and upgrade certain uses of raw types at their own pace. From forax at univ-mlv.fr Thu May 14 17:25:50 2009 From: forax at univ-mlv.fr (=?ISO-8859-1?Q?R=E9mi_Forax?=) Date: Fri, 15 May 2009 02:25:50 +0200 Subject: Notes on implementing concise calls to constructors with type parameters In-Reply-To: <4A0CAE4C.2010706@sun.com> References: <4A0CA064.5060901@sun.com> <4A0CAC3C.3030209@univ-mlv.fr> <4A0CAE4C.2010706@sun.com> Message-ID: <4A0CB68E.3020306@univ-mlv.fr> Alex Buckley a ?crit : > R?mi Forax wrote: >> Re-read section 4.8 of the JLS :) >> *"It is possible that future versions of the Java programming >> language will disallow the use of raw types." >> * >> So it's seems that someone, one day conceive that. > > Is it conceivable to drop raw types and hence migration compatibility? > Sure. Is it an upgrade in behavior? Let's ask people still on 1.4 or 1.3.1. > who use raw types. They may have something to say about the increased > costs you'd impose on them when they try to upgrade their codebase. First we talk about source compatibility, not binary one. Second, there is no migration compat problem if javac can read source in 1.4 and compile them to 1.7. and not stupidly require source 1.5 if target is 1.5, but you already know that. So if there is a raw type the compiler can suggest that source should be compiled with -source 1.6 Third, Are you one of the guys that decide that if you want to use module you need to change the layout of the directories of the sources ? Backward compatibility is the main goal, if it doesn't narrow the future. But I agree with you that this is not a small change, so not for 1.7. > > Alex R?mi From howard.lovatt at iee.org Thu May 14 20:35:53 2009 From: howard.lovatt at iee.org (Howard Lovatt) Date: Fri, 15 May 2009 13:35:53 +1000 Subject: Notes on implementing concise calls to constructors with type parameters Message-ID: <3dd3f56a0905142035l5eca4620l31bb769f467cacfc@mail.gmail.com> A source statement would be great at dealing with this problem - pity source hasn't made it into 7 then we could fix this problem in 8. -- Howard. R?mi Forax wrote: >Alex Buckley a ?crit : >> R?mi Forax wrote: >>> Re-read section 4.8 of the JLS :) >>> *"It is possible that future versions of the Java programming >>> language will disallow the use of raw types." >>> * >>> So it's seems that someone, one day conceive that. >> >> Is it conceivable to drop raw types and hence migration compatibility? >> Sure. Is it an upgrade in behavior? Let's ask people still on 1.4 >or 1.3.1. >> who use raw types. They may have something to say about the increased >> costs you'd impose on them when they try to upgrade their codebase. > >First we talk about source compatibility, not binary one. >Second, there is no migration compat problem if javac can read source in >1.4 and compile them to 1.7. >and not stupidly require source 1.5 if target is 1.5, but you already >know that. >So if there is a raw type the compiler can suggest that source should be >compiled with -source 1.6 >Third, Are you one of the guys that decide that if you want to use module >you need to change the layout of the directories of the sources ? > >Backward compatibility is the main goal, if it doesn't narrow the future. > >But I agree with you that this is not a small change, so not for 1.7. > > > Alex >R?mi From Joe.Darcy at Sun.COM Thu May 14 22:14:38 2009 From: Joe.Darcy at Sun.COM (Joseph D. Darcy) Date: Thu, 14 May 2009 22:14:38 -0700 Subject: Simply implicit method invocation chaining (update) In-Reply-To: <49D13CEB.50208@gmx.de> References: <49D13CEB.50208@gmx.de> Message-ID: <4A0CFA3E.1040606@sun.com> Catching up on proposal responses, if one of the problems this proposal is meant to address is overly-long variable names, a much simpler solution is to use a local variable with a short name! While fluent interfaces are fine, I don't think using a language change to retrofit this pattern of API usage on code not written that way is the best use of the language change budget. -Joe Ulf Zibis wrote: > AUTHOR(S): Ulf Zibis, Cologne, Germany > > OVERVIEW > FEATURE SUMMARY: Simply implicit method invocation chaining. > MAJOR ADVANTAGE: > - Avoids casting in many situations. > - Code would become more legible. > MAJOR BENEFIT: > This proposal would programmers motivate to write short, compact and > best legible code. Because of the need of casting, programmers often > avoid the method-chaining, as it sacrifices one legibility win against > an other. Additionally Semantic of, in fact, void methods would become > more clear. > Secondly legibility would increase, if multiple repetition of initial > referred instance identifier could be avoided. > MAJOR DISADVANTAGE: > Many existing methods should be reviewed, by refactoring return types to > void, to profit from this feature. > ALTERNATIVES: No > > EXAMPLES > SIMPLE EXAMPLE: > After this change: > CharBuffer X = > CharBuffer.allocate(26).position(2).put("C").position(25).put("Z"); > Before this change: > CharBuffer X = ((CharBuffer)((CharBuffer)CharBuffer.allocate(26) > .position(2)).put("C").position(25)).put("Z"); > or: > CharBuffer X = CharBuffer.allocate(26); > X.position(2); > X.put("C").position(25); > X.put("Z"); > Comment: nit-pickers would say, that position(int pos, char c) could be > used in this example, but everyone who has ever worked with nio buffers > should know, of which worries I'm speaking about. > ADVANCED EXAMPLE: > After this change: > String mySub = myVeryLongNamedString.subString(.indexOf("C"), > .indexOf("Q")); > Before this change: > String mySub = myVeryLongNamedString.subString( > myVeryLongNamedString.indexOf("C"), > myVeryLongNamedString.indexOf("Q")); > > DETAILS > SPECIFICATION: > Grammar should allow that method invocation could refer backward to > instance of most right suitable object identifier, if direct preceding method returns void. > '.' starting expressions should refer to most right suitable object identifier. > COMPILATION: > Compile: > CharBuffer X = > CharBuffer.allocate(26).position(2).put("C").position(25).put("Z"); > to: > CharBuffer X = CharBuffer.allocate(26); > X.position(2); > X.put("C"); > X.position(25); > X.put("Z"); > Compile: > CharBuffer X = CharBuffer.allocate(26); > CharBuffer Y = X.position(2); > to: > CharBuffer X = CharBuffer.allocate(26); > CharBuffer Y = X; > Y.position(2); > Compile: > String mySub = myVeryLongNamedString.subString(.indexOf("C"), > .indexOf("Q")); > to: > String mySub = myVeryLongNamedString.subString( > myVeryLongNamedString.indexOf("C"), > myVeryLongNamedString.indexOf("Q")); > > Compiler should skip castings from legacy code. > Class file format would not be affected. > Bytecode would not be affected. > TESTING: > Compiler should compile given examples without errors. > Bytecode of 1. example should be same than before if casting would be > eliminated. > Bytecode of 2. example should be identical. > LIBRARY SUPPORT: No supporting libraries are needed for the feature? > REFLECTIVE APIS: There should not be any affection to reflection API. > OTHER CHANGES: > Legacy API methods returning this should be refactored to void. > A list of affected APIs should be published (see MIGRATION). > MIGRATION: > A list of refactored APIs should be published. To take advantage of this > change, programmers should scan their code base for usage of those APIs, > and refactor the regarding statements manually or by usage of regex > patterns. Anyway no refactoring is needed to stay compatible. > > COMPATIBILITY > BREAKING CHANGES: > No previously valid programs are now invalid. > EXISTING PROGRAMS: > Source and class files of earlier platform versions interact with the > feature without any notice. > > REFERENCES > http://mail.openjdk.java.net/pipermail/coin-dev/2009-March/000107.html > https://jdk-collaboration.dev.java.net/servlets/ProjectForumMessageView?messageID=15541&forumID=1463 > EXISTING BUGS: > http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6451131 > http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4774077 > http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=799586 > URL FOR PROTOTYPE (optional): > > > > > > > From Joe.Darcy at Sun.COM Thu May 14 22:22:16 2009 From: Joe.Darcy at Sun.COM (Joseph D. Darcy) Date: Thu, 14 May 2009 22:22:16 -0700 Subject: Proposal: Sameness operators In-Reply-To: <27F0EA9D-8936-4330-A5FE-97F522C290F0@zwitserloot.com> References: <2729451.1238478698193.JavaMail.root@mswamui-andean.atl.sa.earthlink.net> <49D3B1E3.8070109@sun.com> <88885FEA-F3CF-4D47-8379-7571E9E31F76@zwitserloot.com> <49D4AF9D.9090407@sun.com> <49D4B40F.2010100@optrak.co.uk> <27F0EA9D-8936-4330-A5FE-97F522C290F0@zwitserloot.com> Message-ID: <4A0CFC08.4020505@sun.com> Catching up on commenting... Reinier Zwitserloot wrote: > The argument that .compareTo should not be used because it isn't > entirely congruent with either the meaning of .equals() or the > meanings of all the comparison operators (from == to <) on the > primitives, just doesn't hold water, for this simple reason: > > They make absolutely no sense now, either, and nobody cares about that. > I care about that! ;-) The situation is complicated, but there are reasons for the design of the various floating-point comparison operations. > Here's some fun facts (all asserts are true): > > int x = 0/0; //ArithmeticException > double x = 0/0.0; //okay, x = NaN > double y = 0/0.0; > > assert x != y; > assert ! (x == y); > assert Double.valueOf(x).equals(Double.valueOf(y)); //WTF! > assert Double.valueOf(x).equals(y); //WTF! > > Clearly, equals is fundamentally broken. We need a new equals! Oh no! > Yes, strange but true, the "equals" relation on floating-point values defined by IEEE 754 is *not* an equivalence relation. This odd situation arose to accommodate NaNs. NaNs break the trichotomy of exactly one of the less than, equal to, or greater relations holding between values. A NaN is *unordered* compared to any floating-point value, even itself. Since NaNs are Not-a-Numbers they do not obey the rules of normal numerical values. While the IEEE 754 design is driven by numerical programming concerns, at times there is a need for a true equivalence relation on floating-point values as well as a total ordering. For example, numerical regression tests in the JDK include a boolean equivalent(double, double) method that returns true if both values are NaN or if the values are ==. Another oddity in the IEEE 754 equals relation is that two distinct values, -0.0 and +0.0, are equal to each other. These two values are *not* the same under IEEE 754 operations because 1.0/-0.0 is negative infinity while 1.0/+0.0 is positive infinity. For sorting, a real total order is needed. Arrays.sort(double[]) uses the total ordering from Double.compareTo where -0.0 is less than 0.0 and NaNs are qual to one another and greater than positive infinity and. [snip] > 4. BigDecimal and BigInteger are changed to implement > Comparable instead. The fact that they currently don't is > something I don't really understand would consider filing as a bug if > I worked more with mixed BI/BD and primitives math. By doing this, > something like: > Number should really have b neen an interface more clearly just meaning "convertible to a primitive type;" all Number lets you do is convert to the primitive types and converting to primitive is not necessarily sufficient to let you do anything else with the value. For example, one could write a Complex class that extended Number and a quaterion class that extended Number too. A class like BigDecimal can't implement a sensible comparison on an unknown class that just happens to implement Number. Even properly comparing numerical values of Number classes within the JDK is tricky; without specific instaneof checks, both the double value and long value may need to be extracted even for the primitive types. -Joe From Joe.Darcy at Sun.COM Thu May 14 22:22:57 2009 From: Joe.Darcy at Sun.COM (Joseph D. Darcy) Date: Thu, 14 May 2009 22:22:57 -0700 Subject: PROPOSAL: @OverrideAll annotation In-Reply-To: References: Message-ID: <4A0CFC31.20509@sun.com> Gabriel Belingueres wrote: > Hi, > > I've written a new feature that might be comfortable to use for > someone. All input is welcomed. > > Regards, > Gabriel > > PROJECT COIN SMALL LANGUAGE CHANGE PROPOSAL FORM v1.0 > > AUTHOR(S): Gabriel Belingueres > > OVERVIEW > > Add an @OverrideAll annotation to allow a class to override all > inherited methods with a trivial implementation. The resulting class > then could be used as the basis for a Null Object pattern (or even a > basic Mock object.) > > > FEATURE SUMMARY: > > The proposed @OverrideAll annotation will allow the class to override > all methods (from its superclasses and implemented interfaces) with a > trivial body, but the defined class can choose to implement specific > methods, replacing those that would be produced automatically by the > annotation. > > > MAJOR ADVANTAGE: > > Less coding for implementing Null Objects, or simple tests. > Catching up on commenting, this sounds like a fine job for an IDE and, as you note, this capability already exists in some IDEs. -Joe From Joe.Darcy at Sun.COM Thu May 14 22:23:14 2009 From: Joe.Darcy at Sun.COM (Joseph D. Darcy) Date: Thu, 14 May 2009 22:23:14 -0700 Subject: Proposal: Accepting a subclass as an element type in a for loop In-Reply-To: References: Message-ID: <4A0CFC42.1090402@sun.com> Jean-Louis Ardoint wrote: > I'm maybe a bit too late. Here's my proposal anyway. > > > > -- Jean-Louis Ardoint > > > > Accepting a subclass as an element type in a for loop > > > Catching up on proposal comments, I agree with the previous replies on the list that this scenario is more than adequately handled by filtering library methods. FYI, one class implementing these kinds of filters in the JDK is javax.lang.model.util.ElementFilter. -Joe From Joe.Darcy at Sun.COM Thu May 14 22:24:19 2009 From: Joe.Darcy at Sun.COM (Joseph D. Darcy) Date: Thu, 14 May 2009 22:24:19 -0700 Subject: Naked dot - accessing object fields through unqualified "." [C1] In-Reply-To: <17188EC0-2C56-4AE1-8B4E-11F4B3843341@zwitserloot.com> References: <11840193.1238294525158.JavaMail.root@mswamui-andean.atl.sa.earthlink.net> <17188EC0-2C56-4AE1-8B4E-11F4B3843341@zwitserloot.com> Message-ID: <4A0CFC83.7080501@sun.com> Reinier Zwitserloot wrote: > 'Self-assignment is forbidden' would not be backwards compatibile. > Yes, such code would most likely be a bug, but its still an issue. It > would have to be a warning, at best. > > However: > > Every single external java compiler I know of will warn you when you > self-assign. Eclipse does it. So does netbeans. So does IDEA. So does > pmd. So does findbugs. > > > If you internalize the self-assignment warning, where do you stop? > There are literally hundreds of 'duh, that must be a bug' warnings you > could generate. Not all of them are as obvious, or as non-contentious, > as 'self assignment'. So, where do you stop? Do we use the glacial > nature of the language changes process to set this up? I say: No. The > community has done a fine job of addressing these issues by creating > code checkers. So, I'd instead suggest: > > Any improvements to java core in this area should focus on improving > the ability for external tools to integrate better. For example, a way > to extend @SuppressWarnings with additional keywords would be great. A > way to let javac auto-find (via the SPI system) 'warning/error' > plugins would be another fine idea. Having any kind of plugin system > for the official javac to give other tools a go at creating warnings > and errors on the AST that javac's parser is building would be good > Catching up on responding to Coin email, that plugin system exists in javac as of JDK 6 in the form of annotation processors, the the -processor option etc. Annotation processing in apt and javac was always intended to provide a general meta-programming facility and not be specific to annotations. "Checking" processors occur at the front of the processor list, process "*" (all annotations, including the empty set), and claim no annotations; any annotation processor that is invoked is passed all types, not just the ones with particular annotations. Delving into the javac-specific tree API, full program information can be reconstructed from within an annotation processor. -Joe From Joe.Darcy at Sun.COM Thu May 14 22:26:56 2009 From: Joe.Darcy at Sun.COM (Joseph D. Darcy) Date: Thu, 14 May 2009 22:26:56 -0700 Subject: Naked dot - accessing object fields through unqualified In-Reply-To: <19432589.1238742258930.JavaMail.root@mswamui-thinleaf.atl.sa.earthlink.net> References: <19432589.1238742258930.JavaMail.root@mswamui-thinleaf.atl.sa.earthlink.net> Message-ID: <4A0CFD20.8070906@sun.com> Derek Foster wrote: > Replies inline. > > -----Original Message----- > >> From: Reinier Zwitserloot >> Sent: Mar 31, 2009 9:03 AM >> To: Derek Foster >> Cc: coin-dev at openjdk.java.net >> Subject: Re: Naked dot - accessing object fields through unqualified "." [C1] >> >> 'Self-assignment is forbidden' would not be backwards compatibile. >> Yes, such code would most likely be a bug, but its still an issue. It >> would have to be a warning, at best. >> > > Personally, I think it should be an error, since there seems to be no valid reason to do it, and it almost certainly indicates a bug. I think that compilers should default to being in a 'strict' mode where things like this that have been found to be bad ideas with virtually no upside are treated as illegal, even if that makes them not fully backwards compatible. For backwards compatibility, there could be a command-line switch to turn off strict mode if necessary for compiling old code. > > Some other things I'd like to see in this category: > > * Having an abstract class with a constructor that has 'public' or 'private' access. > > * Using C-style array declarations. (int x[] instead of int[] x) > > I could probably think of a few more. > > [snip] Some checks like this could be added as javac's lint analyzes and the lint warnings can be turned into errors using another flag to javac on an opt-in basis. You can implement fatal warnings yourself using annotation processors in javac which access the javac-specific tree API; in a running annotation processor, the javax.annotation.processing.Messager object can be used to raise an error just as if javac itself did. -Joe From Joe.Darcy at Sun.COM Thu May 14 22:40:30 2009 From: Joe.Darcy at Sun.COM (Joseph D. Darcy) Date: Thu, 14 May 2009 22:40:30 -0700 Subject: PRE-PROPOSAL: Simple operator overloading. In-Reply-To: References: Message-ID: <4A0D004E.608@sun.com> rssh at gradsoft.com.ua wrote: > Permanent URL: http://docs.google.com/Doc?id=dhhvggr8_18djp85shk > > Probably too big, but anyway. > > As I remember, alternative proposal (made [] and []= syntax sugar on > well-known interfaces, as with for-each loop) still not submitted. If > anybody want submit such proposal, then it is possible to reuse > JLS-changed for 15.26.1 from there. > > > OVERVIEW: > FEATURE SUMMARY: > > Add possibility to overloaded common subset of java operators for own > classes. > Catching up on responses, while adding operators for numerical types would certainly improve the readability of numerical code using non-primitive types, for Project Coin and JDK 7, I think efforts in this area should focus on getting [] and []= for collection-like types since they are much more often used than numerical types in Java programming. -Joe From Joe.Darcy at Sun.COM Thu May 14 22:40:41 2009 From: Joe.Darcy at Sun.COM (Joseph D. Darcy) Date: Thu, 14 May 2009 22:40:41 -0700 Subject: PROPOSAL: Allow the class literal of the surrounding class to be referenced with the 'class' keyword In-Reply-To: <34374.122.49.204.51.1238400522.squirrel@webmail.velocity.net.au> References: <34374.122.49.204.51.1238400522.squirrel@webmail.velocity.net.au> Message-ID: <4A0D0059.8030106@sun.com> Peter Runge wrote: > PROJECT COIN SMALL LANGUAGE CHANGE PROPOSAL FORM v1.0 > > AUTHOR(S): Peter Runge > prunge at velocitynet dot com dot au > > OVERVIEW > > FEATURE SUMMARY: > > Allow the class literal of the surrounding class to be referenced with > the 'class' keyword. > Hello. Catching up on proposal commenting, I don't think the small benefit of eliding the leading class name in a class literal used inside a class justifies the effort required to investigate the implications and implementation of this change. -Joe From Joe.Darcy at Sun.COM Thu May 14 22:40:54 2009 From: Joe.Darcy at Sun.COM (Joseph D. Darcy) Date: Thu, 14 May 2009 22:40:54 -0700 Subject: Proposal: Type inference for variable definition/initialization using the 'auto' keyword. In-Reply-To: References: Message-ID: <4A0D0066.1060701@sun.com> Tim Lebedkov wrote: > Type inference for variable definition/initialization using the 'auto' keyword. > > AUTHOR(S): Tim Lebedkov > > OVERVIEW > > Provide a two sentence or shorter description of these five aspects of > the feature: > > FEATURE SUMMARY: Should be suitable as a summary in a language tutorial. > > This proposal addresses the addition of type inference for > variable definitions to the Java programming language using the 'auto' > keyword instead of specific type name. > > For example, consider the following assignment statement: > > Map> anagrams = new HashMap>(); > > This is rather lengthy, so it can be replaced with this: > > auto anagrams = new HashMap>(); > > and anagrams is automatically typed as HashMap> > > MAJOR ADVANTAGE: What makes the proposal a favorable change? > > Generics have had a tremendously positive impact on type safety in the > Java programming language. They have made it possible to provide > static guarantees about the type of instances used by other classes, > preventing entire classes of runtime errors from occurring. However, > generics have added complexity to Java, making the code far more > verbose and occasionally difficult to read. Although solving this > problem is well outside the scope of this proposal, a limited form of > type inference would remove unnecessary redundancy from the language. > Even without generics it seems unnecessary to duplicate type names for > simple variable definitions/assignments like: > > Integer a = new Integer(1023); > > MAJOR BENEFIT: Why is the platform better if the proposal is adopted? > > Less code and no duplication has a positive impact on many things: > - faster typing/faster code changes > - easier code changing without IDE assistance > - code versioning diffs are more clear > > MAJOR DISADVANTAGE: There is always a cost. > > - it could be harder to read the code. > - auto will be a keyword and may break some old code > > ALTERNATIVES: Can the benefits and advantages be had some way without > a language change? > > no > > Catching up on proposal comments, I think the core benefits of using "auto" or "final" on the left hand side for variables are achieved with the diamond operator that allows one to elide type parameters on the right hand side. IMO, the diamond solution of specifying the variable type fully on the left and then specifying only the implementation type without redundant, repeated type parameters on the right is more in keeping with Java coding style. -Joe From Joe.Darcy at Sun.COM Thu May 14 22:41:10 2009 From: Joe.Darcy at Sun.COM (Joseph D. Darcy) Date: Thu, 14 May 2009 22:41:10 -0700 Subject: PROPOSAL: Language Escape Operator In-Reply-To: <1238110511.49cc112f28285@www.paradise.net.nz> References: <1238110511.49cc112f28285@www.paradise.net.nz> Message-ID: <4A0D0076.90902@sun.com> Hello Bruce. More proposal catchup... brucechapman at paradise.net.nz wrote: > Title Language Escape Operator > > latest html version at http://docs.google.com/Doc?docid=dcvp3mkv_9gdg3jfhg > > AUTHOR(S): Bruce Chapman > > OVERVIEW > > > FEATURE SUMMARY: > > There is great potential for syntactic sugars to be implemented in tools rather > than the Java language. One requirement of such a mechanism is that the sugared > form is NOT valid java source code (otherwise the meaning is ambiguous - is a > piece of code intended as is, or intended to be desugared). In order to future > proof such mechanisms it is also desirable that such a syntactic sugar form will > never become a valid java form due to some unanticipated future language change. > > > A simple way to ensure this is to reserve a character as a language escape, > effectively it indicates that source code is at that point escaping from the > java language. > Hmm, not sure how I feel about reserving a character to provide for language escape mechanisms; it is certainly easy to implement today though ;-) In the beginning, Java did reserve certain keywords to prevent their (mis)use ("auto", "goto") and at least "auto" has appeared in a coin proposal or two. There is certainly potential for code transformers to provide useful services, but in the absence of widely-used facilities around these lines, I'm inclined to keep the characters available for future changes within Java itself. -Joe From Joe.Darcy at Sun.COM Thu May 14 22:41:31 2009 From: Joe.Darcy at Sun.COM (Joseph D. Darcy) Date: Thu, 14 May 2009 22:41:31 -0700 Subject: PROPOSAL: Simplified StringBuffer/StringBuilder syntax In-Reply-To: <15886363.1238270778184.JavaMail.root@mswamui-andean.atl.sa.earthlink.net> References: <15886363.1238270778184.JavaMail.root@mswamui-andean.atl.sa.earthlink.net> Message-ID: <4A0D008B.6030604@sun.com> Catching up on proposals... Derek Foster wrote: > Simplified StringBuffer/StringBuilder syntax. > > AUTHOR: Derek Foster > > > OVERVIEW > > The Java language is designed to use immutable strings. Strings are intended to be constructed via one of two builder classes: StringBuffer (older, and slower due to synchronization) and StringBuilder (newer, and faster). Using these classes can make constructing Strings out of multiple pieces considerably more efficient than repeatedly concatenating strings together. These classes are often used by the Java compiler to concatenate strings behind the scenes, so that an expression like this: > > String foo = "abcd" + 42 + "efgh"; > > might be compiled as: > > String foo = new StringBuilder("abcd").append(42).append("efgh"); > The subset of this proposal I'm most sympathetic to is having ""+=" on StringBuffer and StringBuilder desugar into a call to append. Offhand, I think that could be a mostly localized specification change that indicated the String{Buffer, Builder} was being mutated. Coming up with String => StringBuffer conversion rules in assignment contexts is possible, but not necessarily desirable IMO. An analysis of the applicability of just this change to a corpus of code might be informative. -Joe From Joe.Darcy at Sun.COM Thu May 14 22:41:43 2009 From: Joe.Darcy at Sun.COM (Joseph D. Darcy) Date: Thu, 14 May 2009 22:41:43 -0700 Subject: PROPOSAL: open and close brace optional for single statement try, catch, finally, method declaration In-Reply-To: References: Message-ID: <4A0D0097.6090606@sun.com> Catching up on responses... Glenn A.P. Marshall wrote: > PROJECT COIN SMALL LANGUAGE CHANGE PROPOSAL FORM v1.0 > > AUTHOR(S): Glenn Marshall > > *OVERVIEW > > FEATURE SUMMARY: > > Make open and close brace optional for single statement try, catch, > finally, method declaration. > > (the relatively rarely used single statement static initializer would > still require braces under this proposal, due to its relative rarity). > > MAJOR ADVANTAGE: > > Simple, single statement try blocks, catch blocks, and single > statement methods (for example, getter methods) are very common in > Java code. Unlike if, while and do statements, the open and close > braces are mandatory even when the target of the keyword is a single > statement. This requirement needlessly clutters the code with > unneeded open and close braces, increases code complexity slightly > and decreases readability. Removing this requirement addresses a > syntactic inconsistency in Java, whereby braces are required for some > single statement keyword targets but not others. > > MAJOR BENEFIT: > > More readable code, needless syntactic 'noise' removed, consistent > treatment of common single statement keyword targets. Since single > statement try, catch, method are very common, these benefits could be > applied many times to a typical large Java program. > While there is a little extra clutter in code because of this restriction, I don't view that noise as a pressing problem and the lack of an unambiguous grammar in the proposal and the absence of a prototype do not argue in the proposal's favor. -Joe From Joe.Darcy at Sun.COM Thu May 14 22:42:01 2009 From: Joe.Darcy at Sun.COM (Joseph D. Darcy) Date: Thu, 14 May 2009 22:42:01 -0700 Subject: Some notes on Elvis and Other Null-Safe Operators In-Reply-To: <171AADE5-112F-43EB-AEED-4E502EE0914E@googlemail.com> References: <171AADE5-112F-43EB-AEED-4E502EE0914E@googlemail.com> Message-ID: <4A0D00A9.3080304@sun.com> Mark Mahieu wrote: > Below are a few observations I compiled while building and testing > the prototype for Elvis and friends, in case they're of interest. > They are in note form and fairly random order, so please shout if > anything isn't clear. > > Mark > > > -------- > > > Elvis operator can be approximated as a library method: > > static T elvis(T t1, T t2) { return t1 != null ? t1 : t2; } > > In a core-libs round table recording (at http://mail.openjdk.java.net/ > pipermail/core-libs-dev/2009-April/001406.html) the possibility of > adding core library methods for common null-handling tasks is > mentioned, such as throwing a standard exception if a supplied > argument is null (presumably similar to methods in > com.google.common.base.Preconditions). Is it reasonable to implement > the Elvis operator as a language change but other null-handling > facilities as library changes? > A belated reply, in general and for null handling in particular, addressing the problem with libraries is preferable to addressing the problem with a language change. -Joe From howard.lovatt at iee.org Fri May 15 00:26:43 2009 From: howard.lovatt at iee.org (Howard Lovatt) Date: Fri, 15 May 2009 17:26:43 +1000 Subject: Notes on implementing concise calls to constructors with type parameters In-Reply-To: <15e8b9d20905140932g33fbcd7atd6c6e28f95211cb4@mail.gmail.com> References: <3dd3f56a0905132041r67710789if86d4e942987a039@mail.gmail.com> <15e8b9d20905132115r58bfe6a7naa6952e5f94c1392@mail.gmail.com> <3dd3f56a0905140543v63603bd4qed2a149fc06cb0ce@mail.gmail.com> <15e8b9d20905140932g33fbcd7atd6c6e28f95211cb4@mail.gmail.com> Message-ID: <3dd3f56a0905150026ta489f58lece1b35ee17df44d@mail.gmail.com> Neal, The algorithm I am suggesting, textual substitution of missing items, deals with the use cases yourself and Maurizio are discussing. Quick recap; local variable declaration: typeLHS [] name = new [typeRHS] [] ( ... ); The proposed algorithm is that if typeRHS is missing then typeLHS is substituted and if genericParametersRHS is missing and genericParametersLHS is present then genericParametersLHS is substituted. Consider a simple method declaration: returnType methodName ( typeLHS [] name , ... ) { ... } and a simple method call ... methodName ( new [typeRHS] [] ( ... ) , ... ); Then the same substituting of missing items algorithm given above can be used. The two examples that yourself and Maurizio have discussed would work, i.e.: *class X {* * public X( T t ) { ... }* *}* *void f( X xs ) ...* the code *f( new X( "foo" ) )* gets translated into: *f( new X( "foo" ) )* and: *void f( List xs ) ...* the following method call *f( new ArrayList() )* gets translated into: *f( new ArrayList() )* Therefore the textual substitution method proposed works for both of these cases. -- Howard. 2009/5/15 Neal Gafter : > On Thu, May 14, 2009 at 5:43 AM, Howard Lovatt > wrote: >> >> Hopefully this is?sufficiently?detailed to enable you to comment. > > This proposal is completely non-orthogonal and ignores the relationship > between the type parameters of the types on the right-hand-side (typically a > class) and the left-hand side (typically an interface).? Assuming there is a > one-to-one relationship is bad design, even though it is most frequently the > case; the compiler knows the relationships between the types and should use > it.? The proposal change the meaning of existing code (with respect to raw > types).? It isn't clear how to make this proposal orthogonal to be used > elsewhere than a variable declaration.? I suspect specifying this approach > would result in a more complex specification than either the approach I've > been advocating or the approach Maurizio has been implementing. > > ______________________________________________________________________ > This email has been scanned by the MessageLabs Email Security System. > For more information please visit http://www.messagelabs.com/email > ______________________________________________________________________ > -- -- Howard. From howard.lovatt at iee.org Fri May 15 00:34:37 2009 From: howard.lovatt at iee.org (Howard Lovatt) Date: Fri, 15 May 2009 17:34:37 +1000 Subject: PROPOSAL: open and close brace optional for single statement try, catch, finally, method declaration Message-ID: <3dd3f56a0905150034v3a30d0bfr66885137ae15805@mail.gmail.com> I would go the other way and make braces compulsory in all cases including single line blocks for if, while, etc. I say this because I have found missing braces to be a source of errors, particularly for newbies. -- Howard. From Ulf.Zibis at gmx.de Fri May 15 01:08:59 2009 From: Ulf.Zibis at gmx.de (Ulf Zibis) Date: Fri, 15 May 2009 10:08:59 +0200 Subject: Simply implicit method invocation chaining (update) In-Reply-To: <4A0CFA3E.1040606@sun.com> References: <49D13CEB.50208@gmx.de> <4A0CFA3E.1040606@sun.com> Message-ID: <4A0D231B.7000503@gmx.de> Am 15.05.2009 07:14, Joseph D. Darcy schrieb: > Catching up on proposal responses, if one of the problems this > proposal is meant to address is overly-long variable names, a much > simpler solution is to use a local variable with a short name! Thanks for catching up my proposal for the first time. I admit, that the given example was exaggerated, but even with short names, it's annoying to the author _and_ the reader if same name is multiple repeated, and it hampers the view to the essence of the statement. To remain simple, my example only repeats it 2 times, but I have seen examples with more repetitions. But OK, this part is the advanced part of my proposal. > > While fluent interfaces are fine, I don't think using a language > change to retrofit this pattern of API usage on code not written that > way is the best use of the language change budget. Well, I guess the cost is very low, because it's only about simple textual substitution from compiler side. -Ulf From Ulf.Zibis at gmx.de Fri May 15 01:24:37 2009 From: Ulf.Zibis at gmx.de (Ulf Zibis) Date: Fri, 15 May 2009 10:24:37 +0200 Subject: Notes on implementing concise calls to constructors with type parameters In-Reply-To: <3dd3f56a0905150026ta489f58lece1b35ee17df44d@mail.gmail.com> References: <3dd3f56a0905132041r67710789if86d4e942987a039@mail.gmail.com> <15e8b9d20905132115r58bfe6a7naa6952e5f94c1392@mail.gmail.com> <3dd3f56a0905140543v63603bd4qed2a149fc06cb0ce@mail.gmail.com> <15e8b9d20905140932g33fbcd7atd6c6e28f95211cb4@mail.gmail.com> <3dd3f56a0905150026ta489f58lece1b35ee17df44d@mail.gmail.com> Message-ID: <4A0D26C5.3070007@gmx.de> +1 Am 15.05.2009 09:26, Howard Lovatt schrieb: > *class X {* > * public X( T t ) { ... }* > *}* > > > Therefore the textual substitution method proposed works for both of > these cases. > > ... and additionally it saves JLS change regarding error/warning on: X xs = new X( 1 ); ;-) If substituted by: X xs = new X( 1 ); it is clearly an error. -Ulf From Ulf.Zibis at gmx.de Fri May 15 01:53:08 2009 From: Ulf.Zibis at gmx.de (Ulf Zibis) Date: Fri, 15 May 2009 10:53:08 +0200 Subject: Notes on implementing concise calls to constructors with type parameters In-Reply-To: <4A0CB419.5000800@sun.com> References: <4A0CA064.5060901@sun.com> <4A0CA290.2080403@gmx.de> <4A0CAB5C.8010502@sun.com> <4A0CAD61.6040805@gmx.de> <4A0CAFF4.2020806@sun.com> <4A0CB251.9000702@gmx.de> <4A0CB419.5000800@sun.com> Message-ID: <4A0D2D74.1080007@gmx.de> Am 15.05.2009 02:15, Alex Buckley schrieb: > Ulf Zibis wrote: >>> Obviously dropping raw types has an impact anywhere that type names >>> can be used. Since that's every class, interface, and variable >>> declaration, I'm not sure we need to spend much time calculating how >>> it would affect people moving pre-1.5 code to 1.7 - it obviously >>> stops them cold. >> >> It should have stopped them more cold in experiencing a consequently >> occurring CCE at runtime. ;-) > > Which they knew might happen because of the unchecked warning at the > assignment, giving them a chance to identify potential heap pollution > and upgrade certain uses of raw types at their own pace. > With this same argument, following code should similar output a warning instead of a compile time error: int i; ... if (i == 7) { // error: variable not initialized ... } -Ulf From ali.ebrahimi1781 at gmail.com Fri May 15 01:57:28 2009 From: ali.ebrahimi1781 at gmail.com (Ali Ebrahimi) Date: Fri, 15 May 2009 13:27:28 +0430 Subject: Notes on implementing concise calls to constructors with type parameters Message-ID: <5ab441490905150157p5839b3eakd6062f152ba5edc0@mail.gmail.com> Am 15.05.2009 00:51, Alex Buckley schrieb: >* Ulf, you ask why: *>* *>* Cell cs = new Cell(1); //unchecked warning *>* String s = cs.x; //CCE at runtime *>* *>* cannot be rejected at compile-time, presumably with an error rather than *>* a warning on the assignment. *>* *>* The answer is migration compatibility: My answer is that using a transparent diamond operator in *instantiation of generic* types by jdk7+. The code **Cell cs = new Cell(1); * if* Cell is generic class then goto GENERIC_CASE **GENERIC_CASE: * treated as : * Cell cs = new Cell<>(1); * and this treated as: * Cell cs = new Cell<**String**>(1); * goto Next: else // raw type(legacy code) RAW_CASE: *Cell cs = new Cell(1); * Next: And finally catching compile time error. I think one of main goals of adding generic support to java language was catching run time exceptions in compile time and having robust and safe code. I don't think the *Cell* class to be a legacy code(row type)in this case. I think this particular rule can be applicable at least in Object instantiation case. if right side is not a generic type use the row type. Cell cs = new RowLegacySubCell(10); By diamond operator if we use: Cell cs = new RowLegacySubCell*<>*(10); compiler got an error, because RowLegacySubCell is not generic class(legacy code). But by my rule(no diamond operator in code) this compiles fine. because that the RowLegacySubCell class is not generic(legacy code) treated as row type. By this rule we decrease the use of row types and not dropping them totally ones. One advantage of this rule is that if some day we decided to update legacy code and generified them. By recompiling code, in this time the compiler would use the generic RowLegacySubCellclass and We would had: Cell cs = new RowLegacySubCell(10); treated as if RowLegacySubCell is generic class: Cell cs = new RowLegacySubCell<>(10); and this treated as: Cell cs = new RowLegacySubCell(10); And finally catching compile time error. I think we don'nt need to *the second* step: *Cell cs = new Cell(1); * if* Cell is generic class then goto GENERIC_CASE **GENERIC_CASE: * treated as : * Cell cs = new Cell<**String**>(1); * goto Next: else // raw type(legacy code) RAW_CASE: *Cell cs = new Cell(1); * Next: One note: By this rule we don't need to change code for using new generic versions of legacy classes. Therefore by this rule we can slowly remove row types from language. Best Regards Ali Ebrahimi From Ulf.Zibis at gmx.de Fri May 15 02:16:47 2009 From: Ulf.Zibis at gmx.de (Ulf Zibis) Date: Fri, 15 May 2009 11:16:47 +0200 Subject: Notes on implementing concise calls to constructors with type parameters In-Reply-To: <5ab441490905150157p5839b3eakd6062f152ba5edc0@mail.gmail.com> References: <5ab441490905150157p5839b3eakd6062f152ba5edc0@mail.gmail.com> Message-ID: <4A0D32FF.90102@gmx.de> Am 15.05.2009 10:57, Ali Ebrahimi schrieb: > > My answer is that using a transparent diamond operator in *instantiation > of generic* types by jdk7+. > The code > **Cell cs = new Cell(1); * > if* Cell is generic class then goto GENERIC_CASE > I guess you mean: if* new Cell(1) invokes generic type constructor then goto GENERIC_CASE > **GENERIC_CASE: > * treated as : > * Cell cs = new Cell<>(1); * > > and this treated as: > > * Cell cs = new Cell<**String**>(1); * > goto Next: > > else // raw type(legacy code) > RAW_CASE: > *Cell cs = new Cell(1); * > > Next: > > And finally catching compile time error. > Better: And finally catching compile time error for *GENERIC_CASE*, but no error for *RAW_CASE* ;-) -Ulf From ali.ebrahimi1781 at gmail.com Fri May 15 02:43:32 2009 From: ali.ebrahimi1781 at gmail.com (Ali Ebrahimi) Date: Fri, 15 May 2009 14:13:32 +0430 Subject: Notes on implementing concise calls to constructors with type parameters In-Reply-To: <4A0D32FF.90102@gmx.de> References: <5ab441490905150157p5839b3eakd6062f152ba5edc0@mail.gmail.com> <4A0D32FF.90102@gmx.de> Message-ID: <5ab441490905150243x1da93f2dw208819bf04134939@mail.gmail.com> On Fri, May 15, 2009 at 1:46 PM, Ulf Zibis wrote: > Am 15.05.2009 10:57, Ali Ebrahimi schrieb: > >> >> My answer is that using a transparent diamond operator in *instantiation >> of generic* types by jdk7+. >> The code >> **Cell cs = new Cell(1); * >> if* Cell is generic class then goto GENERIC_CASE >> >> > > I guess you mean: > > if* new Cell(1) invokes generic type constructor then goto GENERIC_CASE > I mean: if instantiated object (new Cell(1)) type(Cell) is generic class and have generic type constructor. example: List myList = new ArrayList(); treates as: GENERIC_CASE List myList = new ArrayList(); because that ArrayList is now generic class(since 1.5). But the following code: List myLegacyList = new MyCustomLegacyList(); is treated as: Raw_CASE List myLegacyList = new MyCustomLegacyList(); and some day I update MyCustomLegacyList class(generified it) and recompile above code without changing code: Compiler(jdk 1.7+) in this time must behave as below: List myLegacyList = new MyCustomLegacyList(); Must be treated as: GENERIC_CASE List myLegacyList = new MyCustomLegacyList(); > > > **GENERIC_CASE: >> * treated as : >> * Cell cs = new Cell<>(1); * >> >> and this treated as: >> >> * Cell cs = new Cell<**String**>(1); * >> goto Next: >> >> else // raw type(legacy code) >> RAW_CASE: >> *Cell cs = new Cell(1); * >> >> Next: >> >> And finally catching compile time error. >> >> > > Better: > And finally catching compile time error for *GENERIC_CASE*, but no error > for *RAW_CASE* > > ;-) Yes. > > > -Ulf > > > From Ulf.Zibis at gmx.de Fri May 15 02:46:08 2009 From: Ulf.Zibis at gmx.de (Ulf Zibis) Date: Fri, 15 May 2009 11:46:08 +0200 Subject: Notes on implementing concise calls to constructors with type parameters In-Reply-To: <15e8b9d20905141705l42a86bb0w1c6bfcea468251cc@mail.gmail.com> References: <4A0AFA1E.8020109@sun.com> <4A0C2273.7020404@gmx.de> <4A0C2E04.8000504@sun.com> <4A0C574E.4030305@gmx.de> <15e8b9d20905141112y38835adag905e10e4373a8b45@mail.gmail.com> <4A0C8DC3.2060506@gmx.de> <15e8b9d20905141556l2f15bc92n695cb51e3073c15e@mail.gmail.com> <4A0CA434.4080801@gmx.de> <15e8b9d20905141611nd217748q5723b86b19fed339@mail.gmail.com> <4A0CAEA0.608@gmx.de> <15e8b9d20905141705l42a86bb0w1c6bfcea468251cc@mail.gmail.com> Message-ID: <4A0D39E0.6070406@gmx.de> Am 15.05.2009 02:05, Neal Gafter schrieb: > On Thu, May 14, 2009 at 4:52 PM, Ulf Zibis > wrote: > > Am 15.05.2009 01:11, Neal Gafter schrieb: > > This cannot be an error unless the Java Language Specification > requires it to be an error. > > > So my proposal is to change the JLS in a way, that it requires to > be an error. > > > You haven't actually proposed any specific JLS changes. > > > Statement: > > Cell cs = new Cell(1); > should be defined as an error for generic type T as parameter of a > constructor, if literal/expression is not assignment compatible to > the substitution of T on the LHS. > > > Yes, it should be. How, specifically, do you propose to do so? This > looks like an example, not a specification. > > > > I have no idea what change you are proposing to the > specification that would result in it being an error. Without > knowing that, I cannot evaluate your proposal. > > > Sorry, I don't get what you are not understanding. Maybe english > language problem. > > > Let me put it this way: what specific text do you suggest adding to or > removing from the Java Language Specification, and where would the > changes be made? > OK, I got it. But please let the church in the village. I think you got the content of my "comments". ;-) If a mayor asks some architects for a new town hall, they shouldn't start constructing it, before the the mayor has decided for 1 design, and additionally they wouldn't do it by their own hands, they would encourage a company, which has the skills, to do it. As non-native speaker and not author of the original proposal I only feel capable in the role as commenter, but not constructor. -Ulf From Ulf.Zibis at gmx.de Fri May 15 02:53:25 2009 From: Ulf.Zibis at gmx.de (Ulf Zibis) Date: Fri, 15 May 2009 11:53:25 +0200 Subject: Notes on implementing concise calls to constructors with type parameters In-Reply-To: <4A0CAE4C.2010706@sun.com> References: <4A0CA064.5060901@sun.com> <4A0CAC3C.3030209@univ-mlv.fr> <4A0CAE4C.2010706@sun.com> Message-ID: <4A0D3B95.8020108@gmx.de> Am 15.05.2009 01:50, Alex Buckley schrieb: > R?mi Forax wrote: > >> Re-read section 4.8 of the JLS :) >> *"It is possible that future versions of the Java programming language >> will disallow the use of raw types." >> * >> So it's seems that someone, one day conceive that. >> > > Is it conceivable to drop raw types and hence migration compatibility? > Sure. Is it an upgrade in behavior? Let's ask people still on 1.4 who > use raw types. They may have something to say about the increased costs > you'd impose on them when they try to upgrade their codebase. > BTW: those pre-1.5 people won't have code like: Cell = new Cell(1); ... as generic syntax was not known in those 1.4 times. -Ulf From Ulf.Zibis at gmx.de Fri May 15 02:57:38 2009 From: Ulf.Zibis at gmx.de (Ulf Zibis) Date: Fri, 15 May 2009 11:57:38 +0200 Subject: Notes on implementing concise calls to constructors with type parameters In-Reply-To: <4A0CAFF4.2020806@sun.com> References: <4A0CA064.5060901@sun.com> <4A0CA290.2080403@gmx.de> <4A0CAB5C.8010502@sun.com> <4A0CAD61.6040805@gmx.de> <4A0CAFF4.2020806@sun.com> Message-ID: <4A0D3C92.4080209@gmx.de> Am 15.05.2009 01:57, Alex Buckley schrieb: > >> >> Yes, you got it. This is exactly what I wanted to say. >> This potentially would make constructs like >> Cell cs = new Cell<>(1) >> _superfluous_. >> >> My additional question was, if anybody has an idea, if that would >> break some other things, I'm not aware of. I'm again really ASKING about potential side effects, we and I didn't consider until now. > > Obviously dropping raw types has an impact anywhere that type names > can be used. Since that's every class, interface, and variable > declaration, I'm not sure we need to spend much time calculating how > it would affect people moving pre-1.5 code to 1.7 - it obviously stops > them cold. BTW: those pre-1.5 people won't have code like: Cell = new Cell(1); ... as generic syntax was not known in those 1.4 times. -Ulf From belingueres at gmail.com Fri May 15 04:58:40 2009 From: belingueres at gmail.com (Gabriel Belingueres) Date: Fri, 15 May 2009 08:58:40 -0300 Subject: PROPOSAL: @OverrideAll annotation In-Reply-To: <4A0CFC31.20509@sun.com> References: <4A0CFC31.20509@sun.com> Message-ID: Hi, Implementing a prototype for this using annotation processing I found that covering all cases (like inheriting from a generic class, and implementing several generic interfaces for example) would make the code look somewhat ugly for the reading person, so implementing this as an annotation IS technically possible but produce somewhat confusing code. It seems the case that having proposing this feature using a new keyword would keep the readability of the intended behavior. Here is a discussion of the feature in the annotation processing forum: http://forums.sun.com/thread.jspa?threadID=5381073&tstart=0 (I want to thank Bruce Chapman for helping me with those annotation processing issues.) To summarize, I never really finished the prototype to include generics, having realized those readability issues and that there is not much interest in this feature. 2009/5/15 Joseph D. Darcy : > Gabriel Belingueres wrote: >> >> Hi, >> >> I've written a new feature that might be comfortable to use for >> someone. All input is welcomed. >> >> Regards, >> Gabriel >> >> PROJECT COIN SMALL LANGUAGE CHANGE PROPOSAL FORM v1.0 >> >> AUTHOR(S): Gabriel Belingueres >> >> OVERVIEW >> >> Add an @OverrideAll annotation to allow a class to override all >> inherited methods with a trivial implementation. The resulting class >> then could be used as the basis for a Null Object pattern (or even a >> basic Mock object.) >> >> >> FEATURE SUMMARY: >> >> The proposed @OverrideAll annotation will allow the class to override >> all methods (from its superclasses and implemented interfaces) with a >> trivial body, but the defined class can choose to implement specific >> methods, replacing those that would be produced automatically by the >> annotation. >> >> >> MAJOR ADVANTAGE: >> >> Less coding for implementing Null Objects, or simple tests. >> > > Catching up on commenting, this sounds like a fine job for an IDE and, as > you note, this capability already exists in some IDEs. > > -Joe > > > From howard.lovatt at gmail.com Fri May 15 05:52:38 2009 From: howard.lovatt at gmail.com (Howard Lovatt) Date: Fri, 15 May 2009 22:52:38 +1000 Subject: Notes on implementing concise calls to constructors with type parameters In-Reply-To: <4A0D26C5.3070007@gmx.de> References: <3dd3f56a0905132041r67710789if86d4e942987a039@mail.gmail.com> <15e8b9d20905132115r58bfe6a7naa6952e5f94c1392@mail.gmail.com> <3dd3f56a0905140543v63603bd4qed2a149fc06cb0ce@mail.gmail.com> <15e8b9d20905140932g33fbcd7atd6c6e28f95211cb4@mail.gmail.com> <3dd3f56a0905150026ta489f58lece1b35ee17df44d@mail.gmail.com> <4A0D26C5.3070007@gmx.de> Message-ID: Good point -- Howard Lovatt +61 419 971 263 On 15/05/2009, at 6:24 PM, Ulf Zibis wrote: > +1 > > Am 15.05.2009 09:26, Howard Lovatt schrieb: >> *class X {* >> * public X( T t ) { ... }* >> *}* >> >> >> Therefore the textual substitution method proposed works for both of >> these cases. >> >> > > ... and additionally it saves JLS change regarding error/warning on: > X xs = new X( 1 ); > ;-) > If substituted by: > X xs = new X( 1 ); > it is clearly an error. > > > -Ulf > > > > ______________________________________________________________________ > This email has been scanned by the MessageLabs Email Security System. > For more information please visit http://www.messagelabs.com/email > ______________________________________________________________________ From neal at gafter.com Fri May 15 06:33:06 2009 From: neal at gafter.com (Neal Gafter) Date: Fri, 15 May 2009 06:33:06 -0700 Subject: Notes on implementing concise calls to constructors with type parameters In-Reply-To: <3dd3f56a0905150026ta489f58lece1b35ee17df44d@mail.gmail.com> References: <3dd3f56a0905132041r67710789if86d4e942987a039@mail.gmail.com> <15e8b9d20905132115r58bfe6a7naa6952e5f94c1392@mail.gmail.com> <3dd3f56a0905140543v63603bd4qed2a149fc06cb0ce@mail.gmail.com> <15e8b9d20905140932g33fbcd7atd6c6e28f95211cb4@mail.gmail.com> <3dd3f56a0905150026ta489f58lece1b35ee17df44d@mail.gmail.com> Message-ID: <15e8b9d20905150633n5f3cbb92q79a37a4e736b93b9@mail.gmail.com> On Fri, May 15, 2009 at 12:26 AM, Howard Lovatt wrote: > Consider a simple method declaration: > > returnType methodName ( typeLHS [] name , ... ) { ... > } > > and a simple method call > > ... methodName ( new [typeRHS] [] ( ... ) , ... ); > > Then the same substituting of missing items algorithm given above can > be used. The two examples that yourself and Maurizio have discussed > would work, i.e.: > > *class X {* > * public X( T t ) { ... }* > *}* > > *void f( X xs ) ...* > > the code > > *f( new X( "foo" ) )* > > gets translated into: > > *f( new X( "foo" ) )* > > and: > > *void f( List xs ) ...* > > the following method call > > *f( new ArrayList() )* > > gets translated into: > > *f( new ArrayList() )* > > Therefore the textual substitution method proposed works for both of > these cases. Is this textual substitution supposed to be applied before overload resolution (i.e. before the method to be invoked is identified) or after method resolution (i.e. after the types of the arguments have already been resolved)? Or are you planning a major overhaul of the specification of method invocation expressions? You haven't provided enough of a hint for us to evaluate your proposal. Can you please be more precise about what JLS changes you are proposing? From tball at google.com Fri May 15 07:31:14 2009 From: tball at google.com (Tom Ball) Date: Fri, 15 May 2009 07:31:14 -0700 Subject: PROPOSAL: open and close brace optional for single statement try, catch, finally, method declaration In-Reply-To: <3dd3f56a0905150034v3a30d0bfr66885137ae15805@mail.gmail.com> References: <3dd3f56a0905150034v3a30d0bfr66885137ae15805@mail.gmail.com> Message-ID: At Google braces are compulsory for the reasons you state, although we use code-reviews rather than language changes to enforce it. I strongly encourage engineering teams to investigate the use of existing tools to help them "ratchet up" their source code quality. CheckStyle, for example, can also be used as a preprocessor or VCS check-in verifier step to verify that braces are always used. Tom On Fri, May 15, 2009 at 12:34 AM, Howard Lovatt wrote: > I would go the other way and make braces compulsory in all cases > including single line blocks for if, while, etc. I say this because I > have found missing braces to be a source of errors, particularly for > newbies. > > -- Howard. > > From reinier at zwitserloot.com Fri May 15 08:05:08 2009 From: reinier at zwitserloot.com (Reinier Zwitserloot) Date: Fri, 15 May 2009 17:05:08 +0200 Subject: Proposal: Sameness operators In-Reply-To: <4A0CFC08.4020505@sun.com> References: <2729451.1238478698193.JavaMail.root@mswamui-andean.atl.sa.earthlink.net> <49D3B1E3.8070109@sun.com> <88885FEA-F3CF-4D47-8379-7571E9E31F76@zwitserloot.com> <49D4AF9D.9090407@sun.com> <49D4B40F.2010100@optrak.co.uk> <27F0EA9D-8936-4330-A5FE-97F522C290F0@zwitserloot.com> <4A0CFC08.4020505@sun.com> Message-ID: That's all fine, Joe, but what I was trying to illustrate is this: If one argues that .compareTo is not a good fit for the engine behind an object based comparison operator, then one should also argue that .equals is not the right method to power the engine behind an object based equals operator. Somehow everyone agrees that .equals is congruent with ==, but < isn't congruent with compareTo, and I'm saying that makes no sense whatsoever. Either both are a good fit, or both are a bad fit. I'm very /very/ much in the camp of: Both are good. The situations where floats and doubles make you go 'wahuh' are annoying but we already have them (the second point I was trying to make: This stuff is complicated. It always has been, it always will be; it's an intractably complex problem!) The reason its intractable is because compareTo and equals are both used in totally separate use cases: 1. mathematical operations, 2. non-mathematical operations. and they should act very differently depending on how they are used. When I have a list of doubles that are the result of running a formula a couple of times with an input set of numbers, I want NaNs to consider themselves equal to each other, and to sort below (or above - either way) all other numbers, even the infinities. That way I can render the results in a GUI like so: NaN: 10 times -Infinity: 4 times 0: 2 times 5: 8 times Infinity: 1 time I certainly don't want each NaN to show up separately, or for compareTo to throw an exception, making my sort fail, because technically you can't compare NaNs to either themselves or any other number. In this case, the numbers are just end results, their numeric nature has no further computational meanings; They could be strings for all the program cares. *I* care about the numbers (the end user looking at the display), but to the end user there's no difference between "1" and 1, after all. However, when I have a list of doubles that represents the final score in a competition, and I want to use compareTo to determine the winner, I certainly don't want the guy that scored NaN to get first place because of a fluke of compareTo. There's no way for compareTo to ever know which case its trying to compareTo for. I posit that any system that could make it possible to know this is far too complicated to be worth it. Therefore, we can safely assume this is an intractable problem. This dichotomy will ALWAYS lead to java puzzlers. Period. We must choose which one we want to accept here: A) The 'Perfection isn't feasible, but we're okay with almost perfect' option: We accept some puzzlers, but consider .compareTo and .equals both as adequate engines behind running comparison operations on *any* 2 objects, or B) The 'If it isn't perfect (and it will never be), then I don't want any part of it' option: We accept that java does not know, *and will not ever*, have operators to compare 2 objects (be it for equality or for ordering). There's no "C) We need to come up with something better" - this problem isn't a solvable one. It's one of those two. I vote A. I bet, given the choice between A and B and nothing else, most other java programmers would too. We can discuss if I'm wrong about these being the only two options, of course. We can argue about what these operators should look like, and what they should do when you attempt to compare NaNs this way, but the answer is never going to satisfy everybody. --Reinier Zwitserloot On May 15, 2009, at 07:22, Joseph D. Darcy wrote: > Catching up on commenting... > > Reinier Zwitserloot wrote: >> The argument that .compareTo should not be used because it isn't >> entirely congruent with either the meaning of .equals() or the >> meanings of all the comparison operators (from == to <) on the >> primitives, just doesn't hold water, for this simple reason: >> >> They make absolutely no sense now, either, and nobody cares about >> that. >> > > I care about that! ;-) > > The situation is complicated, but there are reasons for the design > of the various floating-point comparison operations. > >> Here's some fun facts (all asserts are true): >> >> int x = 0/0; //ArithmeticException >> double x = 0/0.0; //okay, x = NaN >> double y = 0/0.0; >> >> assert x != y; >> assert ! (x == y); >> assert Double.valueOf(x).equals(Double.valueOf(y)); //WTF! >> assert Double.valueOf(x).equals(y); //WTF! >> >> Clearly, equals is fundamentally broken. We need a new equals! Oh no! >> > > Yes, strange but true, the "equals" relation on floating-point > values defined by IEEE 754 is *not* an equivalence relation. This > odd situation arose to accommodate NaNs. NaNs break the trichotomy > of exactly one of the less than, equal to, or greater relations > holding between values. A NaN is *unordered* compared to any > floating-point value, even itself. Since NaNs are Not-a-Numbers > they do not obey the rules of normal numerical values. > > While the IEEE 754 design is driven by numerical programming > concerns, at times there is a need for a true equivalence relation > on floating-point values as well as a total ordering. For example, > numerical regression tests in the JDK include a boolean > equivalent(double, double) method that returns true if both values > are NaN or if the values are ==. Another oddity in the IEEE 754 > equals relation is that two distinct values, -0.0 and +0.0, are > equal to each other. These two values are *not* the same under IEEE > 754 operations because 1.0/-0.0 is negative infinity while 1.0/+0.0 > is positive infinity. For sorting, a real total order is needed. > Arrays.sort(double[]) uses the total ordering from Double.compareTo > where -0.0 is less than 0.0 and NaNs are qual to one another and > greater than positive infinity and. > > [snip] > > >> 4. BigDecimal and BigInteger are changed to implement >> Comparable instead. The fact that they currently don't is >> something I don't really understand would consider filing as a bug >> if I worked more with mixed BI/BD and primitives math. By doing >> this, something like: >> > > Number should really have b neen an interface more clearly just > meaning "convertible to a primitive type;" all Number lets you do is > convert to the primitive types and converting to primitive is not > necessarily sufficient to let you do anything else with the value. > For example, one could write a Complex class that extended Number > and a quaterion class that extended Number too. A class like > BigDecimal can't implement a sensible comparison on an unknown class > that just happens to implement Number. Even properly comparing > numerical values of Number classes within the JDK is tricky; without > specific instaneof checks, both the double value and long value may > need to be extracted even for the primitive types. > > -Joe From Joe.Darcy at Sun.COM Fri May 15 08:38:40 2009 From: Joe.Darcy at Sun.COM (Joseph D. Darcy) Date: Fri, 15 May 2009 08:38:40 -0700 Subject: Notes on implementing concise calls to constructors with type parameters In-Reply-To: <15e8b9d20905140853m532e3393odbd71b64250fb645@mail.gmail.com> References: <4A0AFA1E.8020109@sun.com> <15e8b9d20905131047n30080d8cp588a5e9baefc3f80@mail.gmail.com> <4A0BDDBF.1010206@sun.com> <15e8b9d20905140355h501d60b1y4e90fdf841fd4fa9@mail.gmail.com> <4A0C0064.3020709@sun.com> <15e8b9d20905140853m532e3393odbd71b64250fb645@mail.gmail.com> Message-ID: <4A0D8C80.1040204@sun.com> Hello. Especially given the tricky nature of the type system, being able to play with Maurizio's prototype implementation of the diamond operator will be extremely helpful and informative. I think Maurizio's approach provides a favorable migration path and is worth further exploration. We generally don't want large changes to inference in the compiler or language in JDK 7 and the small size of Maurizio's patch is encouraging on that front too. -Joe Neal Gafter wrote: > On Thu, May 14, 2009 at 4:28 AM, Maurizio Cimadamore < > Maurizio.Cimadamore at sun.com> wrote: > > >> Yes, assuming the "diamond" construct is only to be used on the >> >>> right-hand-side of an assignment. But I think it's wrong to make language >>> constructs non-orthogonal. >>> >>> >> It seems to me that the "diamond" construct has always had this >> restricted-ness right from the beginning. See the original draft: >> >> http://mail.openjdk.java.net/pipermail/coin-dev/2009-February/000009.html >> >> > > Noted. That's why I got involved - to get this corrected by designing the > construct to be orthogonal to assignment. Your approach isn't an > implementation of this specification - not even close. > > Btw - allowing inference in method invocation context is rather complex - a > >> slight variation of your example fails to compile with both approaches; >> given the following method declaration:* >> > > > Saying it fails and saying it is complex are two different things. Yes, it > fails just as it would using static factories, and for exactly the same > reason. It's because the specification is so *simple* by relying on the > existing inference algorithm. I'm not suggesting that change until and > unless it changes for type inference on ordinary method invocations as > well. Another advantage of my proposed approach is that "fixing" type > inference for other contexts, as I believe we are likely to do later, would > automatically fix the diamond operator for those contexts as well without > any additional specification effort. > > > >> The bottom-line is: if we just consider inference in assignment context >> (and I think we should - at least if we want to keep this change 'small' >> ;-) ), there's no substantial difference between my proposal and yours. >> > > > Inferring type arguments based on the type of value parameters *is *a > substantial difference. Keeping the spec small is an admirable goal (it > isn't clear that your approach would result in a smaller spec), but it > shouldn't be done at the cost of internal language consistency. > > Given that neither approach has even a draft specification, perhaps they > should be considered out of scope for project coin. > > From Alex.Buckley at Sun.COM Fri May 15 10:05:37 2009 From: Alex.Buckley at Sun.COM (Alex Buckley) Date: Fri, 15 May 2009 10:05:37 -0700 Subject: Notes on implementing concise calls to constructors with type parameters In-Reply-To: <4A0D2D74.1080007@gmx.de> References: <4A0CA064.5060901@sun.com> <4A0CA290.2080403@gmx.de> <4A0CAB5C.8010502@sun.com> <4A0CAD61.6040805@gmx.de> <4A0CAFF4.2020806@sun.com> <4A0CB251.9000702@gmx.de> <4A0CB419.5000800@sun.com> <4A0D2D74.1080007@gmx.de> Message-ID: <4A0DA0E1.7060803@sun.com> Ulf Zibis wrote: >>> It should have stopped them more cold in experiencing a consequently >>> occurring CCE at runtime. ;-) >> >> Which they knew might happen because of the unchecked warning at the >> assignment, giving them a chance to identify potential heap pollution >> and upgrade certain uses of raw types at their own pace. >> > > With this same argument, following code should similar output a warning > instead of a compile time error: > > int i; > ... > if (i == 7) { // error: variable not initialized > ... > } No, it shouldn't. An unchecked warning indicates a hole is being punched in the generic type system. Assigning a List to a List<..> is not statically type correct (List is not a subtype of List<..>) and can lead to a loss of dynamic type safety. But migration compatibility desires the assignment to be legal, so an error is impractical. A warning is the only thing left. (For the same reason, you ought to get a warning every time you assign into an array, but there's a level of realism which prevents that.) Whereas, the assignment type system - where the "type" of i is ASSIGNED or UNASSIGNED - is much more conservative. No holes may be punched through it. Either code is statically checkable (==> dynamic type safety, all variables definitely assigned at runtime), or it's not. Error, or not. Alex From Alex.Buckley at Sun.COM Fri May 15 10:12:56 2009 From: Alex.Buckley at Sun.COM (Alex Buckley) Date: Fri, 15 May 2009 10:12:56 -0700 Subject: Notes on implementing concise calls to constructors with type parameters In-Reply-To: <4A0CB68E.3020306@univ-mlv.fr> References: <4A0CA064.5060901@sun.com> <4A0CAC3C.3030209@univ-mlv.fr> <4A0CAE4C.2010706@sun.com> <4A0CB68E.3020306@univ-mlv.fr> Message-ID: <4A0DA298.1030902@sun.com> R?mi Forax wrote: >> Is it conceivable to drop raw types and hence migration compatibility? >> Sure. Is it an upgrade in behavior? Let's ask people still on 1.4 >> who use raw types. They may have something to say about the increased >> costs you'd impose on them when they try to upgrade their codebase. > > First we talk about source compatibility, not binary one. I'm not sure why you're bringing in binary compatibility. Someone on 1.4 (yes, or 1.3.1, very good) who wants to migrate to 1.7 for source feature X will be displeased to discover they can only get as far as -source 1.6 because Remi cut an infinite number of raw types out of 1.7. > Third, Are you one of the guys that decide that if you want to use module > you need to change the layout of the directories of the sources ? FUD. You don't NEED to change the layout. There is a particular scenario involving simultaneous compilation of multiple source modules that cannot reasonably be achieved without a new layout. But it's off-topic. Alex From tim.lebedkov at googlemail.com Fri May 15 11:27:38 2009 From: tim.lebedkov at googlemail.com (Tim Lebedkov) Date: Fri, 15 May 2009 20:27:38 +0200 Subject: Proposal: Type inference for variable definition/initialization using the 'auto' keyword. In-Reply-To: <4A0D0066.1060701@sun.com> References: <4A0D0066.1060701@sun.com> Message-ID: Hello Joe, see my comments below On Fri, May 15, 2009 at 7:40 AM, Joseph D. Darcy wrote: > Tim Lebedkov wrote: >> >> Type inference for variable definition/initialization using the 'auto' >> keyword. >> >> AUTHOR(S): Tim Lebedkov >> >> OVERVIEW >> >> Provide a two sentence or shorter description of these five aspects of >> the feature: >> >> FEATURE SUMMARY: Should be suitable as a summary in a language tutorial. >> >> This proposal addresses the addition of type inference for >> variable definitions to the Java programming language using the 'auto' >> keyword instead of specific type name. >> >> For example, consider the following assignment statement: >> >> Map> anagrams = new HashMap>(); >> >> This is rather lengthy, so it can be replaced with this: >> >> auto anagrams = new HashMap>(); >> >> and anagrams is automatically typed as HashMap> >> >> MAJOR ADVANTAGE: What makes the proposal a favorable change? >> >> Generics have had a tremendously positive impact on type safety in the >> Java programming language. They ?have made it possible to provide >> static guarantees about the type of instances used by other classes, >> preventing entire classes of runtime errors from occurring. However, >> generics have added complexity to Java, making the code far more >> verbose and occasionally difficult to read. Although solving this >> problem is well outside the scope of this proposal, a limited form of >> type inference would remove unnecessary redundancy from the language. >> Even without generics it seems unnecessary to duplicate type names for >> simple variable definitions/assignments like: >> >> Integer a = new Integer(1023); >> >> MAJOR BENEFIT: Why is the platform better if the proposal is adopted? >> >> Less code and no duplication has a positive impact on many things: >> - faster typing/faster code changes >> - easier code changing without IDE assistance >> - code versioning diffs are more clear >> >> MAJOR DISADVANTAGE: There is always a cost. >> >> - it could be harder to read the code. >> - auto will be a keyword and may break some old code >> >> ALTERNATIVES: Can the benefits and advantages be had some way without >> a language change? >> >> no >> >> > > Catching up on proposal comments, I think the core benefits of using "auto" > or "final" on the left hand side for variables are achieved with the diamond > operator that allows one to elide type parameters on the right hand side. > ?IMO, the diamond solution of specifying the variable type fully on the left > and then specifying only the implementation type without redundant, repeated > type parameters on the right is more in keeping with Java coding style. > > -Joe > your statement "the core benefits ... are achived with the diamond operator" is just not true. As an example I picked 2 classes from Java 6: java.util.ArrayList and javax.management.ObjectName. "auto" can be useful in 3% or 4.5% of code lines respectively (and this including comments and whitespace!). Whereas "diamond" in 0% and 0.09%! "diamond" just cannot help with something like: TableModel m = new JTable().getModel(); Your second statement about "keeping Java coding style" is completely unclear to me. Why is List a = new ArrayList<>(); more "Java" than this: auto a = new ArrayList(); ? java.util.ArrayList statistics: =============================== private static final long serialVersionUID = 8683452581122892189L; int oldCapacity = elementData.length; int oldCapacity = elementData.length; int newCapacity = (oldCapacity * 3)/2 + 1; ArrayList v = (ArrayList) super.clone(); E oldValue = (E) elementData[index]; E oldValue = (E) elementData[index]; int numMoved = size - index - 1; Object[] a = c.toArray(); int numNew = a.length; Object[] a = c.toArray(); int numNew = a.length; int numMoved = size - index; int numMoved = size - toIndex; int newSize = size - (toIndex-fromIndex); int expectedModCount = modCount; int arrayLength = s.readInt(); Object[] a = elementData = new Object[arrayLength]; "auto": 18 out of 596 lines = 3% (including comments and whitespace) "diamond": 0 out of 596 lines = 0% (including comments and whitespace) javax.management.ObjectName statistics: ======================================= int in_begin = _key_index + _key_length + 1; int out_end = in_begin + _value_length; private static final long oldSerialVersionUID = -5467795090068647408L; private static final long newSerialVersionUID = 1081892073854801359L; private static boolean compat = false; GetPropertyAction act = new GetPropertyAction("jmx.serial.form"); String form = AccessController.doPrivileged(act); static final private Property[] _Empty_property_array = new Property[0]; private transient int _domain_length = 0; private transient boolean _domain_pattern = false; private transient boolean _property_list_pattern = false; private transient boolean _property_value_pattern = false; char[] name_chars = name.toCharArray(); int len = name_chars.length; char[] canonical_chars = new char[len]; // canonical form will be same int cname_index = 0; int index = 0; Map keys_map = new HashMap(); int property_index = 0; final String ichar = ((c1=='\n')?"\\n":""+c1); boolean value_pattern = false; final String ichar = ((c1=='\n')?"\\n":""+c1); final StringBuilder sb = new StringBuilder(); String[] keys = new String[nb_props]; final Map keys_map = new HashMap(); int len = sb.length(); char[] initial_chars = new char[len]; char[] canonical_chars = new char[len]; String[] tmp_keys = new String[nb_props]; Property[] tmp_props = new Property[nb_props]; int last_index = nb_props - 1; int next = startKey; int endKey = startKey; final int len = s.length; final String ichar = ((k=='\n')?"\\n":""+k); boolean value_pattern = false; int next = startValue; int endValue = startValue; final int len = s.length; final char q=s[startValue]; final int len = val.length(); final char[] s = val.toCharArray(); final int[] result = parseValue(s,0); final int endValue = result[0]; final boolean value_pattern = result[1] == 1; final int len = key.length(); final char[] k=key.toCharArray(); final int endKey = parseKey(k,0); final int slen = s.length; final int plen = p.length; final char[] d=domain.toCharArray(); final int len = d.length; int next = 0; final char c = d[next++]; final ObjectInputStream.GetField fields = in.readFields(); ObjectOutputStream.PutField fields = out.putFields(); Map table = Collections.singletonMap(key, value); Property prop = _ca_array[i]; String key = prop.getKeyString(_canonicalName); int len = _ca_array.length; final int total_size = _canonicalName.length() - _domain_length - 1- (_property_list_pattern?2:0); final char[] dest_chars = new char[total_size]; final char[] value = _canonicalName.toCharArray(); final int total_size = _canonicalName.length(); final char[] dest_chars = new char[total_size]; final char[] value = _canonicalName.toCharArray(); final int offset = _domain_length+1; final int end = writeKeyPropertyListString(value,dest_chars,offset); final char[] dest_chars = data; final char[] value = _canonicalName.toCharArray(); int index = offset; final int len = _kp_array.length; final int last = len - 1; final Property prop = _kp_array[i]; final int prop_len = prop._key_length + prop._value_length + 1; int len = _canonicalName.length(); ObjectName on = (ObjectName) object; final StringBuilder buf = new StringBuilder("\""); final int len = s.length(); final StringBuilder buf = new StringBuilder(); final int len = q.length(); char c = q.charAt(i); final char[] dom_pattern = getDomain().toCharArray(); final char[] dom_string = name.getDomain().toCharArray(); final Map nameProps = name._getKeyPropertyList(); final Property[] props = _ca_array; final String cn = _canonicalName; final Property p = props[i]; final String k = p.getKeyString(cn); final String v = (String)nameProps.get(k); final char[] val_pattern =p.getValueString(cn).toCharArray(); final char[] val_string = v.toCharArray(); final String p1 = name.getCanonicalKeyPropertyListString(); final String p2 = getCanonicalKeyPropertyListString(); int domainValue = this.getDomain().compareTo(name.getDomain()); String thisTypeKey = this.getKeyProperty("type"); String anotherTypeKey = name.getKeyProperty("type"); "auto": 97 out of 2132 lines = 4.5% (including comments and whitespace) "diamond": 2 out of 2132 lines = 0,09% (including comments and whitespace) Regards --Tim From Joe.Darcy at Sun.COM Fri May 15 12:21:18 2009 From: Joe.Darcy at Sun.COM (Joseph D. Darcy) Date: Fri, 15 May 2009 12:21:18 -0700 Subject: Proposal: Type inference for variable definition/initialization using the 'auto' keyword. In-Reply-To: References: <4A0D0066.1060701@sun.com> Message-ID: <4A0DC0AE.7080103@sun.com> Hi Tim. Tim Lebedkov wrote: > Hello Joe, > > see my comments below > > On Fri, May 15, 2009 at 7:40 AM, Joseph D. Darcy wrote: > >> Tim Lebedkov wrote: >> >>> Type inference for variable definition/initialization using the 'auto' >>> keyword. >>> >>> AUTHOR(S): Tim Lebedkov >>> >>> OVERVIEW >>> >>> Provide a two sentence or shorter description of these five aspects of >>> the feature: >>> >>> FEATURE SUMMARY: Should be suitable as a summary in a language tutorial. >>> >>> This proposal addresses the addition of type inference for >>> variable definitions to the Java programming language using the 'auto' >>> keyword instead of specific type name. >>> >>> For example, consider the following assignment statement: >>> >>> Map> anagrams = new HashMap>(); >>> >>> This is rather lengthy, so it can be replaced with this: >>> >>> auto anagrams = new HashMap>(); >>> >>> and anagrams is automatically typed as HashMap> >>> >>> MAJOR ADVANTAGE: What makes the proposal a favorable change? >>> >>> Generics have had a tremendously positive impact on type safety in the >>> Java programming language. They have made it possible to provide >>> static guarantees about the type of instances used by other classes, >>> preventing entire classes of runtime errors from occurring. However, >>> generics have added complexity to Java, making the code far more >>> verbose and occasionally difficult to read. Although solving this >>> problem is well outside the scope of this proposal, a limited form of >>> type inference would remove unnecessary redundancy from the language. >>> Even without generics it seems unnecessary to duplicate type names for >>> simple variable definitions/assignments like: >>> >>> Integer a = new Integer(1023); >>> >>> MAJOR BENEFIT: Why is the platform better if the proposal is adopted? >>> >>> Less code and no duplication has a positive impact on many things: >>> - faster typing/faster code changes >>> - easier code changing without IDE assistance >>> - code versioning diffs are more clear >>> >>> MAJOR DISADVANTAGE: There is always a cost. >>> >>> - it could be harder to read the code. >>> - auto will be a keyword and may break some old code >>> >>> ALTERNATIVES: Can the benefits and advantages be had some way without >>> a language change? >>> >>> no >>> >>> >>> >> Catching up on proposal comments, I think the core benefits of using "auto" >> or "final" on the left hand side for variables are achieved with the diamond >> operator that allows one to elide type parameters on the right hand side. >> IMO, the diamond solution of specifying the variable type fully on the left >> and then specifying only the implementation type without redundant, repeated >> type parameters on the right is more in keeping with Java coding style. >> >> -Joe >> >> > > your statement "the core benefits ... are achived with the diamond > operator" is just not true. > As an example I picked 2 classes from Java 6: java.util.ArrayList and > javax.management.ObjectName. "auto" can be useful in 3% or 4.5% of > code lines respectively (and this including comments and whitespace!). > Whereas "diamond" in 0% and 0.09%! > Two classes is not a statistically significant sample and choosing ArrayList is not a very representative choice since the implementation of a collection class is much less common than the use of a collection class. > "diamond" just cannot help with something like: TableModel m = new > JTable().getModel(); > > Your second statement about "keeping Java coding style" is completely > unclear to me. Why is > > List a = new ArrayList<>(); > > more "Java" than this: > > auto a = new ArrayList(); ? > Because the Java coding style has been designed to explicitly (and statically) declare the type of variables on the left hand side and choose the implementation type on the right hand side. The diamond pattern preserves all the explicit, textual typing information on the left and keeps the essence of the implementation choice on the right without the clutter of repeated type variables. -Joe From tim.lebedkov at googlemail.com Fri May 15 13:09:57 2009 From: tim.lebedkov at googlemail.com (Tim Lebedkov) Date: Fri, 15 May 2009 22:09:57 +0200 Subject: Proposal: Type inference for variable definition/initialization using the 'auto' keyword. In-Reply-To: <4A0DC0AE.7080103@sun.com> References: <4A0D0066.1060701@sun.com> <4A0DC0AE.7080103@sun.com> Message-ID: Hello Joe, see my comments below On Fri, May 15, 2009 at 9:21 PM, Joseph D. Darcy wrote: > Hi Tim. > > Tim Lebedkov wrote: >> >> Hello Joe, >> >> see my comments below >> >> On Fri, May 15, 2009 at 7:40 AM, Joseph D. Darcy >> wrote: >> >>> >>> Tim Lebedkov wrote: >>> >>>> >>>> Type inference for variable definition/initialization using the 'auto' >>>> keyword. >>>> >>>> AUTHOR(S): Tim Lebedkov >>>> >>>> OVERVIEW >>>> >>>> Provide a two sentence or shorter description of these five aspects of >>>> the feature: >>>> >>>> FEATURE SUMMARY: Should be suitable as a summary in a language tutorial. >>>> >>>> This proposal addresses the addition of type inference for >>>> variable definitions to the Java programming language using the 'auto' >>>> keyword instead of specific type name. >>>> >>>> For example, consider the following assignment statement: >>>> >>>> Map> anagrams = new HashMap>>> List>(); >>>> >>>> This is rather lengthy, so it can be replaced with this: >>>> >>>> auto anagrams = new HashMap>(); >>>> >>>> and anagrams is automatically typed as HashMap> >>>> >>>> MAJOR ADVANTAGE: What makes the proposal a favorable change? >>>> >>>> Generics have had a tremendously positive impact on type safety in the >>>> Java programming language. They ?have made it possible to provide >>>> static guarantees about the type of instances used by other classes, >>>> preventing entire classes of runtime errors from occurring. However, >>>> generics have added complexity to Java, making the code far more >>>> verbose and occasionally difficult to read. Although solving this >>>> problem is well outside the scope of this proposal, a limited form of >>>> type inference would remove unnecessary redundancy from the language. >>>> Even without generics it seems unnecessary to duplicate type names for >>>> simple variable definitions/assignments like: >>>> >>>> Integer a = new Integer(1023); >>>> >>>> MAJOR BENEFIT: Why is the platform better if the proposal is adopted? >>>> >>>> Less code and no duplication has a positive impact on many things: >>>> - faster typing/faster code changes >>>> - easier code changing without IDE assistance >>>> - code versioning diffs are more clear >>>> >>>> MAJOR DISADVANTAGE: There is always a cost. >>>> >>>> - it could be harder to read the code. >>>> - auto will be a keyword and may break some old code >>>> >>>> ALTERNATIVES: Can the benefits and advantages be had some way without >>>> a language change? >>>> >>>> no >>>> >>>> >>>> >>> >>> Catching up on proposal comments, I think the core benefits of using >>> "auto" >>> or "final" on the left hand side for variables are achieved with the >>> diamond >>> operator that allows one to elide type parameters on the right hand side. >>> ?IMO, the diamond solution of specifying the variable type fully on the >>> left >>> and then specifying only the implementation type without redundant, >>> repeated >>> type parameters on the right is more in keeping with Java coding style. >>> >>> -Joe >>> >>> >> >> your statement "the core benefits ... are achived with the diamond >> operator" is just not true. >> As an example I picked 2 classes from Java 6: java.util.ArrayList and >> javax.management.ObjectName. "auto" can be useful in 3% or 4.5% of >> code lines respectively (and this including comments and whitespace!). >> Whereas "diamond" in 0% and 0.09%! >> > > Two classes is not a statistically significant sample and choosing ArrayList > is not a very representative choice since the implementation of a collection > class is much less common than the use of a collection class. You're right. These two classes are not statistically significant, but: - number of lines where "auto" can be used is always >= the number of lines where "diamond" can be used - you have probably written many thousands of lines in Java. Don't you have at least the feeling that there are at least 3-5 times more variable definitions without object creation than with it? - (in case you do not have such feeling :-) I'd try to count lines on a larger source base. > >> "diamond" just cannot help with something like: TableModel m = new >> JTable().getModel(); >> >> Your second statement about "keeping Java coding style" is completely >> unclear to me. Why is >> >> List a = new ArrayList<>(); >> >> more "Java" than this: >> >> auto a = new ArrayList(); ? ? >> > > Because the Java coding style has been designed to explicitly (and > statically) declare the type of variables on the left hand side and choose > the implementation type on the right hand side. OK. I didn't know that Java was designed to explicitly declare the type of variables on the left hand side, but even if it was, it's worth changing. Regards --Tim > > The diamond pattern preserves all the explicit, textual typing information > on the left and keeps the essence of the implementation choice on the right > without the clutter of repeated type variables. > > -Joe > > From forax at univ-mlv.fr Fri May 15 13:40:33 2009 From: forax at univ-mlv.fr (=?ISO-8859-2?Q?R=E9mi_Forax?=) Date: Fri, 15 May 2009 22:40:33 +0200 Subject: Notes on implementing concise calls to constructors with type parameters In-Reply-To: <4A0DA298.1030902@sun.com> References: <4A0CA064.5060901@sun.com> <4A0CAC3C.3030209@univ-mlv.fr> <4A0CAE4C.2010706@sun.com> <4A0CB68E.3020306@univ-mlv.fr> <4A0DA298.1030902@sun.com> Message-ID: <4A0DD341.9070706@univ-mlv.fr> Alex Buckley a ?crit : > R?mi Forax wrote: >>> Is it conceivable to drop raw types and hence migration >>> compatibility? Sure. Is it an upgrade in behavior? Let's ask people >>> still on 1.4 who use raw types. They may have something to say about >>> the increased costs you'd impose on them when they try to upgrade >>> their codebase. >> >> First we talk about source compatibility, not binary one. > > I'm not sure why you're bringing in binary compatibility. Just because I think that source compatibility is less important that binary compatibility. Or even worse, I think that sometime you have to create incompatibilities to teach user to not do things that are harmful. > Someone on 1.4 (yes, or 1.3.1, very good) who wants to migrate to 1.7 > for source feature X will be displeased to discover they can only get > as far as -source 1.6 because Remi cut an infinite number of raw types > out of 1.7. So they will update all the files that use raw types, discover some hidden bugs during the process, and if they have dependencies with a pre-1.5 libraries that was not generified since, they will create clean bridge code and only this code will be compiled with -source 1.6 In the same time, Remi will be able to remove a two hours course that answer the following questions : what is a raw type ? where to use raw type ? where to not use them ? what are the rules when you inherits from a raw type, overrides a method that use raw type ? what is rare type ? why getClass()/.class produce raw type ? etc. And replace it by a 10 minutes explanation on how to call legacy codes. I just hate raw types because they are hard to understand for average developers. > >> Third, Are you one of the guys that decide that if you want to use >> module >> you need to change the layout of the directories of the sources ? > > FUD. You don't NEED to change the layout. Sorry, the FUD wasn't intentional. I am happy that this is not a requirement. > There is a particular scenario involving simultaneous compilation of > multiple source modules that cannot reasonably be achieved without a > new layout. But it's off-topic. > > Alex R?mi From mthornton at optrak.co.uk Fri May 15 13:37:16 2009 From: mthornton at optrak.co.uk (Mark Thornton) Date: Fri, 15 May 2009 21:37:16 +0100 Subject: Proposal: Type inference for variable definition/initialization using the 'auto' keyword. In-Reply-To: References: <4A0D0066.1060701@sun.com> <4A0DC0AE.7080103@sun.com> Message-ID: <4A0DD27C.1000401@optrak.co.uk> > You're right. These two classes are not statistically significant, but: > - number of lines where "auto" can be used is always >= the number of > lines where "diamond" can be used > > Only if you don't follow the common policy of using an interface type on the left hand side. With that policy 'auto' is unusable. > OK. I didn't know that Java was designed to explicitly declare the > type of variables on the left hand side, > but even if it was, it's worth changing. > It allows it and it is a common policy that many have deliberately chosen to use and recommend. Mark Thornton From Joe.Darcy at Sun.COM Fri May 15 14:01:02 2009 From: Joe.Darcy at Sun.COM (Joseph D. Darcy) Date: Fri, 15 May 2009 14:01:02 -0700 Subject: Notes on implementing concise calls to constructors with type parameters In-Reply-To: <4A0DD341.9070706@univ-mlv.fr> References: <4A0CA064.5060901@sun.com> <4A0CAC3C.3030209@univ-mlv.fr> <4A0CAE4C.2010706@sun.com> <4A0CB68E.3020306@univ-mlv.fr> <4A0DA298.1030902@sun.com> <4A0DD341.9070706@univ-mlv.fr> Message-ID: <4A0DD80E.1090902@sun.com> R?mi Forax wrote: > Alex Buckley a ?crit : > >> R?mi Forax wrote: >> >>>> Is it conceivable to drop raw types and hence migration >>>> compatibility? Sure. Is it an upgrade in behavior? Let's ask people >>>> still on 1.4 who use raw types. They may have something to say about >>>> the increased costs you'd impose on them when they try to upgrade >>>> their codebase. >>>> >>> First we talk about source compatibility, not binary one. >>> >> I'm not sure why you're bringing in binary compatibility. >> > > Just because I think that source compatibility is less important that > binary compatibility. > Or even worse, I think that sometime you have to create > incompatibilities to teach user > to not do things that are harmful. > Not all Java users are students or should be treated like students. >> Someone on 1.4 (yes, or 1.3.1, very good) who wants to migrate to 1.7 >> for source feature X will be displeased to discover they can only get >> as far as -source 1.6 because Remi cut an infinite number of raw types >> out of 1.7. >> > > So they will update all the files that use raw types, discover some > hidden bugs during the process, > and if they have dependencies with a pre-1.5 libraries that was not > generified since, > they will create clean bridge code and only this code will be compiled > with -source 1.6 > > In the same time, Remi will be able to remove a two hours course that > answer the following questions : > what is a raw type ? > where to use raw type ? > where to not use them ? > what are the rules when you inherits from a raw type, > overrides a method that use raw type ? > what is rare type ? > why getClass()/.class produce raw type ? > etc. > And replace it by a 10 minutes explanation on how to call legacy codes. > > I just hate raw types because they are hard to understand for average > developers. > Raw types were of course a compromise as part of bring generics to an established language and its existing libraries. Their use should be avoided in new code and the compiler should help users in this regard. -Joe From neal at gafter.com Fri May 15 14:32:05 2009 From: neal at gafter.com (Neal Gafter) Date: Fri, 15 May 2009 14:32:05 -0700 Subject: Notes on implementing concise calls to constructors with type parameters In-Reply-To: <4A0D8C80.1040204@sun.com> References: <4A0AFA1E.8020109@sun.com> <15e8b9d20905131047n30080d8cp588a5e9baefc3f80@mail.gmail.com> <4A0BDDBF.1010206@sun.com> <15e8b9d20905140355h501d60b1y4e90fdf841fd4fa9@mail.gmail.com> <4A0C0064.3020709@sun.com> <15e8b9d20905140853m532e3393odbd71b64250fb645@mail.gmail.com> <4A0D8C80.1040204@sun.com> Message-ID: <15e8b9d20905151432h512850b5x20ed04e3eca56a2a@mail.gmail.com> On Fri, May 15, 2009 at 8:38 AM, Joseph D. Darcy wrote: > Especially given the tricky nature of the type system, being able to play > with Maurizio's prototype implementation of the diamond operator will be > extremely helpful and informative. I think Maurizio's approach provides a > favorable migration path and is worth further exploration. We generally > don't want large changes to inference in the compiler or language in JDK 7 > and the small size of Maurizio's patch is encouraging on that front too. I agree a prototype is educational. I don't agree that two passes of type inference is simpler in the spec, nor that it provides a reasonable migration path to a future one-pass algorithm that may result in a different answer. From forax at univ-mlv.fr Fri May 15 16:06:12 2009 From: forax at univ-mlv.fr (=?ISO-8859-2?Q?R=E9mi_Forax?=) Date: Sat, 16 May 2009 01:06:12 +0200 Subject: Notes on implementing concise calls to constructors with type parameters In-Reply-To: <4A0DD80E.1090902@sun.com> References: <4A0CA064.5060901@sun.com> <4A0CAC3C.3030209@univ-mlv.fr> <4A0CAE4C.2010706@sun.com> <4A0CB68E.3020306@univ-mlv.fr> <4A0DA298.1030902@sun.com> <4A0DD341.9070706@univ-mlv.fr> <4A0DD80E.1090902@sun.com> Message-ID: <4A0DF564.2060106@univ-mlv.fr> Joseph D. Darcy a ?crit : > R?mi Forax wrote: >> Alex Buckley a ?crit : >> >>> R?mi Forax wrote: >>> >>>>> Is it conceivable to drop raw types and hence migration >>>>> compatibility? Sure. Is it an upgrade in behavior? Let's ask >>>>> people still on 1.4 who use raw types. They may have something to >>>>> say about the increased costs you'd impose on them when they try >>>>> to upgrade their codebase. >>>>> >>>> First we talk about source compatibility, not binary one. >>>> >>> I'm not sure why you're bringing in binary compatibility. >> >> Just because I think that source compatibility is less important that >> binary compatibility. >> Or even worse, I think that sometime you have to create >> incompatibilities to teach user >> to not do things that are harmful. >> > > Not all Java users are students or should be treated like students. I don't agree, Java is complex enough to write tons of puzzlers (there are even books about Java puzzlers :) That kind of languages should educate/help their users. But you are right, some users don't want to learn, they are the ones that doesn't want that the language changes. > >>> Someone on 1.4 (yes, or 1.3.1, very good) who wants to migrate to >>> 1.7 for source feature X will be displeased to discover they can >>> only get as far as -source 1.6 because Remi cut an infinite number >>> of raw types out of 1.7. >>> >> >> So they will update all the files that use raw types, discover some >> hidden bugs during the process, >> and if they have dependencies with a pre-1.5 libraries that was not >> generified since, >> they will create clean bridge code and only this code will be >> compiled with -source 1.6 >> >> In the same time, Remi will be able to remove a two hours course that >> answer the following questions : >> what is a raw type ? >> where to use raw type ? >> where to not use them ? >> what are the rules when you inherits from a raw type, >> overrides a method that use raw type ? >> what is rare type ? >> why getClass()/.class produce raw type ? >> etc. >> And replace it by a 10 minutes explanation on how to call legacy codes. >> >> I just hate raw types because they are hard to understand for average >> developers. >> > > Raw types were of course a compromise as part of bring generics to an > established language and its existing libraries. Yes, but raw types are only necessary to cross the bridge between pre and post generics world. Raw types already exist in 1.5, 1.6 and 1.7. So there is no need to have raw types in 1.8 because if I want that kind of bridge I can compile that specific part of the code with -source 1.7 > > Their use should be avoided in new code and the compiler should help > users in this regard. That's not true for javac. Current version doesn't, by default, emit a warning If you use raw types. But your are right that eclipse do that since, I think, at least two years. > > -Joe > R?mi From forax at univ-mlv.fr Fri May 15 16:15:32 2009 From: forax at univ-mlv.fr (=?ISO-8859-1?Q?R=E9mi_Forax?=) Date: Sat, 16 May 2009 01:15:32 +0200 Subject: Proposal: Type inference for variable definition/initialization using the 'auto' keyword. In-Reply-To: <4A0DD27C.1000401@optrak.co.uk> References: <4A0D0066.1060701@sun.com> <4A0DC0AE.7080103@sun.com> <4A0DD27C.1000401@optrak.co.uk> Message-ID: <4A0DF794.9030807@univ-mlv.fr> Mark Thornton a ?crit : >> You're right. These two classes are not statistically significant, but: >> - number of lines where "auto" can be used is always >= the number of >> lines where "diamond" can be used >> >> >> > Only if you don't follow the common policy of using an interface type on > the left hand side. With that policy 'auto' is unusable. > The common policy is stupid because you should only use interfaces when needed. When you write a code you talk to the guys that will read it. So If you put an interface, you say something like, here the code is not obvious because more that one implementations may be used. Only code your needs, never more. >> OK. I didn't know that Java was designed to explicitly declare the >> type of variables on the left hand side, >> but even if it was, it's worth changing. >> >> > It allows it and it is a common policy that many have deliberately > chosen to use and recommend. > > Mark Thornton > > R?mi From ali.ebrahimi1781 at gmail.com Fri May 15 16:27:23 2009 From: ali.ebrahimi1781 at gmail.com (Ali Ebrahimi) Date: Sat, 16 May 2009 03:57:23 +0430 Subject: Notes on implementing concise calls to constructors with type parameters Message-ID: <5ab441490905151627qed54b4by3b01f140830b0f39@mail.gmail.com> On *Fri*, May 15, 2009 at 14:01:02, Joseph D. Darcy > wrote: : > Raw types were of course a compromise as part of bring generics to an > established language and its existing libraries. > > Their use should be avoided in new code and the compiler should help > users in this regard. > > One step in that direction is that compiler(jdk1.7+) to use hidden diamond operator in some cases. By adding below simple rule: code sample: Cell cs = new Cell(1); Rule: if instantiated object type(in new Cell(1), Cell class) is generic class then goto GENERIC_CASE GENERIC_CASE: treated as : Cell cs = new Cell<>(1); and this treated as: Cell cs = new Cell(1); goto Next: else // raw type(legacy code) RAW_CASE: Cell cs = new Cell(1); Next: And finally catching compile time error for generic code. I think one of main goals of adding generic support to java language was catching run time exceptions in compile time and having robust and safe code. I don't think the Cell class to be a legacy code(row type)in this case. I think this particular rule can be applicable at least in Object instantiation case. if right hand side is not a generic type use the row type. Cell cs = new LegacySubCell(10); By diamond operator if we use: Cell cs = new LegacySubCell<>(10); compiler got an error, because LegacySubCell is not generic class(legacy code). But by my rule(no diamond operator in code) this compiles fine. because that the LegacySubCell class is not generic(legacy code) treated as row type. By this rule we decrease the use of row types and not dropping them totally ones. One advantage of this rule is that if some day we decided to update legacy code and generified them. By recompiling code, in this time the compiler would use the generic LegacySubCell class and We would had: the code: Cell cs = new LegacySubCell(10); treated as Cell cs = new LegacySubCell<>(10); and this treated as: Cell cs = new LegacySubCell(10); And finally catching compile time error. I think we don'nt need to the first step and diamond operator to be hidden. And we have: Cell cs = new Cell(1); if Cell is generic class then goto GENERIC_CASE GENERIC_CASE: treated as : Cell cs = new Cell(1); goto Next: else // raw type(legacy code) RAW_CASE: *Cell cs = new Cell(1); Next: One note: By this rule we don't need to change code for using new generic versions of legacy classes. Another example: List myList = new ArrayList(); treates as: GENERIC_CASE List myList = new ArrayList(); because that ArrayList is now generic class(since 1.5). But the following code: List myLegacyList = new MyCustomLegacyList(); is treated as: Raw_CASE List myLegacyList = new MyCustomLegacyList(); and some day if I update MyCustomLegacyList class(generified it) and recompile above code without changing code: Compiler(jdk 1.7+) in this time must behave as below: List myLegacyList = new MyCustomLegacyList(); Must be treated as: GENERIC_CASE List myLegacyList = new MyCustomLegacyList(); Therefore by this rule we can slowly remove row types from language(by compiler help). From reinier at zwitserloot.com Fri May 15 19:47:50 2009 From: reinier at zwitserloot.com (Reinier Zwitserloot) Date: Sat, 16 May 2009 04:47:50 +0200 Subject: Proposal: Type inference for variable definition/initialization using the 'auto' keyword. In-Reply-To: <4A0DF794.9030807@univ-mlv.fr> References: <4A0D0066.1060701@sun.com> <4A0DC0AE.7080103@sun.com> <4A0DD27C.1000401@optrak.co.uk> <4A0DF794.9030807@univ-mlv.fr> Message-ID: <7191905F-0604-45E0-A23C-B58E1E5808AD@zwitserloot.com> Actually, almost all java programmers routinely do not specify the type of expressions. Easily 95%+ of all java code. Example: System.out.println(new StringBuilder().append("Hello, ").append("World!").toString()); This rookie coder clearly needs to be a taught a lesson - that is not readable at all because he's elided 4 types from this code! It should be: System.out.println((String)((StringBuilder)((StringBuilder)new StringBuilder.append("Hello, ")).append("World!")).toString()); Much more readable. Folks, expressions are left without manifest typing ALL THE TIME. The argument that this is 'unjavalike' is frankly ridiculous. There's a fine argument for *mutable* variables to be forcibly manifest typed, to make sure you don't run into silly surprises, such as: auto x = new ArrayList(); if ( someFoo ) { x = Collections.emptyList(); } generating a compiler error (because Collections.emptyList returns a List, whereas the type of x got inferred to ArrayList. You can't assign a list to an arraylist). This is an annoying puzzleresque problem that should be avoided if at all possible, which is why I totally agree that auto is not a good idea without a way to solve this problem. But that problem only applies to mutables. Therefore: final foo = "Hello, "; is perfectly java-esque, and has no such problems because you can't re- assign foo in the first place. It should also provide a very soft incentive for java programmers everywhere to learn to mark local stuff as final if they aren't going to change it anyway - and to not reuse variable names just to save on typing. The boundary between the meaning of the expression and the meaning of the variable is already blurred here; the variable IS the expression; that's what final means. There's a point to the argument that explicit types help make things clear, but you just *can't* expand that argument to FORCING it onto the programmer. There's a reason java allows you to chain method calls and put expressions in the position where you're supposed to put a method parameter. Typing every expression is patently insane. No programming language has ever gone there, and I bet no language ever will. It should be optional. And it will be, if you add the 'final varName = expression;' syntax to java. Nobody is forcing you to use it - adding the type (final Type varName = expressionCompatibleWithType;) won't be going away, of course. Perhaps someone can enlighten me why using an expression more than once requires you to explicitly type it, UNLESS you reuse the expression by way of method chaining (such as StringBuilder's append). I accept the argument that this isn't worth changing because its not enough value for the impact (I'd disagree, but I could be persuaded), but the argument that this is somehow the java way or sensible for readability reasons - I don't buy that for a second, that makes no sense at all. That kind of readability is best enabled by smart editors that will tell you the type of any expression anywhere by way of e.g. tooltips. --Reinier Zwitserloot On May 16, 2009, at 01:15, R?mi Forax wrote: > Mark Thornton a ?crit : >>> You're right. These two classes are not statistically significant, >>> but: >>> - number of lines where "auto" can be used is always >= the number >>> of >>> lines where "diamond" can be used >>> >>> >>> >> Only if you don't follow the common policy of using an interface >> type on >> the left hand side. With that policy 'auto' is unusable. >> > > The common policy is stupid because you should only use interfaces > when > needed. > When you write a code you talk to the guys that will read it. > So If you put an interface, you say something like, here the code is > not > obvious > because more that one implementations may be used. > Only code your needs, never more. > >>> OK. I didn't know that Java was designed to explicitly declare the >>> type of variables on the left hand side, >>> but even if it was, it's worth changing. >>> >>> >> It allows it and it is a common policy that many have deliberately >> chosen to use and recommend. >> >> Mark Thornton >> >> > R?mi > From reinier at zwitserloot.com Fri May 15 19:54:19 2009 From: reinier at zwitserloot.com (Reinier Zwitserloot) Date: Sat, 16 May 2009 04:54:19 +0200 Subject: Notes on implementing concise calls to constructors with type parameters In-Reply-To: <5ab441490905151627qed54b4by3b01f140830b0f39@mail.gmail.com> References: <5ab441490905151627qed54b4by3b01f140830b0f39@mail.gmail.com> Message-ID: <02B35169-AEF2-441E-A86D-8A0CF9352409@zwitserloot.com> I believe the current rules for how generified static methods infer the generics can be very easily adapted to inferring for a constructor call with no generics info whatsoever (what's currently a raw constructor call) - without breaking ANY backwards compatibility. The only major difference is for 'un-inferable' types, where generics inference will bind the type to the specified bound (the Number in ) whereas a raw type will always pick Object, even if Object would never make for a legal T. Inference is very very complicated, so cooking this up without checking the official spec is bound to lead to inconsistencies. Example complex inference: foo(Collections.emptyList(), Arrays.asList(1, 2, 3).get(1)); where foo exists in many overloaded variants. Try and sort that mess out. From past experience the current inference algorithm generally chokes on this, and you'll need to put in explicit generics info. Unfortunately I don't have the time this month to open the JLS and work this out. --Reinier Zwitserloot On May 16, 2009, at 01:27, Ali Ebrahimi wrote: > On *Fri*, May 15, 2009 at 14:01:02, Joseph D. Darcy sun.com> > wrote: > : > >> Raw types were of course a compromise as part of bring generics to an >> established language and its existing libraries. >> >> Their use should be avoided in new code and the compiler should help >> users in this regard. >> >> One step in that direction is that compiler(jdk1.7+) to use hidden >> diamond > operator in some cases. > By adding below simple rule: > code sample: > > Cell cs = new Cell(1); > > Rule: > if instantiated object type(in new Cell(1), Cell class) is generic > class > then goto GENERIC_CASE > > GENERIC_CASE: > treated as : > Cell cs = new Cell<>(1); > > and this treated as: > > Cell cs = new Cell(1); > goto Next: > > else // raw type(legacy code) > RAW_CASE: > Cell cs = new Cell(1); > > Next: > > And finally catching compile time error for generic code. > > I think one of main goals of adding generic support to java language > was catching run time exceptions in compile time and having robust and > safe code. > > I don't think the Cell class to be a legacy code(row type)in this > case. > I think this particular rule can be applicable at least in Object > instantiation case. > > if right hand side is not a generic type use the row type. > > Cell cs = new LegacySubCell(10); > > By diamond operator if we use: > Cell cs = new LegacySubCell<>(10); > > compiler got an error, because LegacySubCell is not generic > class(legacy code). > But by my rule(no diamond operator in code) this compiles fine. > > because that the LegacySubCell class is not generic(legacy code) > treated as row type. > By this rule we decrease the use of row types and not dropping them > totally ones. > > One advantage of this rule is that if some day we decided to update > legacy code and generified them. > By recompiling code, in this time the compiler would use the generic > LegacySubCell class and > We would had: > the code: > Cell cs = new LegacySubCell(10); > > treated as > Cell cs = new LegacySubCell<>(10); > > and this treated as: > Cell cs = new LegacySubCell(10); > > And finally catching compile time error. > > I think we don'nt need to the first step and diamond operator to be > hidden. > > And we have: > > Cell cs = new Cell(1); > > if Cell is generic class > then goto GENERIC_CASE > > GENERIC_CASE: > treated as : > > Cell cs = new Cell(1); > goto Next: > > else // raw type(legacy code) > RAW_CASE: > *Cell cs = new Cell(1); > > Next: > > > One note: By this rule we don't need to change code for using new > generic versions of legacy classes. > > Another example: > List myList = new ArrayList(); > > treates as: GENERIC_CASE > > List myList = new ArrayList(); > > because that ArrayList is now generic class(since 1.5). > > But the following code: > > List myLegacyList = new MyCustomLegacyList(); > > is treated as: Raw_CASE > List myLegacyList = new MyCustomLegacyList(); > > and some day if I update MyCustomLegacyList class(generified it) and > recompile > above code without changing code: > > Compiler(jdk 1.7+) in this time must behave as below: > List myLegacyList = new MyCustomLegacyList(); > > Must be treated as: GENERIC_CASE > List myLegacyList = new MyCustomLegacyList(); > > > Therefore by this rule we can slowly remove row types from language(by > compiler help). > From pbenedict at apache.org Fri May 15 20:43:10 2009 From: pbenedict at apache.org (Paul Benedict) Date: Fri, 15 May 2009 22:43:10 -0500 Subject: Notes on implementing concise calls to constructors with type parameters Message-ID: After reading this board for a couple months, I was waiting for someone to finally make this suggestion: >> Cell cs = new Cell(1); >> treated as : >> Cell cs = new Cell<>(1); YES! I think Ali Ebrahimi is making a noteworthy point here. Unless the compiler can't possibly figure it out (???), there is never a need to specify <> (empty angled brackets) when the genericized type on the left-hand side exists. It's should be obvious in the grammar that constructing new objects should be genercized regardless <> is specified. -- Paul From lk at teamten.com Fri May 15 21:27:13 2009 From: lk at teamten.com (Lawrence Kesteloot) Date: Fri, 15 May 2009 21:27:13 -0700 Subject: Proposal: Type inference for variable definition/initialization using the 'auto' keyword. In-Reply-To: <7191905F-0604-45E0-A23C-B58E1E5808AD@zwitserloot.com> References: <4A0D0066.1060701@sun.com> <4A0DC0AE.7080103@sun.com> <4A0DD27C.1000401@optrak.co.uk> <4A0DF794.9030807@univ-mlv.fr> <7191905F-0604-45E0-A23C-B58E1E5808AD@zwitserloot.com> Message-ID: <997cab100905152127w705a7a3bv6fe5263da7724b9f@mail.gmail.com> Reinier Zwitserloot wrote: > It should be optional. And it will be, if you add the 'final varName = > expression;' syntax to java. Nobody is forcing you to use it Nobody is forcing me to use it, but unfortunately no one can stop my co-workers from using it either. > Perhaps someone can enlighten me why using an expression more than > once requires you to explicitly type it, I like the added documentation. If an expression (as you call it) is going to be used many times in a method, the it's probably important and I want to immediately know its type. When I see: final params = getX().getY().getZ(); I don't want to have to chase down the return value of getX() so I can look up its getY() method, then that object's getZ() method, so I can figure out the type of "params". You might argue that I already don't explicitly know the type of, say, the "getX().getY()" sub-expression, but it's only used in passing and I don't really care. What I need to know is, "What can I do with params?" Reading code is hard enough without forcing this extra work on the reader. And writing the type isn't much of a burden for the author, since he already knows it. I don't particularly buy the argument that "the IDE can just tell you." I'm not sure we want to turn Java into a language that's only usable in a small set of editing environments. Lawrence From neal at gafter.com Fri May 15 21:30:45 2009 From: neal at gafter.com (Neal Gafter) Date: Fri, 15 May 2009 21:30:45 -0700 Subject: Notes on implementing concise calls to constructors with type parameters In-Reply-To: <02B35169-AEF2-441E-A86D-8A0CF9352409@zwitserloot.com> References: <5ab441490905151627qed54b4by3b01f140830b0f39@mail.gmail.com> <02B35169-AEF2-441E-A86D-8A0CF9352409@zwitserloot.com> Message-ID: <15e8b9d20905152130y232cd55bqc92c7acd05f0a531@mail.gmail.com> On Fri, May 15, 2009 at 7:54 PM, Reinier Zwitserloot < reinier at zwitserloot.com> wrote: > I believe the current rules for how generified static methods infer > the generics can be very easily adapted to inferring for a constructor > call with no generics info whatsoever (what's currently a raw > constructor call) - without breaking ANY backwards compatibility. > > Unfortunately I don't have the time this month to open the JLS and > work this out. > I have a truly marvelous proof of this conjecture which this margin is too narrow to contain. ;-) Seriously, without more evidence one way or another - preferable in the form of a proof, or at least some time spent glancing through the JLS and checking some edge cases - I don't see how such a conjecture can be useful to project Coin. From reinier at zwitserloot.com Fri May 15 21:45:27 2009 From: reinier at zwitserloot.com (Reinier Zwitserloot) Date: Sat, 16 May 2009 06:45:27 +0200 Subject: Proposal: Type inference for variable definition/initialization using the 'auto' keyword. In-Reply-To: <997cab100905152127w705a7a3bv6fe5263da7724b9f@mail.gmail.com> References: <4A0D0066.1060701@sun.com> <4A0DC0AE.7080103@sun.com> <4A0DD27C.1000401@optrak.co.uk> <4A0DF794.9030807@univ-mlv.fr> <7191905F-0604-45E0-A23C-B58E1E5808AD@zwitserloot.com> <997cab100905152127w705a7a3bv6fe5263da7724b9f@mail.gmail.com> Message-ID: On May 16, 2009, at 06:27, Lawrence Kesteloot wrote: > Reinier Zwitserloot wrote: >> It should be optional. And it will be, if you add the 'final >> varName = >> expression;' syntax to java. Nobody is forcing you to use it > > Nobody is forcing me to use it, but unfortunately no one can stop my > co-workers from using it either. Then you missed the point of the post. Unless you think forcing your coworkers to write: System.out.println((String)((StringBuilder)((StringBuilder)new StringBuilder().append("Hello, ")).append("World!")).toString()); is a good idea. > You might argue that I already don't > explicitly know the type of, say, the "getX().getY()" sub-expression, > but it's only used in passing and I don't really care. What I need to > know is, "What can I do with params?" Why do you not care here: a.getB().doC(); but you do care here: final z = a.getB(); z.doC(); z.doD(); That's arbitrary. You can't just hand-wave and say its 'only used in passing and I don't care' in one situation but in the other situation it all of a sudden becomes crucial. The -exact- -same- conditions would apply to variables created with "final name = expr;" I grok the basic idea of "I want to know the type of my expression". I agree with you. This is nice to know. But you're going to have to come to terms with the fact that java does not now and will not ever give you this stuff in the raw source file in all situations. That's not feasible. I repeat: Why is re-using without using chaining so special that you want to force explicit typing on everybody? > > > Reading code is hard enough without forcing this extra work on the > reader. If I understand you correctly, I can use your argument to state that this: System.out.println((String)((StringBuilder)((StringBuilder)new StringBuilder().append("Hello, ")).append("World!")).toString()); is more readable than this: System.out.println(new StringBuilder().append("Hello, ").append("World!").toString()); which I'm fairly sure nobody agrees with. I posit instead that eliding type information from expressions that aren't mutable does not neccessarily lead to making code harder to read, and in many cases can help make it easier to read by not foisting irrelevant information onto your eyeballs. > And writing the type isn't much of a burden for the author, > since he already knows it. The amount of boilerplate elimination is staggering. Compared to most of the other proposals on this list, it wins. I hope it's self-evident to the members of this mailing list that java programmers routinely do NOT make their local variables final just because of the minor burden of typing it out. Therefore, please stop acting as if this change is just trying to save people some typing. That's not at all what's at stake. Instead, there are 2 pretty major improvements involved: 1. More local finals, which makes everybody happy, and 2. Less noise by expanding the existing mechanism of offering the programmer to, at their discretion, elide explicit type information. Saving some characters is just gravy. > I don't particularly buy the argument that "the IDE can just tell > you." I'm not sure we want to turn Java into a language that's only > usable in a small set of editing environments. Straw man. I said: If you care about that sort of stuff, you *NEED* *TO* *USE* an IDE. You're acting as if this change all of a sudden changes the situation, which is false. Expressions in java aren't always manifestly typed. Period. If you want to chase down such types easily, you need an editor. 'final name = expr;' does not change this at all. --Reinier Zwitserloot From lk at teamten.com Fri May 15 22:09:30 2009 From: lk at teamten.com (Lawrence Kesteloot) Date: Fri, 15 May 2009 22:09:30 -0700 Subject: Proposal: Type inference for variable definition/initialization using the 'auto' keyword. In-Reply-To: References: <4A0D0066.1060701@sun.com> <4A0DC0AE.7080103@sun.com> <4A0DD27C.1000401@optrak.co.uk> <4A0DF794.9030807@univ-mlv.fr> <7191905F-0604-45E0-A23C-B58E1E5808AD@zwitserloot.com> <997cab100905152127w705a7a3bv6fe5263da7724b9f@mail.gmail.com> Message-ID: <997cab100905152209o3d3749a0td63a91dc75d696d0@mail.gmail.com> Reinier Zwitserloot wrote: > That's arbitrary. You can't just hand-wave and say its 'only used in passing > and I don't care' in one situation but in the other situation it all of a > sudden becomes crucial. I'm not going to be able to use logic to convince you of the difference, but for me it's there. The original "getX().getY().getZ()" may as well have been a utility function "getXYZ()". It's an opaque expression and I don't care about its intermediate types. The chained "append()" is an idiom and the type is the same throughout. But by the time I'm putting a reference into a named (even final) variable, then I want to use it a bunch and I want to know its type. As an author I want the compiler to double-check my work, and as a reader I want the explicit documentation. > ?2. Less noise by expanding the existing mechanism of offering the > programmer to, at their discretion, elide explicit type information. What's noise to you is documentation to me. Perhaps one day I'll write a large Scala program on a team with others and find that the "val" declarations everywhere (which is essentially what you're suggesting) are perfectly readable and don't impede my ability to browse quickly through code when looking for problems. Then I'll change my mind about this. Lawrence From rssh at gradsoft.com.ua Fri May 15 20:23:17 2009 From: rssh at gradsoft.com.ua (Ruslan Shevchenko) Date: Sat, 16 May 2009 06:23:17 +0300 (EEST) Subject: Proposal: Type inference for variable definition/initialization using the 'auto' keyword. In-Reply-To: References: <4A0D0066.1060701@sun.com> <4A0DC0AE.7080103@sun.com> Message-ID: <4b1e39a2a95d71051b5a990d7067d9d8.squirrel@wmail.gradsoft.ua> Sorry, can I ask what exactly patterns you mean. I. e. is such approximation is correct (?) pattern for auto : any variable definition. pattern for 'usefull' auto: any variable definition with templates^H^H^H^H^H type parameters on left side. pattern for diamond : any variable definition with allocation expression at right side. If this is correct, I will add one to set of coin patterns. > > You're right. These two classes are not statistically significant, but: > - number of lines where "auto" can be used is always >= the number of > lines where "diamond" can be used > - you have probably written many thousands of lines in Java. Don't you > have at least the feeling that there are at least 3-5 times more > variable definitions without object creation than with it? > - (in case you do not have such feeling :-) I'd try to count lines on > a larger source base. > From rssh at gradsoft.com.ua Fri May 15 20:45:22 2009 From: rssh at gradsoft.com.ua (Ruslan Shevchenko) Date: Sat, 16 May 2009 06:45:22 +0300 (EEST) Subject: PROPOSAL: Simplified StringBuffer/StringBuilder syntax In-Reply-To: <4A0D008B.6030604@sun.com> References: <15886363.1238270778184.JavaMail.root@mswamui-andean.atl.sa.earthlink.net> <4A0D008B.6030604@sun.com> Message-ID: <9357d1941acb4e80e4734d2c17c81f45.squirrel@wmail.gradsoft.ua> > Catching up on proposals... > > Derek Foster wrote: >> Simplified StringBuffer/StringBuilder syntax. >> >> AUTHOR: Derek Foster >> >> >> OVERVIEW >> >> The Java language is designed to use immutable strings. Strings are >> intended to be constructed via one of two builder classes: StringBuffer >> (older, and slower due to synchronization) and StringBuilder (newer, and >> faster). Using these classes can make constructing Strings out of >> multiple pieces considerably more efficient than repeatedly >> concatenating strings together. These classes are often used by the Java >> compiler to concatenate strings behind the scenes, so that an expression >> like this: >> >> String foo = "abcd" + 42 + "efgh"; >> >> might be compiled as: >> >> String foo = new StringBuilder("abcd").append(42).append("efgh"); >> > > The subset of this proposal I'm most sympathetic to is having ""+=" on > StringBuffer and StringBuilder desugar into a call to append. Offhand, > I think that could be a mostly localized specification change that > indicated the String{Buffer, Builder} was being mutated. Coming up with > String => StringBuffer conversion rules in assignment contexts is > possible, but not necessarily desirable IMO. > > An analysis of the applicability of just this change to a corpus of code > might be informative. > Is this any call of StringBuilder.append() ? Ok, I will add one. Btw, personally I'm not big fun of this proposal, because this is attempt to solve small part of big problem by special partial rule. I. e. real problem - absence of operator overloading. Some partial solutions are index access and overloading of '+=' for string builders. May be I can imagine, that special rules for index access expressions instead describing operator overloading is not very-very wrong way (justified by 80/20 case, as foreach without closures ), but special rule in language for each type when we need operator overloading ? So, for me sense of existence of such approach is be argument to add operator overloading in post-coin phase (Java 8 (?)). > -Joe > > From rssh at gradsoft.com.ua Fri May 15 21:17:34 2009 From: rssh at gradsoft.com.ua (Ruslan Shevchenko) Date: Sat, 16 May 2009 07:17:34 +0300 (EEST) Subject: PRE-PROPOSAL: Simple operator overloading. In-Reply-To: <4A0D004E.608@sun.com> References: <4A0D004E.608@sun.com> Message-ID: > > Catching up on responses, while adding operators for numerical types > would certainly improve the readability of numerical code using > non-primitive types, for Project Coin and JDK 7, I think efforts in this > area should focus on getting [] and []= for collection-like types since > they are much more often used than numerical types in Java programming. > It's vicious circle: numerical types does not usable without operator overloading; operator overloading does not accepted because numerical types are not used ;) Are exists some plans (or some way for third party to get project sponsorship from compiler group) to submit operator overloading JSR for Java 8 ? (based not on annotations, but on JSR292 names, to be compatible with John Rose approach for mlvm: http://wikis.sun.com/display/mlvm/DynamicJava) > -Joe > > From Joe.Darcy at Sun.COM Sat May 16 15:44:54 2009 From: Joe.Darcy at Sun.COM (Joseph D. Darcy) Date: Sat, 16 May 2009 15:44:54 -0700 Subject: Proposal: Generic Specification by Method In-Reply-To: <79d69e110903292215y1b0395bck6fa538ad726d70f6@mail.gmail.com> References: <79d69e110903292215y1b0395bck6fa538ad726d70f6@mail.gmail.com> Message-ID: <4A0F41E6.6060904@sun.com> Hello. Catching up on proposal responses, this feature sounds a lot like the "concepts" work being done in C++: http://www.research.att.com/~bs/C++0xFAQ.html#concepts Changing the type system in this manner is out of scope for Project Coin. -Joe Ron Thomas wrote: > I would like to propose an extension to generics that would allow a > generic type to be specified by methods in addition to the current > inheritance/implementations. > > Generics by Method > > AUTHOR(S): > > Ron Thomas > > OVERVIEW > > FEATURE SUMMARY: > > Generics by Method allows for the use of Generics when using a common > interface or super class is not an option. > > MAJOR ADVANTAGE: > > This would allow the use of generics based off of methods instead of > off of classes/interfaces. > > MAJOR BENEFIT: > > Generics by Method will allow working with different classes with > similar methods easier and more concise. Instead of relying on > instanceof checks and class wrappers a generic type would suffice. > While using Generics by Interface or super class is preferred, it is > not always an option when dealing with 3rd party APIs. > > MAJOR DISADVANTAGE: > > Reflection will be used in order to achieve this goal, and the > corresponding performance hit will be incurred. > > ALTERNATIVES: > > Use wrappers and class composition and use generics as-is. > > EXAMPLES > > SIMPLE EXAMPLE: > > The following method calls the close method on a list of resources. > Unfortunately using the Closeable interface is no an option because > one of the resources is supplied by a 3rd party resource does not > implement the interface. > > public > void closeAllResources(List resources) { > for (T t : resources) { > t.close(); > } > } > > ADVANCED EXAMPLE: Show advanced usage(s) of the feature. > > The following example requires two methods, one of which throws an exception. > public ResourceException : int)> > boolean checkResources(List resources, String host, int port) > throws ResourceException { > for (T t : resources) { > int status = t.open(host, port); > if (status < 0) { > return false; > } > t.close(); > } > return true; > } > > DETAILS > > SPECIFICATION: > > A having generic specification shall be added in the form: > having(METHOD_SIG) > > METHOD_SIG := METHOD_NAME([[PARAM_TYPE,]* PARAM_TYPE]*) : > [RETURN_TYPE] [throws [[EXCEPTION,]* EXCEPTION]* > METHOD_NAME := java legal method name > PARAM_TYPE := java legal parameter type > RETURN_TYPE := java legal return type > EXCEPTION := java level exception > > The following generic expressions become legal: > > Simple specification with no parameters. > > matches classes with: void method() > > Simple specifiation with parameters. > > matches classes with: int method(int, String) > > Constructor specification > > matches classes with constructor that have an int and String parameter > > Specification with exception > > matches classes with : int method(int, String) throws AException > OR int method(int, String) > > > COMPILATION: > > The compiler would use reflection to handle calling of the generic > methods themselves. > > For example: > public > void closeAllResources(List resources) { > for (T t : resources) { > t.close(); > } > } > > Would effectively become: > > void closeAllResources(List resources) { > for (T t : resources) { > try { > t.getClass().getMethod("close").invoke(t); > } catch (IllegalAccessException ex) { > throw new RuntimeException("Method close not found"); > } catch (InvocationTargetException ex) { > throw new RuntimeException("Method close not found"); > } catch (NoSuchMethodException ex) { > throw new RuntimeException("Method close not found"); > } > } > } > > The compiler would also check all uses of this feature, and generate a > compiler error if any usage does not match the criteria given. > > TESTING: > > The feature can be tested by compiling and running programs that > exercise the feature. > > LIBRARY SUPPORT: > > No. > > REFLECTIVE APIS: > > No. The use of this feature is compile time only. > > OTHER CHANGES: > > No. > > MIGRATION: > > No. This is a new feature and no existing code should be affected. > > COMPATIBILITY > > BREAKING CHANGES: > > No. > > EXISTING PROGRAMS: > > This is an addition to generics, and this change would be transparent to them. > > REFERENCES > > EXISTING BUGS: > > From Joe.Darcy at Sun.COM Sat May 16 18:53:37 2009 From: Joe.Darcy at Sun.COM (Joseph D. Darcy) Date: Sat, 16 May 2009 18:53:37 -0700 Subject: PROPOSAL: Enhanced for each loop iteration control In-Reply-To: <49EFE9AF.90909@sun.com> References: <49C56020.2070207@joda.org> <49EDE7B4.2090006@sun.com> <3BBAA5CF-247E-430F-A271-A10C79642FF7@zwitserloot.com> <49EFE9AF.90909@sun.com> Message-ID: <4A0F6E21.6080401@sun.com> PS A join facility for string is being tracked with Sun bug 5015163 "(str) String merge/join that is the inverse of String.split()." To me this sounds like a fine bug to be fixed in JDK 7: :http://mail.openjdk.java.net/pipermail/core-libs-dev/2009-March/001205.html -Joe Joseph D. Darcy wrote: > Reinier Zwitserloot wrote: >> If the proposal was just about making the iterator available, I'd >> agree with you, but the proposal adds methods like .first(), which >> are /very/ useful indeed. It's right up there with ARM, and easily >> beats string switching, in how applicable that would be. > > A library to implement the utility wrapper around an Iterator could be > added without the language change. > >> >> Adding a .join() method to String or List (depending on taste) would >> solve over half of the use-cases for the extended forloop, though. > > Adding one method to string is preferable to a language change! > > -Joe > From Joe.Darcy at Sun.COM Sat May 16 19:21:54 2009 From: Joe.Darcy at Sun.COM (Joseph D. Darcy) Date: Sat, 16 May 2009 19:21:54 -0700 Subject: PROPOSAL: Enhanced for each loop iteration control In-Reply-To: <1E6A673A-C521-4768-A02F-91019EA6CB8D@zwitserloot.com> References: <32096145.1241599561308.JavaMail.root@mswamui-andean.atl.sa.earthlink.net> <4A015C3A.5020406@paradise.net.nz> <5241B403-AA02-4A41-89A7-84B47B5254AB@zwitserloot.com> <4b4f45e00905060538p1405e893w1782373dbeb198b0@mail.gmail.com> <4A01DFBF.70902@sun.com> <1E6A673A-C521-4768-A02F-91019EA6CB8D@zwitserloot.com> Message-ID: <4A0F74C2.5060706@sun.com> PS Sun bug 6463989 "(coll) Provide Iterable utility methods and light-weight Iterable implementations" requests support for some helper methods operating on Iterable's that could be used to perform of the operations in question. -Joe Reinier Zwitserloot wrote: > Ah, that's my mistake. In that case, I know this isn't a democracy, > but, for what it's worth, I'll toss my hat into the ring for the > original 3-way colon separated proposal: > > for ( String foo : someStringList : anyName ) { > } > > > > where anyName's type becomes a class created for java 1.7, which > includes index(), isFirst(), remove(), and other useful utilities, all > based off of the iterator. I believe Stephen Colebourne made a formal > proposal for this one. > > > --Reinier Zwitserloot > Like it? Tip it! > http://tipit.to > > > > On May 6, 2009, at 21:06, Joe Darcy wrote: > > >> On 05/06/09 05:38 AM, Stephen Colebourne wrote: >> >>> 2009/5/6 Reinier Zwitserloot : >>> >>> >>>> the original 3-way colon-separated for proposal that was not even >>>> shortlisted by Joe Darcy. Why are we talking about this again? >>>> >>>> >>> The shortlist occurred before the end of Coin's submission period. >>> IIRC, this proposal was added after that shortlist was published. I >>> suspect that Joe is due to publish a more final shortlist soon. >>> >>> Stephen >>> >>> >>> >> Yes, I'm busy working on the short list and other coin matters :-) >> >> -Joe >> >> >> > > > From tim.lebedkov at googlemail.com Sun May 17 12:17:12 2009 From: tim.lebedkov at googlemail.com (Tim Lebedkov) Date: Sun, 17 May 2009 21:17:12 +0200 Subject: Proposal: Type inference for variable definition/initialization using the 'auto' keyword. In-Reply-To: <4b1e39a2a95d71051b5a990d7067d9d8.squirrel@wmail.gradsoft.ua> References: <4A0D0066.1060701@sun.com> <4A0DC0AE.7080103@sun.com> <4b1e39a2a95d71051b5a990d7067d9d8.squirrel@wmail.gradsoft.ua> Message-ID: Hello Ruslan, It would be really helpful if you could check the patterns on a larger code base. Not only to my proposal, but there is also one for using "final" like in: final m = new JTable().getModel(); // m is automatically typed *and* final. > pattern for auto : any variable definition. some examples: int a = t.getColumn(); for (int a: columns)... class A { auto a = "asldfkjsdlfj"; } > pattern for 'usefull' auto: any variable definition with > templates^H^H^H^H^H type parameters on left side. Let's define "useful" as "with type name longer than 4 characters" auto a = 5; // not useful because longer than "int a = 5;" auto m = new JTable().getModel(); // useful because shorter than TableModel m = new JTable().getModel() > pattern for diamond : any variable definition with allocation > expression at right side. I'd say (I hope I understand the proposal right) any variable definition with template based allocation like List a = new ArrayList(); becomes List a = new ArrayList<>(); Thank You for the offer --Tim 2009/5/16 Ruslan Shevchenko : > > > Sorry, can I ask what exactly patterns you mean. > > I. e. is such approximation is correct (?) > > ?pattern for auto ? ? ? ? ?: any variable definition. > ?pattern for 'usefull' auto: any variable definition with > templates^H^H^H^H^H type parameters on left side. > ?pattern for diamond ? ? ? : any variable definition with allocation > expression at right side. > > > If this is correct, I will add one to set of coin patterns. > >> >> You're right. These two classes are not statistically significant, but: >> - number of lines where "auto" can be used is always >= the number of >> lines where "diamond" can be used >> - you have probably written many thousands of lines in Java. Don't you >> have at least the feeling that there are at least 3-5 times more >> ? variable definitions without object creation than with it? >> - (in case you do not have such feeling :-) I'd try to count lines on >> a larger source base. >> > > > From david at walend.net Sun May 17 16:45:42 2009 From: david at walend.net (David Walend) Date: Sun, 17 May 2009 19:45:42 -0400 Subject: PROPOSAL: Abstract enums (version 2) In-Reply-To: References: Message-ID: <3224672D-3B9D-4666-9FDB-8533A3DC9474@walend.net> On May 13, 2009, at 2:53 AM, coin-dev-request at openjdk.java.net wrote: > Date: Wed, 13 May 2009 10:35:17 +1000 > From: Howard Lovatt > Subject: Re: PROPOSAL: Abstract enums (version 2) > > On a pragmatic point, I doubt if the proposal will go anywhere since > no one is supporting it except me :( The point you make about wanting > to change from a singleton to a number of instances in the future > might be valid, but I haven't personally had this problem in using > Scala and I haven't heard of others having problems in Scala. > > The main enhancement I would find useful is to be able to extend an > arbitrary abstract class when making an enum. The present proposal of > a special abstract enum wouldn't help my use cases much. Therefore I > don't thing the Singleton variation is that important. Howard, I'll speak for enumerations extending abstract classes. It comes up every forth project or so for me; machine-readable JMX notifications come to mind. A lot of general purpose abstract classes should only be used certain ways within a particular context. Sometimes those ways fit an enum well. With the current limitation, I have to extend the abstract class, then create an enum full of pass-through methods. It's uninteresting boilerplate, and labor to maintain. I'd use enums this way occasionally if it were part of JDK7. Dave From howard.lovatt at iee.org Mon May 18 00:35:36 2009 From: howard.lovatt at iee.org (Howard Lovatt) Date: Mon, 18 May 2009 17:35:36 +1000 Subject: PROPOSAL: open and close brace optional for single statement try, catch, finally, method declaration In-Reply-To: References: <3dd3f56a0905150034v3a30d0bfr66885137ae15805@mail.gmail.com> Message-ID: <3dd3f56a0905180035t6a29b069sf13fee907718df39@mail.gmail.com> I personally use Jalopy for this purpose, so for me it isn't a problem. However if numerous tools exist to make sure you don't make a mistake then it is probably a sign that their is a problem with the language construct. -- Howard. 2009/5/16 Tom Ball : > At Google braces are compulsory for the reasons you state, although we use > code-reviews rather than language changes to enforce it.? I strongly > encourage engineering teams to investigate the use of existing tools to help > them "ratchet up" their source code quality.? CheckStyle, for example, can > also be used as a preprocessor or VCS check-in verifier step to verify that > braces are always used. > > Tom > > On Fri, May 15, 2009 at 12:34 AM, Howard Lovatt > wrote: >> >> I would go the other way and make braces compulsory in all cases >> including single line blocks for if, while, etc. I say this because I >> have found missing braces to be a source of errors, particularly for >> newbies. >> >> ?-- Howard. >> > > > ______________________________________________________________________ > This email has been scanned by the MessageLabs Email Security System. > For more information please visit http://www.messagelabs.com/email > ______________________________________________________________________ > -- -- Howard. From howard.lovatt at iee.org Mon May 18 01:13:16 2009 From: howard.lovatt at iee.org (Howard Lovatt) Date: Mon, 18 May 2009 18:13:16 +1000 Subject: Notes on implementing concise calls to constructors with type parameters In-Reply-To: <15e8b9d20905150633n5f3cbb92q79a37a4e736b93b9@mail.gmail.com> References: <3dd3f56a0905132041r67710789if86d4e942987a039@mail.gmail.com> <15e8b9d20905132115r58bfe6a7naa6952e5f94c1392@mail.gmail.com> <3dd3f56a0905140543v63603bd4qed2a149fc06cb0ce@mail.gmail.com> <15e8b9d20905140932g33fbcd7atd6c6e28f95211cb4@mail.gmail.com> <3dd3f56a0905150026ta489f58lece1b35ee17df44d@mail.gmail.com> <15e8b9d20905150633n5f3cbb92q79a37a4e736b93b9@mail.gmail.com> Message-ID: <3dd3f56a0905180113l1b7dab5fge695caba96fdcf72@mail.gmail.com> Hi Neal, Yes I should have spelled this out, it is one of those things obvious to the author but not to the reader. I would propose that given more than one method of the same name, method in example below, with the general declaration for each following the syntax: ... method ( typeLHS [] name , ... ) { ... } and given the call: ... method ( new [typeRHS] [] ( ... ) , ... ); Then a three step procedure would be used: 1. If typeRHS is absent assume for step 2 type Void, where Void is the bottom type (in Java 7 this may be called Null but I chose Void to be consistent with the InvokeDynamic proposal) 2. Resolve method as normal and hence find typeLHS and if specified genericParametersLHS also 3. Apply textual substitution algorithm, i.e. If typeRHS is absent substitute typeLHS and if genericParametersRHS is absent and genericParametersLHS is present then substitute genericParametersLHS For example, given two methods: void method( Object notUsed ) { out.println( "Object" ); } void method( String notUsed ) { out.println( "String" ); } The call: method( new() ); would print String because it would be translated by the textual substitution algorithm into method( new String() ), i.e. the same behaviour as method( null ) because null has type Void (bottom). Does that add sufficient clarity? I would be really interested if you can see a problem with the technique? If not the method maybe a good solution as it has many desirable characteristics (as listed in previous posts in this thread). I also note that many people would like a var or auto style declaration and maybe this proposal of text substitution can satisfy more people than other proposals, since it retains LHS types but saves re-specification of type, generic type, and doesn't require a diamond operator on the RHS. -- Howard. 2009/5/15 Neal Gafter : > On Fri, May 15, 2009 at 12:26 AM, Howard Lovatt > wrote: >> >> Consider a simple method declaration: >> >> returnType methodName ( typeLHS [] name , ... ) { >> ... } >> >> and a simple method call >> >> ... methodName ( new [typeRHS] [] ( ... ) , ... ); >> >> Then the same substituting of missing items algorithm given above can >> be used. The two examples that yourself and Maurizio have discussed >> would work, i.e.: >> >> *class X {* >> * ?public X( T t ) { ... }* >> *}* >> >> *void f( X xs ) ...* >> >> the code >> >> *f( new X( "foo" ) )* >> >> gets translated into: >> >> *f( new X( "foo" ) )* >> >> and: >> >> *void f( List xs ) ...* >> >> the following method call >> >> *f( new ArrayList() )* >> >> gets translated into: >> >> *f( new ArrayList() )* >> >> Therefore the textual substitution method proposed works for both of >> these cases. > > Is this textual substitution supposed to be applied before overload > resolution (i.e. before the method to be invoked is identified) or after > method resolution (i.e. after the types of the arguments have already been > resolved)? ? Or are you planning a major overhaul of the specification of > method invocation expressions?? You haven't provided enough of a hint for us > to evaluate your proposal.? Can you please be more precise about what JLS > changes you are proposing? > > ______________________________________________________________________ > This email has been scanned by the MessageLabs Email Security System. > For more information please visit http://www.messagelabs.com/email > ______________________________________________________________________ > -- -- Howard. From rssh at gradsoft.com.ua Sun May 17 23:34:36 2009 From: rssh at gradsoft.com.ua (Ruslan Shevchenko) Date: Mon, 18 May 2009 09:34:36 +0300 (EEST) Subject: Proposal: Type inference for variable definition/initialization using the 'auto' keyword. In-Reply-To: References: <4A0D0066.1060701@sun.com> <4A0DC0AE.7080103@sun.com> <4b1e39a2a95d71051b5a990d7067d9d8.squirrel@wmail.gradsoft.ua> Message-ID: <99207756021168bc1ca8adbc9ff7a126.squirrel@wmail.gradsoft.ua> I changed useful auto to be at least 7 symbols. Difference is still huge. (It's not all data array yet;) jetty: all variable initializers : 3687 initializers with type arguments or long type names : 837 initializers with allocation and type arguments : 0 gwt-user: all variable initializers : 4208 initializers with type arguments or long type names : 1673 nitializers with allocation and type arguments : 252 hibernate: all variable initializers : 10271 initializers with type arguments or long type names : 4013 initializers with allocation and type arguments : 100 I will post more details with full report at evening/in GMT+2/. > Hello Ruslan, > > It would be really helpful if you could check the patterns on a larger > code base. > Not only to my proposal, but there is also one for using "final" like in: > final m = new JTable().getModel(); // m is automatically typed *and* > final. > >> pattern for auto : any variable definition. > some examples: > int a = t.getColumn(); > for (int a: columns)... > class A { > auto a = "asldfkjsdlfj"; > } > >> pattern for 'usefull' auto: any variable definition with >> templates^H^H^H^H^H type parameters on left side. > Let's define "useful" as "with type name longer than 4 characters" > auto a = 5; // not useful because longer than "int a = 5;" > auto m = new JTable().getModel(); // useful because shorter than > TableModel m = new JTable().getModel() > >> pattern for diamond : any variable definition with allocation >> expression at right side. > I'd say (I hope I understand the proposal right) any variable > definition with template based allocation like > List a = new ArrayList(); becomes > List a = new ArrayList<>(); > > Thank You for the offer > --Tim > > 2009/5/16 Ruslan Shevchenko : >> >> >> Sorry, can I ask what exactly patterns you mean. >> >> I. e. is such approximation is correct (?) >> >> ?pattern for auto ? ? ? ? ?: any variable definition. >> ?pattern for 'usefull' auto: any variable definition with >> templates^H^H^H^H^H type parameters on left side. >> ?pattern for diamond ? ? ? : any variable definition with allocation >> expression at right side. >> >> >> If this is correct, I will add one to set of coin patterns. >> >>> >>> You're right. These two classes are not statistically significant, but: >>> - number of lines where "auto" can be used is always >= the number of >>> lines where "diamond" can be used >>> - you have probably written many thousands of lines in Java. Don't you >>> have at least the feeling that there are at least 3-5 times more >>> ? variable definitions without object creation than with it? >>> - (in case you do not have such feeling :-) I'd try to count lines on >>> a larger source base. >>> >> >> >> > From rssh at gradsoft.com.ua Sun May 17 23:40:27 2009 From: rssh at gradsoft.com.ua (Ruslan Shevchenko) Date: Mon, 18 May 2009 09:40:27 +0300 (EEST) Subject: StringBuffer/Builder vs Collection Access Message-ID: <6411db7ae4ab40ee62f61fedefeb5c8f.squirrel@wmail.gradsoft.ua> Also partial results, full data later: Under simplicified collection element access i understand call of Collection.get or List.set or Map.put Under simplicified StringBuilder/Buffer append: call of StringBuilder.append or StringBuffer.append jetty: simplicified collection element access : 241 simplicified StringBuilder/Buffer syntax : 363 gwt-user: simplicified collection element access : 324 simplicified StringBuilder/Buffer syntax : 216 hibernate: simplicified collection element access : 613 simplicified StringBuilder/Buffer syntax : 1128 From ARDOINT at fr.ibm.com Mon May 18 02:36:45 2009 From: ARDOINT at fr.ibm.com (Jean Louis Ardoint) Date: Mon, 18 May 2009 11:36:45 +0200 Subject: Proposal: Accepting a subclass as an element type in a for loop In-Reply-To: <4A0CFC42.1090402@sun.com> References: <4A0CFC42.1090402@sun.com> Message-ID: Hi Joe, Thank you for your answer and your pointer to the interesting use of Class.cast in ElementFilter. I agree that what I proposed can be done by using library classes or methods, yet such a solution comes with a cost in terms of performance and memory. In ElementFilter for example, the whole collection gets duplicated. This could be avoided by implementing specific Iterable and Iterator interfaces, yet you would still get two allocations for some code that would not require any by writing it manually or using the proposal. Eventually better JVMs will remove the cost of those extra allocated objects but it is not the case as of today. Still, the problem addressed by my proposal seems to be too specific. I think it could be made more interesting if it took into account filtering in a loop in a broader sense, for example by adding an optional test to a foreach loop: for (Rectangle r : shapes; r != null && r.length() * r.width() < 12) drawRectangle(r); that would replace: for (Shape s : shapes) { if (s instanceof Rectangle) { Rectangle r = (Shape)s; if (r != null && r.length() * r.width() < 12) drawRectangle(r); } } Jean-Louis From: "Joseph D. Darcy" To: Jean-Louis Ardoint Cc: coin-dev at openjdk.java.net Date: 15/05/2009 07:24 Subject: Re: Proposal: Accepting a subclass as an element type in a for loop Sent by: Joe.Darcy at Sun.COM Jean-Louis Ardoint wrote: > I'm maybe a bit too late. Here's my proposal anyway. > > > > -- Jean-Louis Ardoint > > > > Accepting a subclass as an element type in a for loop > > > Catching up on proposal comments, I agree with the previous replies on the list that this scenario is more than adequately handled by filtering library methods. FYI, one class implementing these kinds of filters in the JDK is javax.lang.model.util.ElementFilter. -Joe Sauf indication contraire ci-dessus:/ Unless stated otherwise above: Compagnie IBM France Si?ge Social : Tour Descartes, 2, avenue Gambetta, La D?fense 5, 92400 Courbevoie RCS Nanterre 552 118 465 Forme Sociale : S.A.S. Capital Social : 609.751.783,30 ? SIREN/SIRET : 552 118 465 02430 From schulz at e-Spirit.de Mon May 18 02:51:05 2009 From: schulz at e-Spirit.de (Schulz, Stefan) Date: Mon, 18 May 2009 11:51:05 +0200 Subject: Some notes on Elvis and Other Null-Safe Operators In-Reply-To: <4A0D00A9.3080304@sun.com> References: <171AADE5-112F-43EB-AEED-4E502EE0914E@googlemail.com> <4A0D00A9.3080304@sun.com> Message-ID: <7D2077BFF677D2429DDDEE095D9A48AC1130CA00@osiris2.e-spirit.de> Joseph D. Darcy wrote: > Mark Mahieu wrote: > > Elvis operator can be approximated as a library method: > > > > static T elvis(T t1, T t2) { return t1 != null > ? t1 : t2; } > > > > In a core-libs round table recording (at > http://mail.openjdk.java.net/ > > pipermail/core-libs-dev/2009-April/001406.html) the possibility of > > adding core library methods for common null-handling tasks is > > mentioned, such as throwing a standard exception if a supplied > > argument is null (presumably similar to methods in > > com.google.common.base.Preconditions). Is it reasonable to > implement > > the Elvis operator as a language change but other null-handling > > facilities as library changes? > > > > A belated reply, in general and for null handling in particular, > addressing the problem with libraries is preferable to addressing the > problem with a language change. > > -Joe Just as a side note: while such a library based solution for elvis is formally possible, without some closure like construct, the advantage of evaluating the RHS expression on demand only will be lost. Cheers, Stefan From scolebourne at joda.org Mon May 18 04:37:11 2009 From: scolebourne at joda.org (Stephen Colebourne) Date: Mon, 18 May 2009 12:37:11 +0100 Subject: Some notes on Elvis and Other Null-Safe Operators In-Reply-To: <7D2077BFF677D2429DDDEE095D9A48AC1130CA00@osiris2.e-spirit.de> References: <171AADE5-112F-43EB-AEED-4E502EE0914E@googlemail.com> <4A0D00A9.3080304@sun.com> <7D2077BFF677D2429DDDEE095D9A48AC1130CA00@osiris2.e-spirit.de> Message-ID: <4b4f45e00905180437w9b91912gd556ec5dee62ee9f@mail.gmail.com> 2009/5/18 Schulz, Stefan : > Joseph D. Darcy wrote: >> A belated reply, in general and for null handling in particular, >> addressing the problem with libraries is preferable to addressing the >> problem with a language change. > > Just as a side note: while such a library based solution for elvis is formally possible, without some closure like construct, the advantage of evaluating the RHS expression on demand only will be lost. I'd also note that libraries have been available for elvis for some time, yet they are not especially widely used. All the evidence is that developers would rather code the if statement themselves than import a library. Stephen From neal at gafter.com Mon May 18 08:41:39 2009 From: neal at gafter.com (Neal Gafter) Date: Mon, 18 May 2009 08:41:39 -0700 Subject: Notes on implementing concise calls to constructors with type parameters In-Reply-To: <3dd3f56a0905180113l1b7dab5fge695caba96fdcf72@mail.gmail.com> References: <3dd3f56a0905132041r67710789if86d4e942987a039@mail.gmail.com> <15e8b9d20905132115r58bfe6a7naa6952e5f94c1392@mail.gmail.com> <3dd3f56a0905140543v63603bd4qed2a149fc06cb0ce@mail.gmail.com> <15e8b9d20905140932g33fbcd7atd6c6e28f95211cb4@mail.gmail.com> <3dd3f56a0905150026ta489f58lece1b35ee17df44d@mail.gmail.com> <15e8b9d20905150633n5f3cbb92q79a37a4e736b93b9@mail.gmail.com> <3dd3f56a0905180113l1b7dab5fge695caba96fdcf72@mail.gmail.com> Message-ID: <15e8b9d20905180841n11b9825aj59d9bf6f4aa1a3f1@mail.gmail.com> I don't understand how this is all supposed to work when typeRHS is absent and is then inferred to be a generic type involving wildcards (e.g. List). Are we supposed to just drop the wildcards? It seems madness to ignore the types of the (constructor) parameters, the type parameter bounds, the relationship between the type parameters in typeLHS and typeRHS, etc, in doing type inference. That's probably not something that can be done "later" because of compatibility. For an example, consider class Permutation implements Map { ... } Textual substitution cannot work with this class. Regards, Neal On Mon, May 18, 2009 at 1:13 AM, Howard Lovatt wrote: > Hi Neal, > > Yes I should have spelled this out, it is one of those things obvious > to the author but not to the reader. I would propose that given more > than one method of the same name, method in example below, with the > general declaration for each following the syntax: > > ... method ( typeLHS [] name , ... ) { ... } > > and given the call: > > ... method ( new [typeRHS] [] ( ... ) , ... ); > > Then a three step procedure would be used: > > 1. If typeRHS is absent assume for step 2 type Void, where Void is the > bottom type (in Java 7 this may be called Null but I chose Void to be > consistent with the InvokeDynamic proposal) > > 2. Resolve method as normal and hence find typeLHS and if specified > genericParametersLHS also > > 3. Apply textual substitution algorithm, i.e. If typeRHS is absent > substitute typeLHS and if genericParametersRHS is absent and > genericParametersLHS is present then substitute genericParametersLHS > > For example, given two methods: > > void method( Object notUsed ) { out.println( "Object" ); } > void method( String notUsed ) { out.println( "String" ); } > > The call: > > method( new() ); > > would print String because it would be translated by the textual > substitution algorithm into method( new String() ), i.e. the same > behaviour as method( null ) because null has type Void (bottom). > > Does that add sufficient clarity? I would be really interested if you > can see a problem with the technique? > > If not the method maybe a good solution as it has many desirable > characteristics (as listed in previous posts in this thread). I also > note that many people would like a var or auto style declaration and > maybe this proposal of text substitution can satisfy more people than > other proposals, since it retains LHS types but saves re-specification > of type, generic type, and doesn't require a diamond operator on the > RHS. > > -- Howard. > > 2009/5/15 Neal Gafter : > > On Fri, May 15, 2009 at 12:26 AM, Howard Lovatt > > wrote: > >> > >> Consider a simple method declaration: > >> > >> returnType methodName ( typeLHS [] name , ... ) { > >> ... } > >> > >> and a simple method call > >> > >> ... methodName ( new [typeRHS] [] ( ... ) , ... ); > >> > >> Then the same substituting of missing items algorithm given above can > >> be used. The two examples that yourself and Maurizio have discussed > >> would work, i.e.: > >> > >> *class X {* > >> * public X( T t ) { ... }* > >> *}* > >> > >> *void f( X xs ) ...* > >> > >> the code > >> > >> *f( new X( "foo" ) )* > >> > >> gets translated into: > >> > >> *f( new X( "foo" ) )* > >> > >> and: > >> > >> *void f( List xs ) ...* > >> > >> the following method call > >> > >> *f( new ArrayList() )* > >> > >> gets translated into: > >> > >> *f( new ArrayList() )* > >> > >> Therefore the textual substitution method proposed works for both of > >> these cases. > > > > Is this textual substitution supposed to be applied before overload > > resolution (i.e. before the method to be invoked is identified) or after > > method resolution (i.e. after the types of the arguments have already > been > > resolved)? Or are you planning a major overhaul of the specification of > > method invocation expressions? You haven't provided enough of a hint for > us > > to evaluate your proposal. Can you please be more precise about what JLS > > changes you are proposing? > > > > ______________________________________________________________________ > > This email has been scanned by the MessageLabs Email Security System. > > For more information please visit http://www.messagelabs.com/email > > ______________________________________________________________________ > > > > > > -- > -- Howard. > From rssh at gradsoft.com.ua Mon May 18 06:45:07 2009 From: rssh at gradsoft.com.ua (Ruslan Shevchenko) Date: Mon, 18 May 2009 16:45:07 +0300 (EEST) Subject: more syntax patterns[ v5] Message-ID: Good day. Next set of syntax patterns for count of LOCs, affected by coin possible optimizations with results is available. main changes from previous set are: - added count for using collection indexes. (I. e. number of LOCs, probably will be optimized after implementing index array access) (pattern named 'simplicified collection element access', for review see lines from 313 to 353 of checkers_coin.def [ http://redmine.gradsoft.ua/repositories/entry/javachecker/trunk/JavaChecker/etc/checkers_coin.def ]) - added count for using simplicified string builder/buffer append (pattern named 'simplicified StringBuilder/Buffer syntax', lines 285-311) - added count for variable declarators with initializers. ('all variable initializers', lines 355-363) - added count for variable initializers, applicable for proposal: Type inference for variable definition/initialization using the 'auto' keyword. ('initializers with type arguments or long type names', lines 365-415) - added count for variable initalizers, applicable for 'diamond' proposal [i.e. calls of counstructor with type parameters] ('initializers with allocation and type arguments', lines 417-468) //in short - auto proposal for type inheritance is a clean winner. - integrated counters for traditional for loops, which not only applicable to 'Enhanced for each loop iteration control', but can also be transformed to java5 foreach loop. (file etc/checkers_coin_loop.def) - removed incorrect counters for elvis proposal (see summary of elvis1 and nullsafe call of fields and methods instead) - removed counters for syntax bit-and with 0xFF - added 'Compiere ERP' for set of analyzed sources. // And yes, exception catching is differ from frameworks exactly as in Stephen Colebourne measurements for e-commerce system (see http://mail.openjdk.java.net/pipermail/coin-dev/2009-April/001597.html) Results are: openjdk-jdk: all bit ands : 6814 all conditional expressions : 6770 all catchs : 8411 all ifs : 28442 all integer literals : 120613 all traditional fors : 11530 all variable initializers : 139836 initializers with type arguments or long type names : 40211 big integer literals(undescores) : 4589 byte literal : 1452 catch in finally : 103 simplicified collection element access : 5438 initializers with allocation and type arguments : 1499 elvis1 : 437 for loop (length),convertable to foreach : 1515 for loop (size),convertable to foreach : 158 for loop from 0 to size or length : 3137 for with limit like it.next() : 235 instanceof switch : 317 loop with remove : 94 multi catch : 412 nullsafe call of fields and methods : 384 object switch : 1360 rethrow clause : 3267 simplicified StringBuilder/Buffer syntax : 5142 string in switch : 444 widening operator (semantics) : 1090 Files:9278 Compiere ERP: all bit ands : 17 all conditional expressions : 435 all catchs : 2251 all ifs : 6158 all integer literals : 22482 all traditional fors : 719 all variable initializers : 31027 initializers with type arguments or long type names : 9990 big integer literals(undescores) : 1422 byte literal : 1 catch in finally : 82 simplicified collection element access : 732 initializers with allocation and type arguments : 708 elvis1 : 36 for loop (length),convertable to foreach : 130 for loop (size),convertable to foreach : 136 for loop from 0 to size or length : 476 for with limit like it.next() : 2 instanceof switch : 31 loop with remove : 4 multi catch : 7 nullsafe call of fields and methods : 31 object switch : 257 rethrow clause : 46 simplicified StringBuilder/Buffer syntax : 4635 string in switch : 215 widening operator (semantics) : 1 Files:2110 jetty: all bit ands : 121 all conditional expressions : 277 all catchs : 281 all ifs : 764 all integer literals : 2903 all traditional fors : 315 all variable initializers : 3687 initializers with type arguments or long type names : 837 big integer literals(undescores) : 25 byte literal : 52 catch in finally : 3 simplicified collection element access : 241 initializers with allocation and type arguments : 0 elvis1 : 33 for loop (length),convertable to foreach : 63 for loop (size),convertable to foreach : 16 for loop from 0 to size or length : 100 for with limit like it.next() : 4 instanceof switch : 8 invalid checker comments : 0 loop with remove : 0 multi catch : 22 nullsafe call of fields and methods : 35 object switch : 31 rethrow clause : 34 simplicified StringBuilder/Buffer syntax : 363 string in switch : 19 widening operator (semantics) : 10 Files:187 gwt-user: all bit ands : 58 all conditional expressions : 208 all catchs : 171 all ifs : 735 all integer literals : 2282 all traditional fors : 271 all variable initializers : 4208 initializers with type arguments or long type names : 1673 big integer literals(undescores) : 24 byte literal : 2 catch in finally : 2 simplicified collection element access : 324 initializers with allocation and type arguments : 252 elvis1 : 18 for loop (length),convertable to foreach : 24 for loop (size),convertable to foreach : 5 for loop from 0 to size or length : 71 for with limit like it.next() : 20 instanceof switch : 6 loop with remove : 7 multi catch : 9 nullsafe call of fields and methods : 10 object switch : 27 rethrow clause : 84 simplicified StringBuilder/Buffer syntax : 216 string in switch : 10 widening operator (semantics) : 0 Files:920 Hibernate: all bit ands : 2 all conditional expressions : 792 all catchs : 650 all ifs : 2410 all integer literals : 3240 all traditional fors : 708 all variable initializers : 10271 initializers with type arguments or long type names : 4013 big integer literals(undescores) : 12 byte literal : 1 catch in finally : 27 simplicified collection element access : 613 initializers with allocation and type arguments : 100 elvis1 : 77 for loop (length),convertable to foreach : 177 for loop (size),convertable to foreach : 17 for loop from 0 to size or length : 385 for with limit like it.next() : 16 instanceof switch : 28 loop with remove : 12 multi catch : 25 nullsafe call of fields and methods : 116 object switch : 94 rethrow clause : 450 simplicified StringBuilder/Buffer syntax : 1128 string in switch : 86 widening operator (semantics) : 0 Files:1372 If you want run checker on own codeset or play with patterns, it can be download as http://datacenter.gradsoft.ua/public.repository/ua.gradsoft/javachecker/installations/JavaCheckerBinaryInstaller-2.5.0p5.jar How to run: see instructions at the end of the first letter: http://mail.openjdk.java.net/pipermail/coin-dev/2009-April/001442.html Hope, this information will be useful. Regards ! From rssh at gradsoft.com.ua Mon May 18 07:43:04 2009 From: rssh at gradsoft.com.ua (Ruslan Shevchenko) Date: Mon, 18 May 2009 17:43:04 +0300 (EEST) Subject: more syntax patterns[ v5] In-Reply-To: References: Message-ID: <5c5c559c9d5e29c580ddb48a3fc6de7e.squirrel@wmail.gradsoft.ua> > > If you want run checker on own codeset or play with patterns, it can be > download as > http://datacenter.gradsoft.ua/public.repository/ua.gradsoft/javachecker/installations/JavaCheckerBinaryInstaller-2.5.0p5.jar > Sorry, instructions was for source-installer, so url must be read as http://datacenter.gradsoft.ua/public.repository/ua.gradsoft/javachecker/installations/JavaCheckerSourceInstaller-2.5.0p5.jar > How to run: see instructions at the end of the first letter: > http://mail.openjdk.java.net/pipermail/coin-dev/2009-April/001442.html > > Hope, this information will be useful. > Regards ! > > > > From vapor1 at teleport.com Mon May 18 11:45:24 2009 From: vapor1 at teleport.com (Derek Foster) Date: Mon, 18 May 2009 11:45:24 -0700 Subject: StringBuffer/Builder vs Collection Access In-Reply-To: <6411db7ae4ab40ee62f61fedefeb5c8f.squirrel@wmail.gradsoft.ua> References: <6411db7ae4ab40ee62f61fedefeb5c8f.squirrel@wmail.gradsoft.ua> Message-ID: <4ADC1BEF-F84C-4354-A354-B84D9F00BC5C@teleport.com> Thanks for researching this, Ruslan. I note that these results don't seem to include the constructs "SV += SE" or "SV = SV + SE" where SV is a String variable and SE is a String expression. These constructs would also be candidates for replacement with the new StringBuilder/StringBuffer operators. Also, any calls to "SBE.setLength(0)" where SBE is an expression of type StringBuffer or StringBuilder could be replaced with 'SBE = ""' under the current proposal. Also, any code like "SB foo = new SB();" or "SB foo=new SB(SE)" could be replaced with "SB foo = SE" under the current proposal (where SB is StringBuffer or StringBuilder and SE is a string expression). Thanks again for your time spent researching this! Derek On May 17, 2009, at 11:40 PM, "Ruslan Shevchenko" wrote: > > Also partial results, full data later: > > Under simplicified collection element access i understand call of > Collection.get or List.set or Map.put > > Under simplicified StringBuilder/Buffer append: call of > StringBuilder.append or StringBuffer.append > > > jetty: > simplicified collection element access : 241 > simplicified StringBuilder/Buffer syntax : 363 > > gwt-user: > simplicified collection element access : 324 > simplicified StringBuilder/Buffer syntax : 216 > > hibernate: > simplicified collection element access : 613 > simplicified StringBuilder/Buffer syntax : 1128 > > > > > From tim.lebedkov at googlemail.com Mon May 18 13:06:01 2009 From: tim.lebedkov at googlemail.com (Tim Lebedkov) Date: Mon, 18 May 2009 22:06:01 +0200 Subject: more syntax patterns[ v5] In-Reply-To: References: Message-ID: Hello Ruslan, once again thank you for the great work. Regards --Tim On Mon, May 18, 2009 at 3:45 PM, Ruslan Shevchenko wrote: > Good day. > > ?Next set of syntax patterns for count of LOCs, affected by coin possible > optimizations with results is available. > > main changes from previous set are: > > - added count for using collection indexes. (I. e. number of LOCs, > probably will be optimized after implementing index array access) > (pattern named 'simplicified collection element access', for review see > lines from 313 to 353 of checkers_coin.def [ > http://redmine.gradsoft.ua/repositories/entry/javachecker/trunk/JavaChecker/etc/checkers_coin.def > ]) > > - added count for using simplicified string builder/buffer append > (pattern named 'simplicified StringBuilder/Buffer syntax', lines 285-311) > > - added count for variable declarators with initializers. > ('all variable initializers', lines 355-363) > > - added count for variable initializers, applicable for proposal: Type > inference for variable definition/initialization using the 'auto' keyword. > ('initializers with type arguments or long type names', lines 365-415) > > - added count for variable initalizers, applicable for 'diamond' proposal > [i.e. calls of counstructor with type parameters] > ('initializers with allocation and type arguments', lines 417-468) > > //in short - auto proposal for type inheritance is a clean winner. > > - integrated counters for traditional for loops, which not only applicable > to 'Enhanced for each loop iteration control', but can also be transformed > to java5 foreach loop. (file etc/checkers_coin_loop.def) > > - removed incorrect counters for elvis proposal (see summary of elvis1 and > ?nullsafe call of fields and methods instead) > > - removed counters for syntax bit-and with 0xFF > > - added 'Compiere ERP' ?for set of analyzed sources. > ?// And yes, exception catching is differ from frameworks ?exactly as in > Stephen Colebourne measurements for e-commerce system (see > http://mail.openjdk.java.net/pipermail/coin-dev/2009-April/001597.html) > > Results are: > > openjdk-jdk: > all bit ands ? ?: ? ? ? 6814 > all conditional expressions ? ? : ? ? ? 6770 > all catchs ? ? ?: ? ? ? 8411 > all ifs : ? ? ? 28442 > all integer literals ? ?: ? ? ? 120613 > all traditional fors ? ?: ? ? ? 11530 > all variable initializers ? ? ? : ? ? ? 139836 > initializers with type arguments or long type names ? ? : ? ? ? 40211 > big integer literals(undescores) ? ? ? ?: ? ? ? 4589 > byte literal ? ?: ? ? ? 1452 > catch in finally ? ? ? ?: ? ? ? 103 > simplicified collection element access ?: ? ? ? 5438 > initializers with allocation and type arguments : ? ? ? 1499 > elvis1 ?: ? ? ? 437 > for loop (length),convertable to foreach ? ? ? ?: ? ? ? 1515 > for loop (size),convertable to foreach ?: ? ? ? 158 > for loop from 0 to size or length ? ? ? : ? ? ? 3137 > for with limit like it.next() ? : ? ? ? 235 > instanceof switch ? ? ? : ? ? ? 317 > loop with remove ? ? ? ?: ? ? ? 94 > multi catch ? ? : ? ? ? 412 > nullsafe call of fields and methods ? ? : ? ? ? 384 > object switch ? : ? ? ? 1360 > rethrow clause ?: ? ? ? 3267 > simplicified StringBuilder/Buffer syntax ? ? ? ?: ? ? ? 5142 > string in switch ? ? ? ?: ? ? ? 444 > widening operator (semantics) ? : ? ? ? 1090 > Files:9278 > > Compiere ERP: > all bit ands ? ?: ? ? ? 17 > all conditional expressions ? ? : ? ? ? 435 > all catchs ? ? ?: ? ? ? 2251 > all ifs : ? ? ? 6158 > all integer literals ? ?: ? ? ? 22482 > all traditional fors ? ?: ? ? ? 719 > all variable initializers ? ? ? : ? ? ? 31027 > initializers with type arguments or long type names ? ? : ? ? ? 9990 > big integer literals(undescores) ? ? ? ?: ? ? ? 1422 > byte literal ? ?: ? ? ? 1 > catch in finally ? ? ? ?: ? ? ? 82 > simplicified collection element access ?: ? ? ? 732 > initializers with allocation and type arguments : ? ? ? 708 > elvis1 ?: ? ? ? 36 > for loop (length),convertable to foreach ? ? ? ?: ? ? ? 130 > for loop (size),convertable to foreach ?: ? ? ? 136 > for loop from 0 to size or length ? ? ? : ? ? ? 476 > for with limit like it.next() ? : ? ? ? 2 > instanceof switch ? ? ? : ? ? ? 31 > loop with remove ? ? ? ?: ? ? ? 4 > multi catch ? ? : ? ? ? 7 > nullsafe call of fields and methods ? ? : ? ? ? 31 > object switch ? : ? ? ? 257 > rethrow clause ?: ? ? ? 46 > simplicified StringBuilder/Buffer syntax ? ? ? ?: ? ? ? 4635 > string in switch ? ? ? ?: ? ? ? 215 > widening operator (semantics) ? : ? ? ? 1 > Files:2110 > > jetty: > all bit ands ? ?: ? ? ? 121 > all conditional expressions ? ? : ? ? ? 277 > all catchs ? ? ?: ? ? ? 281 > all ifs : ? ? ? 764 > all integer literals ? ?: ? ? ? 2903 > all traditional fors ? ?: ? ? ? 315 > all variable initializers ? ? ? : ? ? ? 3687 > initializers with type arguments or long type names ? ? : ? ? ? 837 > big integer literals(undescores) ? ? ? ?: ? ? ? 25 > byte literal ? ?: ? ? ? 52 > catch in finally ? ? ? ?: ? ? ? 3 > simplicified collection element access ?: ? ? ? 241 > initializers with allocation and type arguments : ? ? ? 0 > elvis1 ?: ? ? ? 33 > for loop (length),convertable to foreach ? ? ? ?: ? ? ? 63 > for loop (size),convertable to foreach ?: ? ? ? 16 > for loop from 0 to size or length ? ? ? : ? ? ? 100 > for with limit like it.next() ? : ? ? ? 4 > instanceof switch ? ? ? : ? ? ? 8 > invalid checker comments ? ? ? ?: ? ? ? 0 > loop with remove ? ? ? ?: ? ? ? 0 > multi catch ? ? : ? ? ? 22 > nullsafe call of fields and methods ? ? : ? ? ? 35 > object switch ? : ? ? ? 31 > rethrow clause ?: ? ? ? 34 > simplicified StringBuilder/Buffer syntax ? ? ? ?: ? ? ? 363 > string in switch ? ? ? ?: ? ? ? 19 > widening operator (semantics) ? : ? ? ? 10 > Files:187 > > gwt-user: > all bit ands ? ?: ? ? ? 58 > all conditional expressions ? ? : ? ? ? 208 > all catchs ? ? ?: ? ? ? 171 > all ifs : ? ? ? 735 > all integer literals ? ?: ? ? ? 2282 > all traditional fors ? ?: ? ? ? 271 > all variable initializers ? ? ? : ? ? ? 4208 > initializers with type arguments or long type names ? ? : ? ? ? 1673 > big integer literals(undescores) ? ? ? ?: ? ? ? 24 > byte literal ? ?: ? ? ? 2 > catch in finally ? ? ? ?: ? ? ? 2 > simplicified collection element access ?: ? ? ? 324 > initializers with allocation and type arguments : ? ? ? 252 > elvis1 ?: ? ? ? 18 > for loop (length),convertable to foreach ? ? ? ?: ? ? ? 24 > for loop (size),convertable to foreach ?: ? ? ? 5 > for loop from 0 to size or length ? ? ? : ? ? ? 71 > for with limit like it.next() ? : ? ? ? 20 > instanceof switch ? ? ? : ? ? ? 6 > loop with remove ? ? ? ?: ? ? ? 7 > multi catch ? ? : ? ? ? 9 > nullsafe call of fields and methods ? ? : ? ? ? 10 > object switch ? : ? ? ? 27 > rethrow clause ?: ? ? ? 84 > simplicified StringBuilder/Buffer syntax ? ? ? ?: ? ? ? 216 > string in switch ? ? ? ?: ? ? ? 10 > widening operator (semantics) ? : ? ? ? 0 > Files:920 > > Hibernate: > all bit ands ? ?: ? ? ? 2 > all conditional expressions ? ? : ? ? ? 792 > all catchs ? ? ?: ? ? ? 650 > all ifs : ? ? ? 2410 > all integer literals ? ?: ? ? ? 3240 > all traditional fors ? ?: ? ? ? 708 > all variable initializers ? ? ? : ? ? ? 10271 > initializers with type arguments or long type names ? ? : ? ? ? 4013 > big integer literals(undescores) ? ? ? ?: ? ? ? 12 > byte literal ? ?: ? ? ? 1 > catch in finally ? ? ? ?: ? ? ? 27 > simplicified collection element access ?: ? ? ? 613 > initializers with allocation and type arguments : ? ? ? 100 > elvis1 ?: ? ? ? 77 > for loop (length),convertable to foreach ? ? ? ?: ? ? ? 177 > for loop (size),convertable to foreach ?: ? ? ? 17 > for loop from 0 to size or length ? ? ? : ? ? ? 385 > for with limit like it.next() ? : ? ? ? 16 > instanceof switch ? ? ? : ? ? ? 28 > loop with remove ? ? ? ?: ? ? ? 12 > multi catch ? ? : ? ? ? 25 > nullsafe call of fields and methods ? ? : ? ? ? 116 > object switch ? : ? ? ? 94 > rethrow clause ?: ? ? ? 450 > simplicified StringBuilder/Buffer syntax ? ? ? ?: ? ? ? 1128 > string in switch ? ? ? ?: ? ? ? 86 > widening operator (semantics) ? : ? ? ? 0 > Files:1372 > > If you want run checker on own codeset or play with patterns, it can be > download as > http://datacenter.gradsoft.ua/public.repository/ua.gradsoft/javachecker/installations/JavaCheckerBinaryInstaller-2.5.0p5.jar > > How to run: see instructions at the end of the first letter: > http://mail.openjdk.java.net/pipermail/coin-dev/2009-April/001442.html > > Hope, this information will be useful. > Regards ! > > > > From neal at gafter.com Mon May 18 14:20:38 2009 From: neal at gafter.com (Neal Gafter) Date: Mon, 18 May 2009 14:20:38 -0700 Subject: Notes on implementing concise calls to constructors with type parameters In-Reply-To: <15e8b9d20905180841n11b9825aj59d9bf6f4aa1a3f1@mail.gmail.com> References: <3dd3f56a0905132041r67710789if86d4e942987a039@mail.gmail.com> <15e8b9d20905132115r58bfe6a7naa6952e5f94c1392@mail.gmail.com> <3dd3f56a0905140543v63603bd4qed2a149fc06cb0ce@mail.gmail.com> <15e8b9d20905140932g33fbcd7atd6c6e28f95211cb4@mail.gmail.com> <3dd3f56a0905150026ta489f58lece1b35ee17df44d@mail.gmail.com> <15e8b9d20905150633n5f3cbb92q79a37a4e736b93b9@mail.gmail.com> <3dd3f56a0905180113l1b7dab5fge695caba96fdcf72@mail.gmail.com> <15e8b9d20905180841n11b9825aj59d9bf6f4aa1a3f1@mail.gmail.com> Message-ID: <15e8b9d20905181420s61c5530ble15499b90701423d@mail.gmail.com> One more thing. What if "genericParametersRHS" contain captured wildcards or conjunctive types? On Mon, May 18, 2009 at 8:41 AM, Neal Gafter wrote: > I don't understand how this is all supposed to work when typeRHS is absent > and is then inferred to be a generic type involving wildcards (e.g. List extends Number>). Are we supposed to just drop the wildcards? > > It seems madness to ignore the types of the (constructor) parameters, the > type parameter bounds, the relationship between the type parameters in > typeLHS and typeRHS, etc, in doing type inference. That's probably not > something that can be done "later" because of compatibility. > > For an example, consider > > class Permutation implements Map { ... } > > Textual substitution cannot work with this class. > > Regards, > Neal > > > On Mon, May 18, 2009 at 1:13 AM, Howard Lovatt wrote: > >> Hi Neal, >> >> Yes I should have spelled this out, it is one of those things obvious >> to the author but not to the reader. I would propose that given more >> than one method of the same name, method in example below, with the >> general declaration for each following the syntax: >> >> ... method ( typeLHS [] name , ... ) { ... } >> >> and given the call: >> >> ... method ( new [typeRHS] [] ( ... ) , ... ); >> >> Then a three step procedure would be used: >> >> 1. If typeRHS is absent assume for step 2 type Void, where Void is the >> bottom type (in Java 7 this may be called Null but I chose Void to be >> consistent with the InvokeDynamic proposal) >> >> 2. Resolve method as normal and hence find typeLHS and if specified >> genericParametersLHS also >> >> 3. Apply textual substitution algorithm, i.e. If typeRHS is absent >> substitute typeLHS and if genericParametersRHS is absent and >> genericParametersLHS is present then substitute genericParametersLHS >> >> For example, given two methods: >> >> void method( Object notUsed ) { out.println( "Object" ); } >> void method( String notUsed ) { out.println( "String" ); } >> >> The call: >> >> method( new() ); >> >> would print String because it would be translated by the textual >> substitution algorithm into method( new String() ), i.e. the same >> behaviour as method( null ) because null has type Void (bottom). >> >> Does that add sufficient clarity? I would be really interested if you >> can see a problem with the technique? >> >> If not the method maybe a good solution as it has many desirable >> characteristics (as listed in previous posts in this thread). I also >> note that many people would like a var or auto style declaration and >> maybe this proposal of text substitution can satisfy more people than >> other proposals, since it retains LHS types but saves re-specification >> of type, generic type, and doesn't require a diamond operator on the >> RHS. >> >> -- Howard. >> >> 2009/5/15 Neal Gafter : >> > On Fri, May 15, 2009 at 12:26 AM, Howard Lovatt >> > wrote: >> >> >> >> Consider a simple method declaration: >> >> >> >> returnType methodName ( typeLHS [] name , ... ) { >> >> ... } >> >> >> >> and a simple method call >> >> >> >> ... methodName ( new [typeRHS] [] ( ... ) , ... >> ); >> >> >> >> Then the same substituting of missing items algorithm given above can >> >> be used. The two examples that yourself and Maurizio have discussed >> >> would work, i.e.: >> >> >> >> *class X {* >> >> * public X( T t ) { ... }* >> >> *}* >> >> >> >> *void f( X xs ) ...* >> >> >> >> the code >> >> >> >> *f( new X( "foo" ) )* >> >> >> >> gets translated into: >> >> >> >> *f( new X( "foo" ) )* >> >> >> >> and: >> >> >> >> *void f( List xs ) ...* >> >> >> >> the following method call >> >> >> >> *f( new ArrayList() )* >> >> >> >> gets translated into: >> >> >> >> *f( new ArrayList() )* >> >> >> >> Therefore the textual substitution method proposed works for both of >> >> these cases. >> > >> > Is this textual substitution supposed to be applied before overload >> > resolution (i.e. before the method to be invoked is identified) or after >> > method resolution (i.e. after the types of the arguments have already >> been >> > resolved)? Or are you planning a major overhaul of the specification >> of >> > method invocation expressions? You haven't provided enough of a hint >> for us >> > to evaluate your proposal. Can you please be more precise about what >> JLS >> > changes you are proposing? >> > >> > ______________________________________________________________________ >> > This email has been scanned by the MessageLabs Email Security System. >> > For more information please visit http://www.messagelabs.com/email >> > ______________________________________________________________________ >> > >> >> >> >> -- >> -- Howard. >> > > From reinier at zwitserloot.com Mon May 18 21:13:35 2009 From: reinier at zwitserloot.com (Reinier Zwitserloot) Date: Tue, 19 May 2009 06:13:35 +0200 Subject: Some notes on Elvis and Other Null-Safe Operators In-Reply-To: <4b4f45e00905180437w9b91912gd556ec5dee62ee9f@mail.gmail.com> References: <171AADE5-112F-43EB-AEED-4E502EE0914E@googlemail.com> <4A0D00A9.3080304@sun.com> <7D2077BFF677D2429DDDEE095D9A48AC1130CA00@osiris2.e-spirit.de> <4b4f45e00905180437w9b91912gd556ec5dee62ee9f@mail.gmail.com> Message-ID: <84D303B5-3659-43C3-A6AE-E363A715FC96@zwitserloot.com> There's a big difference between: 'available in some third party library' and 'available in java core libraries'. Take Pair (also known as Tuple). There are a couple thousand implementations floating around, I bet. Everyone rolls their own, because including a complete library just for Pair/Tuple, especially considering that in java land, adding a library is not a matter of tossing a one-liner in your java file and letting java/javac take care of the rest (we need ant, maven, ivy, protoJ, or other tools to go hunt down those dependencies for us). It's just too small - the effort of adding any form of dependency management is much bigger than rolling your own half-baked Tuple.java. That's an entire class, so imagine what happens for the elvis operation. The effort of even adding the dependency if there's already a dependency framework in place is borderline too much effort for something as simple as the elvis operation. This same process happens on the small scale as well: Because writing 1 if statement is so simple, nobody initially bothers to roll their own elvis utility method. In theory, after needing it a couple of times, you should abstract away the elvis operation, but its such a trivial operation that the lines blur and there's no urgent impression upon the programmer that something is amiss in the source base and needs abstracting. So, is the elvis operator a good idea? Probably - I'm mostly agnostic*, but if I had to make the final call, sure, why not. However, we clearly cannot say that 'the library path doesn't work' - because we haven't tested the library path yet. Toss it into java.lang.Something, and if people then still won't go for it, THEN we know it won't fly as a library**. *) The biggest problem with the entire elvis line of thinking is that it promotes nulls and null handling at runtime, which I think is fundamentally un-java-like. I've heard plenty of complaints that it would be too complicated, but I strongly prefer moving nullity into the type system. Not the Fan copout - that doesn't work; you'd still have plenty of situations where you have a variable, it should have been compile-time possible to determine its nullity, but you don't know and the compiler/editor can't tell you (because of generics). I want the complete solution, which includes 4 nullity states: Definitely not legal to hold null, Absolutely legal to hold null, Might or might not legally hold null, and legacy type (analogous to the raw type for generics, and with similar semantics: Acts like might or might not legally hold null in practice, but you can assign it to any of the other nullity states, and get a warning instead of an error). It's not that complicated - certainly simpler than generics, and mostly the same principle. **) But how would the elvis operation in a library look like? Without closures or some other control statement abstraction, any elvis operation as a java static method that I can think of is considerably more horrible. Adding CICE to java would help, but not much. --Reinier Zwitserloot On May 18, 2009, at 13:37, Stephen Colebourne wrote: > 2009/5/18 Schulz, Stefan : >> Joseph D. Darcy wrote: >>> A belated reply, in general and for null handling in particular, >>> addressing the problem with libraries is preferable to addressing >>> the >>> problem with a language change. >> >> Just as a side note: while such a library based solution for elvis >> is formally possible, without some closure like construct, the >> advantage of evaluating the RHS expression on demand only will be >> lost. > > I'd also note that libraries have been available for elvis for some > time, yet they are not especially widely used. All the evidence is > that developers would rather code the if statement themselves than > import a library. > > Stephen > From markmahieu at googlemail.com Mon May 18 22:34:39 2009 From: markmahieu at googlemail.com (Mark Mahieu) Date: Tue, 19 May 2009 06:34:39 +0100 Subject: Some notes on Elvis and Other Null-Safe Operators In-Reply-To: <84D303B5-3659-43C3-A6AE-E363A715FC96@zwitserloot.com> References: <171AADE5-112F-43EB-AEED-4E502EE0914E@googlemail.com> <4A0D00A9.3080304@sun.com> <7D2077BFF677D2429DDDEE095D9A48AC1130CA00@osiris2.e-spirit.de> <4b4f45e00905180437w9b91912gd556ec5dee62ee9f@mail.gmail.com> <84D303B5-3659-43C3-A6AE-E363A715FC96@zwitserloot.com> Message-ID: On 19 May 2009, at 05:13, Reinier Zwitserloot wrote: > > So, is the elvis operator a good idea? Probably - I'm mostly > agnostic*, but if I had to make the final call, sure, why not. Can't beat a well-reasoned argument like that ;) > However, we clearly cannot say that 'the library path doesn't work' - > because we haven't tested the library path yet. Toss it into > java.lang.Something, and if people then still won't go for it, THEN we > know it won't fly as a library**. Is that language design by Coin-toss? Mark From reinier at zwitserloot.com Mon May 18 23:06:36 2009 From: reinier at zwitserloot.com (Reinier Zwitserloot) Date: Tue, 19 May 2009 08:06:36 +0200 Subject: Some notes on Elvis and Other Null-Safe Operators In-Reply-To: References: <171AADE5-112F-43EB-AEED-4E502EE0914E@googlemail.com> <4A0D00A9.3080304@sun.com> <7D2077BFF677D2429DDDEE095D9A48AC1130CA00@osiris2.e-spirit.de> <4b4f45e00905180437w9b91912gd556ec5dee62ee9f@mail.gmail.com> <84D303B5-3659-43C3-A6AE-E363A715FC96@zwitserloot.com> Message-ID: I agree with you that this 'meh, let's see what happens' attitude doesn't exactly sound kosher, but them's the breaks. Presuming, of course, that you agree that there's a -big- difference for very small utility classes and methods being in java core, and being in a third party library. That, or we make guesses about a Utils.elvis() method's popularity, which seems similarly objectionable. But, back on the topic of the elvis operator as a library for a moment: Even if some form of it would be added to the core libraries, what would that look like? All I can come up with: with the actual null checking operators: public void test() { Integer x = foo?.bar()?.baz(); return x ?: 0; } library attempt: public void test() { Integer x = Utils.ifNotNull(new IfNotNullBlock() { public void run() { return foo.bar().baz(); } }); return Utils.elvis(x, 0); } contrast this to how I'd do this now, without either a library or an operator: public void test() { Integer x = barBaz(foo); return x != null ? x : 0; } private void fooBarBaz(Foo foo) { if ( foo == null ) return null; Bar bar = foo.bar(); if ( bar == null ) return null; return bar.baz(); } The actual elvis operator could be a library, sure, but a null-safe dereferencing operator clearly couldn't be, unless I'm missing something. Because elvis looks acceptable without a library, just written out with a ternary operator, and because elvis does librarify (coining words here!) somewhat nicely, The amount of pain/boilerplate you can eliminate with the null safe derefencing operator (?.) is considerably bigger than elvis. Though, from anecdotal evidence and Ruslan's work, ?: would be useful more often. Personally, I can't recall even a single instance of having to write out a chain of method calls that all need to be null-safed out (though I admit I tend to avoid nulls like the plague in the first place). The value of a language change for coin is something along the lines of (boilerplate eliminated * frequency of use case) / (negative impact on the language). The negative impact part is equal, as far as I can tell, so it boils down to boilerplate*frequency. I'm not sure which one is the winner there - elvis avoids a little boilerplate a lot of the time, and null-safe dereference avoids a lot of boilerplate, only a few times. Given that introducing related changes in batch form has its own advantages, I'm somewhat confused as to why this proposal isn't a both or neither kind of deal: Whats the thinking behind introducing ?: but not ?. and, possibly, ?[], though where do you draw the line? Technically we'd need a synchronized ( foo? ), a throw foo?, and a for ( x : foo? ) as well, if you want to cover all the situations that can result in NPEs!). FWIW, the for ( x : foo? ) thing seems more useful to me than ?[], because arrays are a niche device compared to the Collections API, and the amount of boilerplate involved is bigger (either a lengthy foo ?: Collections.emptyList() - which adds an import dependency, or a whole new nesting level by prefixing the entire for loop with an if ( foo != null ) {}, compared to just foo != null ? foo[x] : null). --Reinier Zwitserloot On May 19, 2009, at 07:34, Mark Mahieu wrote: > > On 19 May 2009, at 05:13, Reinier Zwitserloot wrote: >> >> So, is the elvis operator a good idea? Probably - I'm mostly >> agnostic*, but if I had to make the final call, sure, why not. > > Can't beat a well-reasoned argument like that ;) > > >> However, we clearly cannot say that 'the library path doesn't work' - >> because we haven't tested the library path yet. Toss it into >> java.lang.Something, and if people then still won't go for it, THEN >> we >> know it won't fly as a library**. > > Is that language design by Coin-toss? > > > Mark From rssh at gradsoft.com.ua Tue May 19 01:43:20 2009 From: rssh at gradsoft.com.ua (Ruslan Shevchenko) Date: Tue, 19 May 2009 11:43:20 +0300 (EEST) Subject: StringBuffer/Builder vs Collection Access In-Reply-To: <4ADC1BEF-F84C-4354-A354-B84D9F00BC5C@teleport.com> References: <6411db7ae4ab40ee62f61fedefeb5c8f.squirrel@wmail.gradsoft.ua> <4ADC1BEF-F84C-4354-A354-B84D9F00BC5C@teleport.com> Message-ID: Thanks for corrections. Will be included in v6. Regards ! > > I note that these results don't seem to include the constructs "SV += > SE" or "SV = SV + SE" where SV is a String variable and SE is a String > expression. These constructs would also be candidates for replacement > with the new StringBuilder/StringBuffer operators. > > Also, any calls to "SBE.setLength(0)" where SBE is an expression of > type StringBuffer or StringBuilder could be replaced with 'SBE = ""' > under the current proposal. > > Also, any code like "SB foo = new SB();" or "SB foo=new SB(SE)" could > be replaced with "SB foo = SE" under the current proposal (where SB is > StringBuffer or StringBuilder and SE is a string expression). > > Thanks again for your time spent researching this! > > Derek > > > On May 17, 2009, at 11:40 PM, "Ruslan Shevchenko" > wrote: > >> >> Also partial results, full data later: >> >> Under simplicified collection element access i understand call of >> Collection.get or List.set or Map.put >> >> Under simplicified StringBuilder/Buffer append: call of >> StringBuilder.append or StringBuffer.append >> >> >> jetty: >> simplicified collection element access : 241 >> simplicified StringBuilder/Buffer syntax : 363 >> >> gwt-user: >> simplicified collection element access : 324 >> simplicified StringBuilder/Buffer syntax : 216 >> >> hibernate: >> simplicified collection element access : 613 >> simplicified StringBuilder/Buffer syntax : 1128 >> >> >> >> >> > From Dmitry.Miltsov at Sun.COM Tue May 19 05:42:11 2009 From: Dmitry.Miltsov at Sun.COM (Dmitry Miltsov) Date: Tue, 19 May 2009 16:42:11 +0400 Subject: JCK feedback on "Strings in Switch" proposal Message-ID: <4A12A923.9060501@sun.com> Hello, The JCK engineers have reviewed the "Strings in switch" proposal and found one issue to clarify. "14.11 The switch Statement" states: ------------------------------------------------------------------ ... Otherwise, execution continues by comparing the value of the Expression with each case constant. Then there is a choice: * If one of the case constants is equal to the value of the expression, then we say that the case matches ... ------------------------------------------------------------------ It would be good to clarify what "equal" means in case of the String values. It would be useful to mention that in this case the result of comparison will be "expression.equals(constant)", not "expression == constant" as for other types. We have no special comments on testability of this feature. The JCK team will develop conformance tests for it. Thanks, Dmitry Miltsov, JCK engineer From Joe.Darcy at Sun.COM Tue May 19 14:52:42 2009 From: Joe.Darcy at Sun.COM (Joe Darcy) Date: Tue, 19 May 2009 14:52:42 -0700 Subject: JCK feedback on "Strings in Switch" proposal In-Reply-To: <4A12A923.9060501@sun.com> References: <4A12A923.9060501@sun.com> Message-ID: <4A132A2A.6020708@sun.com> Hello. On 05/19/09 05:42 AM, Dmitry Miltsov wrote: > Hello, > > The JCK engineers have reviewed the "Strings in switch" proposal > and found one issue to clarify. > > "14.11 The switch Statement" states: > ------------------------------------------------------------------ > ... > Otherwise, execution continues by comparing the value of the > Expression with each case constant. Then there is a choice: > * If one of the case constants is equal to the value of the > expression, then we say that the case matches ... > ------------------------------------------------------------------ > > It would be good to clarify what "equal" means in case of the > String values. It would be useful to mention that in this case > the result of comparison will be "expression.equals(constant)", > not "expression == constant" as for other types. > I think that would be a fine note to make in a discussion comment. > We have no special comments on testability of this feature. > The JCK team will develop conformance tests for it. > > Thanks, > Dmitry Miltsov, JCK engineer > > Thanks, -Joe From Joe.Darcy at Sun.COM Tue May 19 15:25:58 2009 From: Joe.Darcy at Sun.COM (Joe Darcy) Date: Tue, 19 May 2009 15:25:58 -0700 Subject: PROPOSAL: Unsigned Integer Widening Operator In-Reply-To: <49CA07D3.8090909@peralex.com> References: <49C9F30E.2020008@paradise.net.nz> <49CA07D3.8090909@peralex.com> Message-ID: <4A1331F6.3010904@sun.com> Hello. Further proposal catch-up, I would prefer a library-based approach to address this issue. Later in JDK 7, I hope to get a constellation of unsigned libraries work implemented and integrated: 4504839 Java libraries should provide support for unsigned integer arithmetic 4215269 Some Integer.toHexString(int) results cannot be decoded back to an int 6282196 There should be Math.mod(number, modulo) methods 6322074 Converting integers to string as if unsigned 5100935 No way to access the 64-bit integer multiplication of 64-bit CPUs efficiently Part of the first bug would be some unsigned conversion. I was thinking either a set of methods like int Integer.unsigned(short val); int Integer.unsigned(byte val); long Long.unsigned(int val); long Long.unsigned(short val); long Long.unsigned(byte val); or short Byte.toUnsignedShort(byte b); int Byte.toUnsignedInt(byte b); long Byte.toUnsignedLong(byte b); ... -Joe On 03/25/09 03:30 AM, Noel Grandin wrote: > I would think that a utility class that performed widening operations, > and maybe some other useful stuff would be preferable to extending the > language/ > > Perhaps a BinaryMath class to live alongside java.lang.Math? > > Regards, Noel. > > Bruce Chapman wrote: > >> Title >> Unsigned Integer Widening Operator >> >> latest html version at http://docs.google.com/Doc?id=dcvp3mkv_2k39wt5gf&hl >> >> AUTHOR(S): Bruce Chapman >> >> OVERVIEW >> >> >> >> FEATURE SUMMARY: >> Add an unsigned widening operator to convert bytes (in particular), >> shorts, and chars (for completeness) to int while avoiding sign extension. >> >> >> MAJOR ADVANTAGE: >> >> Byte manipulation code becomes littered with (b & 0xFF) expressions in >> order to reverse the sign extension that occurs when a byte field or >> variable or array access appears on either side of an operator and is >> thus subject to widening conversion with its implicit sign extension. >> This masking with 0xFF can detract from the clarity of the code by >> masking the actual algorithm. It is the Java Language's rules and not >> the algorithm itself that demand this masking operation which can appear >> to be a redundant operation to the uninitiated. >> >> >> It is highly intentional that the new operator (+) can be read as a cast >> to a positive. >> >> >> >> MAJOR DISADVANTAGE: >> A new operator. >> >> >> ALTERNATIVES: >> >> explicit masking. If java.nio.ByteBuffer was extensible (it isn't) >> unsigned get and set methods could be added to hide the masking in an >> API. Extension methods could be employed to that end if they were >> implemented. >> >> EXAMPLES >> SIMPLE EXAMPLE: >> >> byte[] buffer = ...; int idx=...; int length=...; >> >> int value=0; >> >> for(int i = idx; i < idx + length; i++) { >> value = (value << 8) | (buffer[i] & 0xff); >> } >> >> can be recoded as >> >> >> for(int i = idx; i < idx + length; i++) { >> value = (value << 8) | (+)buffer[i]; >> } >> >> >> ADVANCED EXAMPLE: >> >> private int getBerValueLength(byte[] contents, int idx) { >> if((contents[idx] & 0x80) == 0) return contents[idx]; >> int lenlen = (+)contents[idx] ^ 0x80; // invert high bit which = 1 >> int result=0; >> for(int i = idx+1; i < idx + 1 + lenlen; i++ ) { >> result = (result << 8) | (+)contents[i]; >> } >> return result; >> } >> >> DETAILS >> SPECIFICATION: >> >> amend 15.15 >> >> The unary operators include +, -, ++, --, ~, !, unsigned integer >> widening operator and cast operators. >> >> >> >> add the following to the grammars in 15.15 >> >> >> >> The following productions from ?new section are repeated here for >> convenience: >> >> >> UnsignedWideningExpression: >> >> UnsignedIntegerWideningOperator UnaryExpression >> >> >> UnsignedIntegerWideningOperator: >> >> ( + ) >> >> >> >> Add a new section to 15 - between "15.15 Unary Expressions" and "15.16 >> Cast Expressions" would seem ideal in terms of context and precedence level. >> >> >> The unsigned integer widening operator is a unary operator which may be >> applied to expressions of type byte, short and char. It is a compile >> time error to apply this operator to other types. >> >> >> UnsignedWideningExpression: >> >> UnsignedIntegerWideningOperator UnaryExpression >> >> >> UnsignedIntegerWideningOperator: >> >> ( + ) >> >> >> The unsigned integer widening operator converts its operand to type int. >> Unary numeric promotion (?) is NOT performed on the operand. For a byte >> operand, the lower order 8 bits of the resultant have the same values as >> in the operand. For short and char operands, the resultant's lower order >> 16 bits have the same value as the operand's. The remaining high order >> bits are set to zero. This is effectively a zero extend widening >> conversion and is equivalent to the following expression for byte operand x, >> >> x & 0xFF >> >> and equivalent to the following for a short or char operand y >> >> y & 0xFFFF >> >> >> Other sections have lists of operators for which various things apply. >> Add to these as appropriate - yet to be determined. >> >> Note the specification above could also be ammended to allow the >> operator to zero extend an int to a long, however the utility value of >> this is uncertain. >> COMPILATION: >> >> Compilation may be equivalent to the masking operation above. Hotspot >> could detect the redundant sign extend followed by masking out the sign >> extended bits and remove both. If that were the case the operator could >> be applied to every access of a byte field, variable or array to >> indicate treatment as unsigned byte, with no cost. >> >> >> For a char, the operator is equivalent to a widening conversion to int. >> The new operator is permitted on a char expression because there is no >> reason to disallow it. However it would be equally effective if it did >> not apply to char. >> >> >> TESTING: >> >> There are no gnarly use cases, so testing is straight forward. It could >> be as simple as compiling and executing a main class with a handful of >> asserts. >> >> LIBRARY SUPPORT: >> >> No library support required. >> >> REFLECTIVE APIS: >> >> None >> >> OTHER CHANGES: >> >> none foreseen >> >> MIGRATION: >> >> COMPATIBILITY >> BREAKING CHANGES: >> >> None >> >> EXISTING PROGRAMS: >> >> Tools could detect the specific masking operations used to zero extend a >> previously sign extended byte or short, and replace that with the new >> operator. >> >> REFERENCES >> EXISTING BUGS: >> >> http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4186775 >> >> http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4879804 >> >> http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4504839 >> >> >> URL FOR PROTOTYPE (optional): >> None >> >> >> >> >> > > > Disclaimer: http://www.peralex.com/disclaimer.html > > > > From Joe.Darcy at Sun.COM Tue May 19 15:37:51 2009 From: Joe.Darcy at Sun.COM (Joe Darcy) Date: Tue, 19 May 2009 15:37:51 -0700 Subject: PROPOSAL: Using Ordinary Syntax for Reflective Method Invocations In-Reply-To: <53374.69.239.104.86.1238181944.squirrel@69.239.104.86> References: <53374.69.239.104.86.1238181944.squirrel@69.239.104.86> Message-ID: <4A1334BF.3040309@sun.com> Catching up on proposal commenting, don't find this proposal to be detailed enough to evaluated fully, type system vocabulary is definitely needed to explain what was intended! That said, since generics aren't reified at runtime, there are likely to be impedance mismatches in calling generic methods under such a proposal. -Joe On 03/27/09 12:25 PM, Alan Snyder wrote: > Using Ordinary Syntax for Reflective Method Invocations > > > AUTHOR: Alan Snyder > > OVERVIEW > > FEATURE SUMMARY: > > This proposal allows ordinary method invocation syntax to be used to issue > a reflective method invocation, when enabled by the use of a new marker > type for the target object. > > MAJOR ADVANTAGE: > > Invoking a method using the reflection API is tedious and verbose, and it > does not look anything like the corresponding ordinary method invocation > that would be used when the target class or interface is statically known. > The proposal allows the ordinary method invocation syntax to be used > instead to invoke a method using reflection. > > MAJOR BENEFIT: > > This proposal makes invoking methods using reflection much easier to write > and also much more readable. > > When a programmer wants to avoid creating a static dependency on an > optional module, one way to do so is to invoke the module using > reflection. (Note that the target interface may be packaged with the rest > of the module, so even a static reference to the target interface would > create a dependency.) This proposal would make such loose couplings much > simpler and more natural, and would also make it easier to change from > tight coupling to loose coupling, or vice versa. > > MAJOR DISADVANTAGE: > > A small language change is required, involving the introduction of a new > marker type and an extension of method invocation semantics to cover the > new marker type. > > ALTERNATIVES: > > The major alternatives are to use an IDE or a (nonstandard) preprocessor > to generate the appropriate calls on the reflection API. IDE generated > code is easy to write but remains difficult to read. Preprocessors do not > interact well with tools, especially debuggers. > > EXAMPLE: > > Here is a simple invocation of a method on an object whose type is not > statically known. The type Unknown is the new marker type that signals the > use of reflection to invoke methods on the object so declared. > > Unknown o = ...; // obtain object without referencing its class > try { > String s = (String) o.getName("Foo", 3); > } catch (InvocationTargetException ex) { > ... method threw an exception > } catch (Exception ex) { > ... could not find method, invoke method, or wrong result type > } > > A more complex example might need to use a type cast to provide a type for > a null argument: > > String s = (String) o.getName((String) null, 3); > > Another complex example would handle the various individual exceptions > that can be raised: > > try { > String s = (String) o.getName("Foo", 3); > } catch (NoSuchMethodException ex) { > ... > } catch (SecurityException ex) { > ... > } catch (IllegalAccessException ex) { > ... > } catch (ExceptionInInitializerError ex) { > ... > } catch (InvocationTargetException ex) { > ... > } catch (ClassCastException ex) { > ... > } > > DETAILS > > The proposal requires the introduction of a new marker type, which I am > calling Unknown. It could be new interface, perhaps in java.reflect. My > thought is that extending this interface probably should not be allowed, > as it would seem pointless. > > The Unknown type is used by the programmer to indicate a desire to perform > reflective invocations on an object whose type is not statically known. It > is thus different than Object (despite having the same set of declared > methods), where no such intent is implied. Thus, there is no relaxation of > static type checking in programs that do not explicitly use this new > feature. > > When the compiler encounters a method invocation where the static type of > the target object expression is Unknown, it replaces the static invocation > with the equivalent reflection code, something like this: > > { > Class c = o.getClass(); > Class c1 = String.class; > Class c2 = Integer.class; > Method m = c.getMethod("getName", c1, c2); > Object arg1 = "Foo"; > Object arg2 = 3; > String s = (String) m.invoke(o, arg1, arg2); > } > > The Class objects used in the method lookup are determined based on the > expression types of the invocation argument expressions, not the runtime > types of the argument objects. (The latter would fail to handle null > arguments, for example.) As in the above example, the null literal could > not be used without a type cast. I do not claim to have full command of > the type system vocabulary, but it seems to me that the process is roughly > equivalent to creating a class literal based on the result of type > erasure. > > SPECIFICATION: > > JLS 15.12.1 would need to be changed to recognize this new case. > Specifically, this clause: > > If the form is Primary.NonWildTypeArgumentsopt Identifier, then the > name of the method is the Identifier. Let T be the type of the Primary > expression; then the class or interface to be searched is T if T is a > class or interface type, or the upper bound of T if T is a type > variable. > > would be extended as follows: > > If the form is Primary.NonWildTypeArgumentsopt Identifier, then the > name of the method is the Identifier. Let T be the type of the Primary > expression; then the class or interface to be searched is T if T is a > class or interface type, or the upper bound of T if T is a type > variable. However, if T is the interface Unknown, no search of that > interface is performed. Instead, the method is determined at runtime > by examining the class of the target object. > > Since the JLS does not define reflection, it is not clear to me whether > the exact details would be specified in the JLS. > > COMPILATION: > > The compiler would have to implement this new case. I don't believe there > are any new concepts involved. Debuggers should be changed to make the > invocation look like an ordinary invocation. > > COMPATIBILITY > > The major compatibility issue arises from the introduction of a new name > in the class name space. That could potentially cause a program to fail to > compile if it imported a class with the name Unknown using a wild card > import statement. > > > > From Joe.Darcy at Sun.COM Tue May 19 15:44:20 2009 From: Joe.Darcy at Sun.COM (Joe Darcy) Date: Tue, 19 May 2009 15:44:20 -0700 Subject: Extend switch .. case statement for Object types and simple expressions In-Reply-To: <49D10FE6.3000404@gmx.de> References: <49D10FE6.3000404@gmx.de> Message-ID: <4A133644.40104@sun.com> Hello. Catching up on comments. On 03/30/09 11:31 AM, Ulf Zibis wrote: > AUTHOR(S): Ulf Zibis, Cologne, Germany > > OVERVIEW > FEATURE SUMMARY: Extend switch .. case statement for Object types and simple expressions. > MAJOR ADVANTAGE: > - Increases readability of source in concurrence to if .. else if .. else syntax. > - Sophisticated jumps. > MAJOR BENEFIT: > Stop some programmers escaping to some modern scripting language. > MAJOR DISADVANTAGE: > Programmers from other languages, especially C, may be confused about such rich syntax. > I'm also a bit confused over what exactly is being proposed; it does feel to me to be a rather aggressive change to switch. -Joe > EXAMPLES > SIMPLE EXAMPLE: > (1): > switch( myObject) { > case CONSTANT1 : doSomething(); break; > case CONSTANT2 : doSomethingElse(); break; > default : doSomethingDefault(); > } > (2): > switch( myString) { > case equals("red") : stop(); break; > case equals("green") : go(); break; > default : openYourEyesForCrossingTraffic(); > } > (3): > switch( myString) { > case equalsIgnoreCase("RED") : sureStop(); break; > case equalsIgnoreCase("GREEN") : sureGo(); break; > default : beAwareOfPoliceWachtingYou(); > } > > ADVANCED EXAMPLE: > (1): > switch( primitiveInt) { > case == 10 : doOnlyIf10(); // alternative syntax for 'case 10:' > case < 10 : > case >= 20 : break; > default : doOnlyInRange(); > } > (2): > switch( primitiveInt) { > case (>= 10 && < 20) : doOnlyInRange(); > default : throw new Exception("Out of range"); > } > (3): > switch( myString) { > case contains("foo") : doSomething(); break; > case regionMatches(true, 2, otherString, 4, 6) : doSomethingElse(); break; > default : doSomethingDefault(); > } > (4): > switch( myString.equals()) { // alternative: myString.equals(..) > case "foo" : foo(); break; > case "bar" : bar(); break; > default : dontCare(); > } > (5): > switch( className.startsWith("String", ..)) { // alternative: className.startsWith("String", ?) > case 0 : doForSimpleName(); break; > case 9 : doForFullName(); break; > default : canNotDecide(); > } > (6): > switch( anyObjectOrPrimitive instanceof) { // note, that casting is solved implicit > case boolean, byte, ... float : break; // Don't do anything > case double : forDouble(anyObjectOrPrimitive); > case HashMap : > case TreeMap : forPlattformMap(anyObjectOrPrimitive); break; > case Map : forOtherMap(anyObjectOrPrimitive); break; > default : forObject(anyObjectOrPrimitive); > } > (7): > switch( some_lethargic_function_we_cant_call_much().equals(..) ) { > case "this": > case "that": this_or_that(); break; > case "bigjump": big(); // fall > case "jump": jump(); break; > case "secondlastchance": > case "lastchance": last_chance(); break; > default: do_default(); > } > .. as replacement for: > String sSomeString = some_lethargic_function_we_cant_call_much(); > if( sSomeString.equals( "this" ) || sSomeString.equals( "that" ) ) > this_or_that(); > else if( sSomeString.equals( "jump" ) || sSomeString.equals( "bigjump" ) ) > { > if( sSomeString.equals( "bigjump" ) ) > big(); > jump(); > } else if( sSomeString.equals( "secondlastchance" ) || > sSomeString.equals( "lastchance" ) ) > { > last_chance(); > } else do_default(); > > ALTERNATIVES: > switch( myString) { // note the '.', I personally would prefer this alternative! > case .equals("red") : stop(); break; > case .equals("green") : go(); break; > default : openYourEyesForCrossingTraffic(); > } > switch( primitiveInt) { // note the '.' > case (. >= 10 && . < 20) : doOnlyInRange(); > // case (? >= 10 && ? < 20) : doOnlyInRange(); // alternative > default : throw new Exception("Out of range"); > } > > > DETAILS > SPECIFICATION: > The new syntax should be interpreted as > switch ( leftExpressionPart ) { > case rightExpressionPart1 : > case rightExpressionPart2 : > ... > default : > } > The result of entire expression should be boolean type. > There is shortcut for: > leftExpressionPart: intVariable > rightExpressionPart: == intLiteral > (the '==' could be ommitted.) > > COMPILATION: > Compiler could first pre-compile to appropriate if..then..else syntax. > Bytecode would not be affected, but in special cases it could be more compact, if noted pre-compilation would be replaced by sophisticated optimization. > TESTING: > Compiler byte-code results for new syntax should be same than from equivalent hand-coded legacy if..then..else syntax > . Exception: sophisticated optimization. > LIBRARY SUPPORT: No supporting libraries are needed for the feature? > REFLECTIVE APIS: There should not be any affection to reflection API. > OTHER CHANGES: No. > MIGRATION: > No refactoring is needed to stay compatible. > > COMPATIBILITY > BREAKING CHANGES: > No previously valid programs are now invalid. > ... but ATTENTION: > If proposals from some other guys regarding "Strings in switch" would be taken into JDK 7, there won't be any compatible way to implement my more general proposal in future version of JDK !!! > --> So switch .. case statement should compare for IDENTITY if not syntactically determined otherwise. > --> compare for EQUALITY would also break semantic of existing switch .. case statement. > EXISTING PROGRAMS: > Source and class files of earlier platform versions interact with the feature without any notice. > > REFERENCES > http://mail.openjdk.java.net/pipermail/coin-dev/2009-February/000001.html > http://mail.openjdk.java.net/pipermail/coin-dev/2009-March/000213.html > http://mail.openjdk.java.net/pipermail/coin-dev/2009-March/000855.html > http://forums.java.net/jive/thread.jspa?messageID=27781沅 > http://forums.java.net/jive/thread.jspa?messageID=15769㶙 > http://forums.java.net/jive/thread.jspa?messageID=27773汽 > http://forums.java.net/jive/thread.jspa?messageID=11393ⲁ > EXISTING BUGS: > http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=5012262 > URL FOR PROTOTYPE (optional): > > > > From Joe.Darcy at Sun.COM Tue May 19 15:52:57 2009 From: Joe.Darcy at Sun.COM (Joe Darcy) Date: Tue, 19 May 2009 15:52:57 -0700 Subject: PROPOSAL: Templated Construction Expressions (i.e., Expressions Embedded in Strings) In-Reply-To: <9EA33E4A-C6EB-4F54-93E5-0E06FBD1876F@sun.com> References: <3dd3f56a0903181505m517125a0w30f0aa540d1d038b@mail.gmail.com> <977c14e250a47d19b21f818f9aceb1aa.squirrel@wmail.gradsoft.ua> <7D2077BFF677D2429DDDEE095D9A48AC105DFB8D@osiris2.e-spirit.de> <9EA33E4A-C6EB-4F54-93E5-0E06FBD1876F@sun.com> Message-ID: <4A133849.4070409@sun.com> Hello. Catching up on commenting, while such a facility certainly has use cases, it feels a bit like adding a pre-processor, which Java has traditionally eschewed. -Joe On 03/30/09 05:39 PM, John Rose wrote: > On Mar 20, 2009, at 1:50 PM, John Rose wrote: > > >> I wrote the spec. draft and implementation (in antlr) for Groovy >> gstring syntax; I did the work with the intention of helping the JSR >> 241 Groovy standard. It could work in Java with adjustments, and the >> Groovy spec. is detailed enough to be a starting point. I don't >> really have time to work on it though. That's why I haven't done a >> proposal. >> >> For Java, to extend the string syntax and emphasize that a new string >> is being constructed, I recommend this: >> >> new "$foo, ${bar}s." >> > > I wrote up something more specific, for the sake of this go-around. > It is generic and pluggable enough to provide some help with XML > templating, and SQL construction. > > Enjoy! > > http://wikis.sun.com/display/mlvm/TemplatedConstructorExpressions > > (Although this document is hosted on mlvm at present, it has nothing > to do with JSR 292.) > > -- John > > P.S. For the archive, here is the original wiki source. > > h3. AUTHOR(S): > > John Rose > > h3. OVERVIEW > > String templating syntaxes are found in shell-like languages. They > allow a flexible and natural-looking mixture of constant templates > with non-constant interpolation. Adapt such a notation to Java, in a > way that provides natural-looking templating for unformatted and > formatted text, XML, SQL, and other applications involving foreign > notations andstructured text. > > h3. FEATURE SUMMARY: > > h4. *1.* simple templated strings > > The {{new}} keyword is currently used for creating objects and > arrays. This specification introduces another syntax based on the > {{new}} keyword, called the *templated construction expression*: > > {noformat} > int zip = 95120, phone = 5551212; > String s = new "zip=$(zip), phone=$(phone)."; > String s2 = "zip=" + zip + ", phone=" + phone + "."; // same code > {noformat} > > As with other languages, each unescaped dollar sign {{$}} > introduces an *interpolation*, which is an arbitrary Java expression > that contributes to the template. Everything else between the string > quotes is treated as constant text; each non-empty span of string > characters is called a *string segment*. The string segments also > contribute to the template. As with the current plus {{+}} > notation, each interpolation or string segment causes another item to > be appended. > > Every interpolation ends with zero or more expressions, called the > *interpolation arguments*. If there is exactly one interpolation > argument, we speak unambiguously of the *interpolation expression*. > (There are multi-argument examples below.) > > Such a syntax would be a merely marginal improvement over the current > plus {{+}} notation for {{StringBuilder it includes two additional > degree of freedom. They allow the programmer to specify templating > mechanisms other than {{StringBuilder}}, and to more easily control > the details of formatting for the interpolated items. > > h4. *2.* programmer-defined templating > > A templated construction expression may be qualified: > > {noformat} > int zip = 95120, phone = 5551212; > StringBuilder buf = new StringBuilder(); > buf.new "zip=$(zip), phone=$(phone)."; > String s = buf.toString(); // same result as previous example > {noformat} > > In fact, if a templated construction expression is unqualified, it is > exactly as if the compiler had supplied a default qualifier of {{new > StringBuilder()}} and appended a call to {{toString}} at the end, to > extract the resulting string. > > But, the programmer may provide a different object reference {{x}} as > a qualifier to a templated construction expression; an object used > this way is called a *template factory*. A qualified templated > construction expression is equivalent to a chain of {{append}} method > calls applied to the template factory, as detailed below. > > This allows new classes to be created which can define library- > specific semantics for templated construction. The only requirement > on template factories is that they supply the {{append}} calls implied > by the interpolations within the templates. These {{append}} calls > may be overloaded, and may take multiple arguments, or no arguments at > all. > > {noformat} > java.lang.Appendable app = ...; > app.new "subseq: $(str, beg, end)"; // append(str, beg, end) > {noformat} > > h4. *3.* generic format specifiers > > The dollar sign of an interpolation may be immediately followed by a > *format specifier*, a sequence of string characters enclosed in angle > brackets. These characters are collected into separate (presumably > short) string literal which is passed as an additional leading > argument to the method call for the interpolation; the method is named > {{format}} instead of append, and may (again) take any number of > arguments. Format specifiers may not contain unescaped right angle > brackets; otherwise they are arbitrary, and interpreted only by the > {{append}} call they are passed to. > > {noformat} > String s = new Formatter().new "zip=$<%05d>(zip), phone=$< > %d>(phone).".toString(); > {noformat} > > h4. *4.* abbreviated interpolation expressions > > For certain simple interpolation expressions, the enclosing > parentheses are optional. The expressions which can drop parentheses > are a decimal numeral, a name (qualified or simple), a name followed > by one parenthesized argument list, and a name followed by one > bracketed array index. The name must not contain any dollar signs in > its spelling. > > {noformat} > int zip = 95120, phone = 5551212; > String s = new "zip=$zip, phone=$phone."; // same code > {noformat} > > As always, any ambiguity between the interpolation expression and a > following interpolation or string segment can always be resolved by > using explicit parentheses. > > (Note: This last feature of abbreviation is troublesome to specify and > implement, but it appears to be a worthwhile creature comfort.) > > h3. MAJOR ADVANTAGE: > > The features specified here allow programmers a superior notation for > creating templated textual items. Such notations are popular and well > proven in other languages, including the shells, PHP, Perl, and > Groovy. It will reduce pressure on programmers to move to those other > languages. > > h3. MAJOR BENEFIT: > > Concise, natural templated expressions are easier to code and maintain > than equivalent nests of method calls. > > h3. MAJOR DISADVANTAGE: > > The JLS gets more complicated. > > h3. ALTERNATIVES: > > Programmers may use explicitly coded nests method calls; they are of > course more verbose. > > h3. EXAMPLES, BEFORE/AFTER: > > See above and below (in the specification) for one-line examples > demonstrating each aspect of this specification. > > h4. SIMPLE EXAMPLE: > > {noformat} > String whom = "world"; > System.out.printlin(new "Hello, $whom!"); > {noformat} > > h4. ADVANCED EXAMPLE: > > This syntax can easily support two-phase template creation, where a > template is first compiled and checked, and then later applied one or > more times. > > Let's suppose a hypothetical XML snippet compiler designed for > templated construction expressions. It might be used this way to > compile a snippet generator with optionally typed free variables > mapped to an API featuring a {{make}} method with positional arguments: > > {noformat} > XMLSnippetCompiler xmlc = ...; > xmlc.new "$1 pattern>$2"; > XMLSnippet xmls = xmlc.compile(); > System.out.println(xmls.make("raining", "walk inside", 5 /*medium > pri*/)); > System.out.println(xmls.make("fire", "run outside", 1 /*highest pri*/)); > {noformat} > > h3. DETAILS > > The sequence of string segments and interpolations of a templated > construction expression is called its body. Each string segment > begins with either the opening quote of the body, or the end of a > previous > > The templated construction expression is broken into zero or more > interpolations and zero or more (non-empty) string segments. These > are presented in order to the template factory object, as method calls > to {{appendText}}, {{append}}, or {{format}}. > > {noformat} > x.new "a"; // sugar for x.appendText("a") > x.new "$(y)"; // sugar for x.append(y) > x.new "$(y)"; // sugar for x.format("q",y) > x.new "$(y)"; // sugar for x.format("q",y) > x.new "a$(y)b"; // sugar for > x.appendText("a").append(y).appendText("b") > x.new "a$(y)b"; // sugar for > x.appendText("a").format("q",y).appendText("b") > x.new "a$(y)$(z)"; // sugar for > x.appendText("a").append(y).format("q",z) > x.new ""; // degenerate sugar for x > {noformat} > > There is no particular restriction on the syntax of interpolation > argument expressions. In particular, they can contain quoted strings > and templated construction expressions. > > {noformat} > new "Hello, $("world")."; > new "Hello, $(new "wor$("")ld")."; > {noformat} > > There is no particular restriction on the type or number of > interpolation argument expressions. Since they are sugar for > {{append}} or {{format}} method calls, they are simply required to > participate successfully in the rules for method call resolution. > > {noformat} > x.new "$()"; // sugar for x.append() > x.new "$(y)"; // sugar for x.append(y) > x.new "$(y,z)"; // sugar for x.append(y,z) > x.new "$()"; // sugar for x.format("q") > x.new "$(y)"; // sugar for x.format("q",y) > x.new "$(y,z)"; // sugar for x.format("q",z) > {noformat} > > If the templated construction expression is unqualified, it is > provided with a new {{StringBuilder}} factory object, and the > expression as a whole is closed with a {{toString}} call. > > For the sake of template factories which need to make the distinction, > string segments are appended by {{appendText}} method call, if one > exists on the factory object's static type; an error is reported if it > is not applicable to a single {{String}}. Otherwise {{append}} is > applied to the constant string segment, which will be a string literal. > > If the format specifier is completely empty, the leading argument to > format is omitted, and it is up to the programmer to specify it > explicitly in the interpolation arguments: > > {noformat} > String fmt = (zip <= 99999) ? "%05d" : "%d"; > String s = new Formatter().new "zip=$<>(fmt, zip), phone=$< > %d>(phone).".toString(); > //new Formatter().appendText > {noformat} > > Here are examples of abbreviated interpolation expressions: > > {noformat} > "$x" // same as "$(x)" > "$1" // same as "$(1)" > "$x.y" // same as "$(x.y)" > "$x.y.z" // same as "$(x.y.z)" > "$f(x)" // same as "$(f(x))" > "$x.f(y)" // same as "$(x.f(y))" > "$x[y]" // same as "$(x[y])" > "$x.y[z]" // same as "$(x.y[z])" > {noformat} > > Here are examples of abbreviated interpolation expression with > interesting right contexts: > > {noformat} > "$x." // same as "$(x)." > "$1." // same as "$(1)." > "$1.0" // same as "$(1).0" > "$x.y." // same as "$(x.y)." > "$f(x)[" // same as "$(f(x))[" > "$x[y](" // same as "$(x[y])(" > {noformat} > > Here are examples of illegal attempts at abbreviation: > {noformat} > "$$" // not same as "$($)"; must be rejected > "$$x" // not same as "$($x)"; must be rejected > "$x.$" // not same as "$(x.$)"; must be rejected > "$x["... // same as "$(x["..., a likely syntax error > "$[x]" // reserved; must be rejected > "${x}" // reserved; must be rejected > "$x{y}" // reserved; must be rejected > "$x" // reserved; must be rejected > {noformat} > > Within a string segment of a templated construction expression, the > dollar character may be escaped with a backslash, to prevent it from > introducing an interpolation. Within a format specifier of an > interpolation, the close-angle-bracket may be escaped with a > backslash, to prevent it from terminating the format specifier. An > unescaped dollar sign must introduce a well-formed interpolation. > > {noformat} > new "\$$x.priceInDollars()" > new "$<<\>>("has strange format of \"<>\"")." > new "$" // must be rejected; should be new "\$" > {noformat} > > h3. SPECIFICATION: > > The specification is complete in the running text of this document. > It will be distilled shortly. > > h3. COMPILATION: > > As this is syntactic sugar, no new mechanisms are needed. The hack of > changing {{appendText}} to {{append}} when the former is missing > requires an extra symbol table lookup. > > h3. TESTING: > > Testing will be done the usual way, via unit tests, and by early > access customers experimenting with the new facilities. > > h3. LIBRARY SUPPORT: > > There should be some retrofitting of libraries that perform append- > like operations. (This is similar retrofitting to that done when > varargs was introduced.) > > Suitable methods for {{appendText}} are added to {{StringBuilder}}, > {{StringBuffer}}, and {{Formatter}}. > > The class {{StringBuilder}}, which is privileged as the default > template factory type, is augmented with one or more {{format}} > methods that redirect to {{Formatter}}. > > {noformat} > String s = new "zip=$<%05d>zip, phone=$phone.".toString(); > {noformat} > > The class {{PrintStream}}, which already has {{format}} methods, is > also given {{appendText}} and {{append}} methods, as synonyms for > {{print}}. > > {noformat} > System.out.new "zip=$<%05d>zip, phone=$phone.".toString(); > {noformat} > > (*QUESTION:* What other classes could benefit from retrofitting?) > > h3. REFLECTIVE APIS: > > No changes. > > h3. OTHER CHANGES: > > None. > > h3. MIGRATION: > > The feature is for new code only. > > h3. COMPATIBILITY > > h4. BREAKING CHANGES: > > None. All changes are associated with previously unused syntaxes. > > h4. EXISTING PROGRAMS: > > No special interaction. > > h3. REFERENCES > > h4. EXISTING BUGS: > > None known. > > h4. URL FOR PROTOTYPE: > > None yet. > > > From Joe.Darcy at Sun.COM Tue May 19 15:59:57 2009 From: Joe.Darcy at Sun.COM (Joe Darcy) Date: Tue, 19 May 2009 15:59:57 -0700 Subject: UPDATED: Rethrows Clause In-Reply-To: <39084932-B2CC-4B91-97EA-006FE21301F0@googlemail.com> References: <39084932-B2CC-4B91-97EA-006FE21301F0@googlemail.com> Message-ID: <4A1339ED.8090309@sun.com> Hello. Hmm; this strikes me as a bit involved for the potential benefits of the feature. -Joe On 03/30/09 05:04 PM, Mark Mahieu wrote: > Forgot my JLS references in the first one... > > > > HTML version + prototype available at: > > http://slm888.com > > > > > Rethrows Clause > v0.1.1 > > > AUTHOR(S): > > Mark Mahieu > > > OVERVIEW > > FEATURE SUMMARY: Should be suitable as a summary in a language tutorial. > > A new clause on method declarations which allows exception > translations (wrapping and rethrowing as a different type) to be > cleanly defined separately from the body of the method. In many > cases, checked exception type names do not then need to be repeated > in a method's throws clause and in a throw statement in the method body. > > > MAJOR ADVANTAGE: What makes the proposal a favorable change? > > The proposal adds direct support for a common idiom in daily use by > Java programmers worldwide, allowing them to express their intentions > with greater clarity and ease. In comparison with some proposals, > this is an attempt to make dealing with checked exceptions easier by > increasing the expressiveness of exception handling code in general, > rather than by attempting to deprecate checked exceptions in favour > of unchecked exceptions. > > > MAJOR BENEFIT: Why is the platform better if the proposal is adopted? > > There is a reduction in the amount of boilerplate Java programmers > have to read and write for code dealing with checked exceptions. > Declarations specifying both thrown and rethrown (wrapped) exceptions > are kept together, aiding comprehension of the code. > > > MAJOR DISADVANTAGE: There is always a cost. > > As with any syntax sugar which enables an alternative way of > expressing an existing idiom, programmers may be tempted to use it > even when the existing idiom would be more appropriate. > > > ALTERNATIVES: Can the benefits and advantages be had some way without > a language change? > > No. > > > EXAMPLES > > SIMPLE EXAMPLE: Show the simplest possible program utilizing the new > feature. > > > Before: > > void before() throws ConfigException { > try { > Class.forName("where.is.the.Code"); > } > catch (ClassNotFoundException e) { > throw new ConfigException(e); > } > } > > After: > > void after() > catch ClassNotFoundException throw ConfigException { > > Class.forName("here.is.the.Code"); > } > > > ADVANCED EXAMPLE: Show advanced usage(s) of the feature. > > Before: > > void suspendAccount() > throws AuthorizationException, > PersistenceException { > try { > checkMyAuthoritah(); > db.update(/*...*/); > log.recordInfo(/*...*/); > } > catch (InfernalDBException e) { > throw new PersistenceException(e); > } > catch (InfernalLogException e) { > throw new RuntimeException(e); > } > } > > After: > > void suspendAccount() > throws AuthorizationException > catch InfernalDBException throw PersistenceException, > InfernalLogException throw RuntimeException { > > checkMyAuthoritah(); > db.update(/*...*/); > log.recordInfo(/*...*/); > } > > > DETAILS > > SPECIFICATION: Describe how the proposal affects the grammar, type > system, and meaning of expressions and statements in the Java > Programming Language as well as any other known impacts. > > The syntactic grammar is modified to allow an optional rethrows > clause immediately prior to a MethodBody: > > MethodDeclaratorRest: > FormalParameters {[]} [throws > QualifiedIdentifierList] ( ( [catch ExceptionTranslationList] > MethodBody ) | ; ) > > ExceptionTranslationList: > QualifiedIdentifier throw QualifiedIdentifier { , > ExceptionTranslationList } > > > > JLSv3 ?8.4.6 : A rethrows clause lists one or more exception > translations, each translation consisting of a caught type C and a > translated type T for which all of the following must hold: > * C <: java.lang.Exception > * T < java.lang.Throwable > * Neither C nor T is a type variable. > * T has an accessible constructor suitable for rethrowing a > value of type C (see below). > * T is not the same type as C. > > Any exceptions thrown by the method body which are a subtype of a > caught exception type in the rethrows clause, are rethrown as the > corresponding translated exception type. > > For a given translated type T with corresponding caught type C, if T > has an accessible constructor accepting a value of type C, then the > translation is equivalent to the following: > > catch (C e) { > throw new T(e); > } > > Otherwise it must have an accessible no argument constructor, and the > translation is equivalent to: > > catch (C e) { > throw new T().initCause(e); > } > > > A rethrows clause does not restrict which types may appear in a > throws clause for the same method. In particular, for a given caught > type C in the rethrows clause, it is permitted for some type C1 :> C > to also be listed in the throws clause. > > > JLSv3 ?8.2 : The set of exception types declared to be thrown by a > method is the union of: > * the types in the throws clause > * the translated types in the rethrow clause > * the types thrown by the translated types' selected constructors > > JLSv3 ?11.2.2 : For the purposes of exception analysis, the set of > checked exception types which may be thrown by the method's body is > the union of: > * the types in the throws clause > * the caught types in the rethrows clause > > JLSv3 ?11.2.3 : It is a compile-time error if a rethrows clause > contains a translation from a checked exception type C but there > exists no checked exception type E such that all of the following hold: > * E <: C > * The method body can throw E > * No preceding translation in the rethrow clause catches E or a > supertype of E > unless C is the class java.lang.Exception. > > JLSv3 ?13.4.21 : Changes to the rethrows clause of methods or > constructors do not break compatibility with existing binaries; these > clauses are checked only at compile time. > > > > COMPILATION: How would the feature be compiled to class files? Show > how the simple and advanced examples would be compiled. Compilation > can be expressed as at least one of a desugaring to existing source > constructs and a translation down to bytecode. If a new bytecode is > used or the semantics of an existing bytecode are changed, describe > those changes, including how they impact verification. Also discuss > any new class file attributes that are introduced. Note that there > are many downstream tools that consume class files and that they may > to be updated to support the proposal! > > A simple desugaring could consist of enclosing the method body's > statements in a try statement, with catch clauses for each translated > exception type. For example, the following method: > > Method findMethod() > catch ClassNotFoundException throw ConfigException, > NoSuchMethodException throw ConfigException { > > Class c = Class.forName("some.Thing"); > return c.getDeclaredMethod("execute", null); > } > > would be desugared to: > > Method findMethod() > throws ConfigException { > try { > Class c = Class.forName("some.Thing"); > return c.getDeclaredMethod("execute", null); > } > catch (ClassNotFoundException e) { > throw new ConfigException(e); > } > catch (MethodNotFoundException e) { > throw new ConfigException(e); > } > } > > No changes to the classfile format are required. > > > TESTING: How can the feature be tested? > > An initial set of jtreg tests is included in the prototype. > > > LIBRARY SUPPORT: Are any supporting libraries needed for the feature? > > No > > > REFLECTIVE APIS: Do any of the various and sundry reflection APIs > need to be updated? This list of reflective APIs includes but is not > limited to core reflection (java.lang.Class and java.lang.reflect.*), > javax.lang.model.*, the doclet API, and JPDA. > > com.sun.source.tree.MethodTree would require updates to access the > rethrows clause's caught and translated types. > > > OTHER CHANGES: Do any other parts of the platform need be updated > too? Possibilities include but are not limited to JNI, serialization, > and output of the javadoc tool. > > No > > > MIGRATION: Sketch how a code base could be converted, manually or > automatically, to use the new feature. > > Catch clauses which simply wrap and rethrow an exception as another > exception type not caught in an enclosing scope, can be trivially > replaced with a rethrows clause, either manually or automatically. > > It should be possible for tools to offer bidirectional conversions > such that an exception translation may be moved back into the method > body if it is subsequently decided that additional logic is required. > > > COMPATIBILITY > > BREAKING CHANGES: Are any previously valid programs now invalid? If > so, list one. > > No > > > EXISTING PROGRAMS: How do source and class files of earlier platform > versions interact with the feature? Can any new overloadings occur? > Can any new overriding occur? > > The semantics of existing class files and legal source files are > unchanged by this feature. > > > REFERENCES > > EXISTING BUGS: Please include a list of any existing Sun bug ids > related to this proposal. > > http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6534270 > (similar, but emphasizes unchecked exceptions) > > > URL FOR PROTOTYPE (optional): > > http://slm888.com/javac > > > From markmahieu at googlemail.com Tue May 19 17:22:10 2009 From: markmahieu at googlemail.com (Mark Mahieu) Date: Wed, 20 May 2009 01:22:10 +0100 Subject: UPDATED: Rethrows Clause In-Reply-To: <4A1339ED.8090309@sun.com> References: <39084932-B2CC-4B91-97EA-006FE21301F0@googlemail.com> <4A1339ED.8090309@sun.com> Message-ID: Yeah, I suppose I did make it rather more complicated than it needed to be. Thanks for the feedback. Mark On 19 May 2009, at 23:59, Joe Darcy wrote: > Hello. > > Hmm; this strikes me as a bit involved for the potential benefits > of the feature. > > -Joe > > On 03/30/09 05:04 PM, Mark Mahieu wrote: >> Forgot my JLS references in the first one... >> >> >> >> HTML version + prototype available at: >> >> http://slm888.com >> >> >> >> >> Rethrows Clause >> v0.1.1 >> >> >> AUTHOR(S): >> >> Mark Mahieu >> >> >> OVERVIEW >> >> FEATURE SUMMARY: Should be suitable as a summary in a language >> tutorial. >> >> A new clause on method declarations which allows exception >> translations (wrapping and rethrowing as a different type) to be >> cleanly defined separately from the body of the method. In many >> cases, checked exception type names do not then need to be >> repeated in a method's throws clause and in a throw statement in >> the method body. >> >> >> MAJOR ADVANTAGE: What makes the proposal a favorable change? >> >> The proposal adds direct support for a common idiom in daily use >> by Java programmers worldwide, allowing them to express their >> intentions with greater clarity and ease. In comparison with >> some proposals, this is an attempt to make dealing with checked >> exceptions easier by increasing the expressiveness of exception >> handling code in general, rather than by attempting to deprecate >> checked exceptions in favour of unchecked exceptions. >> >> >> MAJOR BENEFIT: Why is the platform better if the proposal is adopted? >> >> There is a reduction in the amount of boilerplate Java >> programmers have to read and write for code dealing with checked >> exceptions. Declarations specifying both thrown and rethrown >> (wrapped) exceptions are kept together, aiding comprehension of >> the code. >> >> >> MAJOR DISADVANTAGE: There is always a cost. >> >> As with any syntax sugar which enables an alternative way of >> expressing an existing idiom, programmers may be tempted to use >> it even when the existing idiom would be more appropriate. >> >> >> ALTERNATIVES: Can the benefits and advantages be had some way >> without a language change? >> >> No. >> >> >> EXAMPLES >> >> SIMPLE EXAMPLE: Show the simplest possible program utilizing the >> new feature. >> >> >> Before: >> >> void before() throws ConfigException { >> try { >> Class.forName("where.is.the.Code"); >> } >> catch (ClassNotFoundException e) { >> throw new ConfigException(e); >> } >> } >> >> After: >> >> void after() >> catch ClassNotFoundException throw ConfigException { >> >> Class.forName("here.is.the.Code"); >> } >> >> >> ADVANCED EXAMPLE: Show advanced usage(s) of the feature. >> >> Before: >> >> void suspendAccount() >> throws AuthorizationException, >> PersistenceException { >> try { >> checkMyAuthoritah(); >> db.update(/*...*/); >> log.recordInfo(/*...*/); >> } >> catch (InfernalDBException e) { >> throw new PersistenceException(e); >> } >> catch (InfernalLogException e) { >> throw new RuntimeException(e); >> } >> } >> >> After: >> >> void suspendAccount() >> throws AuthorizationException >> catch InfernalDBException throw PersistenceException, >> InfernalLogException throw RuntimeException { >> >> checkMyAuthoritah(); >> db.update(/*...*/); >> log.recordInfo(/*...*/); >> } >> >> >> DETAILS >> >> SPECIFICATION: Describe how the proposal affects the grammar, >> type system, and meaning of expressions and statements in the >> Java Programming Language as well as any other known impacts. >> >> The syntactic grammar is modified to allow an optional rethrows >> clause immediately prior to a MethodBody: >> >> MethodDeclaratorRest: >> FormalParameters {[]} [throws >> QualifiedIdentifierList] ( ( [catch ExceptionTranslationList] >> MethodBody ) | ; ) >> >> ExceptionTranslationList: >> QualifiedIdentifier throw QualifiedIdentifier >> { , ExceptionTranslationList } >> >> >> >> JLSv3 ?8.4.6 : A rethrows clause lists one or more exception >> translations, each translation consisting of a caught type C and >> a translated type T for which all of the following must hold: >> * C <: java.lang.Exception >> * T < java.lang.Throwable >> * Neither C nor T is a type variable. >> * T has an accessible constructor suitable for rethrowing a >> value of type C (see below). >> * T is not the same type as C. >> >> Any exceptions thrown by the method body which are a subtype of a >> caught exception type in the rethrows clause, are rethrown as the >> corresponding translated exception type. >> >> For a given translated type T with corresponding caught type C, if >> T has an accessible constructor accepting a value of type C, then >> the translation is equivalent to the following: >> >> catch (C e) { >> throw new T(e); >> } >> >> Otherwise it must have an accessible no argument constructor, and >> the translation is equivalent to: >> >> catch (C e) { >> throw new T().initCause(e); >> } >> >> >> A rethrows clause does not restrict which types may appear in a >> throws clause for the same method. In particular, for a given >> caught type C in the rethrows clause, it is permitted for some >> type C1 :> C to also be listed in the throws clause. >> >> >> JLSv3 ?8.2 : The set of exception types declared to be thrown by >> a method is the union of: >> * the types in the throws clause >> * the translated types in the rethrow clause >> * the types thrown by the translated types' selected >> constructors >> >> JLSv3 ?11.2.2 : For the purposes of exception analysis, the set >> of checked exception types which may be thrown by the method's >> body is the union of: >> * the types in the throws clause >> * the caught types in the rethrows clause >> >> JLSv3 ?11.2.3 : It is a compile-time error if a rethrows clause >> contains a translation from a checked exception type C but there >> exists no checked exception type E such that all of the following >> hold: >> * E <: C >> * The method body can throw E >> * No preceding translation in the rethrow clause catches E or >> a supertype of E >> unless C is the class java.lang.Exception. >> >> JLSv3 ?13.4.21 : Changes to the rethrows clause of methods or >> constructors do not break compatibility with existing binaries; >> these clauses are checked only at compile time. >> >> >> >> COMPILATION: How would the feature be compiled to class files? >> Show how the simple and advanced examples would be compiled. >> Compilation can be expressed as at least one of a desugaring to >> existing source constructs and a translation down to bytecode. If >> a new bytecode is used or the semantics of an existing bytecode >> are changed, describe those changes, including how they impact >> verification. Also discuss any new class file attributes that are >> introduced. Note that there are many downstream tools that >> consume class files and that they may to be updated to support >> the proposal! >> >> A simple desugaring could consist of enclosing the method body's >> statements in a try statement, with catch clauses for each >> translated exception type. For example, the following method: >> >> Method findMethod() >> catch ClassNotFoundException throw ConfigException, >> NoSuchMethodException throw ConfigException { >> >> Class c = Class.forName("some.Thing"); >> return c.getDeclaredMethod("execute", null); >> } >> >> would be desugared to: >> >> Method findMethod() >> throws ConfigException { >> try { >> Class c = Class.forName("some.Thing"); >> return c.getDeclaredMethod("execute", null); >> } >> catch (ClassNotFoundException e) { >> throw new ConfigException(e); >> } >> catch (MethodNotFoundException e) { >> throw new ConfigException(e); >> } >> } >> >> No changes to the classfile format are required. >> >> >> TESTING: How can the feature be tested? >> >> An initial set of jtreg tests is included in the prototype. >> >> >> LIBRARY SUPPORT: Are any supporting libraries needed for the feature? >> >> No >> >> >> REFLECTIVE APIS: Do any of the various and sundry reflection APIs >> need to be updated? This list of reflective APIs includes but is >> not limited to core reflection (java.lang.Class and >> java.lang.reflect.*), javax.lang.model.*, the doclet API, and JPDA. >> >> com.sun.source.tree.MethodTree would require updates to access >> the rethrows clause's caught and translated types. >> >> >> OTHER CHANGES: Do any other parts of the platform need be updated >> too? Possibilities include but are not limited to JNI, >> serialization, and output of the javadoc tool. >> >> No >> >> >> MIGRATION: Sketch how a code base could be converted, manually or >> automatically, to use the new feature. >> >> Catch clauses which simply wrap and rethrow an exception as >> another exception type not caught in an enclosing scope, can be >> trivially replaced with a rethrows clause, either manually or >> automatically. >> >> It should be possible for tools to offer bidirectional >> conversions such that an exception translation may be moved back >> into the method body if it is subsequently decided that >> additional logic is required. >> >> >> COMPATIBILITY >> >> BREAKING CHANGES: Are any previously valid programs now invalid? >> If so, list one. >> >> No >> >> >> EXISTING PROGRAMS: How do source and class files of earlier >> platform versions interact with the feature? Can any new >> overloadings occur? Can any new overriding occur? >> >> The semantics of existing class files and legal source files are >> unchanged by this feature. >> >> >> REFERENCES >> >> EXISTING BUGS: Please include a list of any existing Sun bug ids >> related to this proposal. >> >> http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6534270 >> (similar, but emphasizes unchecked exceptions) >> >> >> URL FOR PROTOTYPE (optional): >> >> http://slm888.com/javac >> >> >> > From Joe.Darcy at Sun.COM Tue May 19 17:57:15 2009 From: Joe.Darcy at Sun.COM (Joe Darcy) Date: Tue, 19 May 2009 17:57:15 -0700 Subject: Proposal: Improved declaration using final keyword of internal method variables and for-loop statement In-Reply-To: <795553.78251.qm@web50611.mail.re2.yahoo.com> References: <795553.78251.qm@web50611.mail.re2.yahoo.com> Message-ID: <4A13556B.3010408@sun.com> Hello. I don't find this proposal very compelling. Slight performance differences in the client, or server, compiler can change in update releases. Regards, -Joe On 03/31/09 02:04 AM, Andrej Navodnik wrote: > Hi Project Coin members, > > here is my little proposal for improved declaration using final keyword > of internal method variables and for-loop statement. > > Is it too late? Maybe not. At the time I'm sending this e-mail, in Honolulu, Hawaii, it is still Monday, 30 March 2009. > > Kind regards, > Andrei > > ----------------------------------------------------------------------- > > PROJECT COIN SMALL LANGUAGE CHANGE PROPOSAL FORM v1.0 > > TITLE: > Improved declaration using final keyword of > internal method variables and for-loop statement > > AUTHOR(S): > Andrei Navodnik (andrejnavodnik at yahoo.com) > > > OVERVIEW > ======== > > FEATURE SUMMARY: > Allow declaration of mixed final and non-final internal method > variables in one statement and enable final keyword in for-loop > declaration for variables other than index variable. > > MAJOR ADVANTAGE: > Suppose that the developer wants to have as much variables defined > as final then if this feature were accepted in the language one major > advantage would be to allow shorter syntax of internal method variables. > Mixing of final and non-final variables in one declaration statement > would be allowed which is prohibited with the current state of the > compiler. The compiler either allows all variables to be final or > all variables to be non-final. > > As far as for-loop declaration is concerned, this feature would allow > syntax that is more compact (no pollution of scope outside of the > for-loop) and "safer" (the size of the list would be assigned to final > variable and this value can not be changed inside of the loop). > > MAJOR BENEFIT: > Suppose that the majority of code is written as > > for (int i = 0; i < values.size(); i++ ) { > // ... > } > > then this feature would allow easier refactoring to the optimized > style of for-loops > > for (int i = 0, final n = values.size(); i < n; i++) { > // ... > } > > because variable n can not be already defined in the scope either > outside or inside of the for-loop. Any such violation would make > program uncompilable. According to my benchmarks the later style of > for-loops is also slightly faster in client VM. > > MAJOR DISADVANTAGE: > If the feature were accepted then the major disadvantage in my opinion > would be slightly more complex grammar which would have to take care > of the compatibility with the existing programs. > > ALTERNATIVES: > One of the alternatives to the proposed syntax (see simple example > bellow) would be to declare internal method variables in separate > statements, for example one statement for all non-final variables and > one statement for all final variables. Someone might even argue that > syntax where each variable is defined on separate statements is better > comparing to the syntax where all variables are defined in one > statement. > > int a, c = 1; > final b, d = 4; > > But, if developer's strategy is to define all read-only variables as > final then the alternatives to the proposed syntax for the for-loop > are not very nice. One is to declare variable of the size of the list > outside of the for-loop declaration, for example > > final n = values.size(); > for (int i = 0; i < n; i++) { > // ... > } > > or to declare index variable outside of the for-loop. > > int i = 0; > for (final int n = values.size(); i < n; i++ ) { > // ... > } > > > EXAMPLES > ======== > > SIMPLE EXAMPLE: > If the proposal were accepted then the code below should be valid. > Please, compare the proposed syntax with the alternatives presented > above. > > int a, final b, c = 1, final d = 4; > for (int i = 0, final n = values.size(); i < n; i++) { > // ... > } > > ADVANCED EXAMPLE: > No advanced example. > > > DETAILS > ======= > > SPECIFICATION: > To support mixed final and non-final internal method variables the > grammar should be changed as follows: > > LocalVariableDeclarationStatement: > AllVariablesFinalDeclarationStatement > SomeVariablesFinalDeclarationStatement > > AllVariablesFinalDeclarationStatement: > final Type VariableDeclarators ; > > SomeVariablesFinalDeclarationStatement: > Type SomeVariablesFinalDeclarators ; > > SomeVariablesFinalDeclarators: > VariableDeclarator { , VariableMaybeFinalDeclarator } > > VariableMaybeFinalDeclarator: > [final] Identifier SomeVariablesFinalDeclaratorsRest > > SomeVariablesFinalDeclaratorsRest: > SomeVariablesFinalDeclaratorsRest { , VariableMaybeFinalDeclarator } > > To better support final keyword in the for-loop declaration the grammar > should be changed as follows: > > ForVarControl: > AllVariablesFinalForVarControl > SomeVariablesFinalForVarControl > > AllVariablesFinalForVarControl: > final [Annotations] Type Identifier ForVarControlRest > > SomeVariablesFinalForVarControl: > [Annotations] Type Identifier SomeVariablesFinalForVarControlRest > > SomeVariablesFinalForVarControlRest: > SomeVariablesFinalDeclaratorsRest; [Expression] ; [ForUpdate] > : Expression > > TESTING: > No specific testing is needed to test this feature. > > LIBRARY SUPPORT: > The proposed language feature needs no additional library support. > > REFLECTIVE APIS: > The feature does not affect reflective API's. > > OTHER CHANGES: > The feature does not need other changes. > > MIGRATION: > Existing programs should work without any change. > > COMPATIBILITY: > All existing programs are compatible. > > BREAKING CHANGES: > None. > > EXISTING PROGRAMS: > There should be no impact on existing programs. > > > REFERENCES > ========== > > EXISTING BUGS: > RFE has been already filed for this feature, please check internal > review ID 1200191. > > URL FOR PROTOTYPE: > There is no prototype for this feature. > > > > > > > From Joe.Darcy at Sun.COM Tue May 19 18:05:36 2009 From: Joe.Darcy at Sun.COM (Joe Darcy) Date: Tue, 19 May 2009 18:05:36 -0700 Subject: PROPOSAL: Byte and Short Integer Literal Suffixes In-Reply-To: <49C9F27F.7090006@paradise.net.nz> References: <49C9F27F.7090006@paradise.net.nz> Message-ID: <4A135760.20400@sun.com> Hi Bruce. Between your two proposals "Byte and Short Integer Literal Suffixes" and "Auto Typing Hexadecimal and Binary Integer Literals," the suffixes are more in keeping with the existing flavor of Java literals. I'm more inclined for support to be added for narrow (or auto) literals for bytes rather than shorts since my impression is short is rarely used and those annoying casts of values 0xF1 to byte are much more common. -Joe On 03/25/09 01:59 AM, Bruce Chapman wrote: > TITLE: Byte and Short Integer Literal Suffixes > > latest html version at > http://docs.google.com/Doc?docid=dcvp3mkv_0fvz5gx7b&hl > > AUTHOR(S): Bruce Chapman > > OVERVIEW > > Problems occur when trying to create literal byte values for known bit > patterns because byte is signed therefore 0x80 thru 0xFF are not valid > byte values. > > Working with bytes (binary files, network communications) can be > simplified by allowing byte size integer literals (and short for > consistency). Specifically allow hexadecimal byte literals, others for > completeness. > > > > FEATURE SUMMARY: > > Allow byte and short integer literals by introducing 4 new integer type > suffixes 'y' & 'Y' for bytes, 's' & 'S' for shorts. > > > MAJOR ADVANTAGE: > > Somewhat reduces the pain resulting from byte being a signed type, > removes the need to downcast integer literals to byte or short. > > > MAJOR BENEFIT: Why is the platform better if the proposal is adopted? > > cruddy code like > > byte[] stuff = { 0x00, 0x7F, (byte)0x80, (byte)0xFF}; > > can be recoded as > > > > byte[] ufum7 = { 0x00y, 0x7Fy, 0x80y, 0xFFy }; > > MAJOR DISADVANTAGE: > > Some familiarisation curve required before the syntax stops looking > slightly odd. > > Would prefer to but cannot use 'B' as Integral type suffix because it is > a hexadecimal digit, 'Y' can be used but is slightly esoteric, but > probably no more so than 'X' for hexadecimal prefix. > > > ALTERNATIVES: > > An alternative language change would be to have hexadecimal integer > literals that are typed according to the number of digits. > > EXAMPLES > Show us the code! > SIMPLE EXAMPLE: > > > byte[] utf8bom7 = { 0xEFy, 0xBBy, 0xBFy }; > > > ADVANCED EXAMPLE: > > > byte[] buffer = ...; > > if(buffer[i] == 0xBBy) { // never equal with 0xBB > > ... > > } > > DETAILS > SPECIFICATION: > > > "3.10.1 Integer literals" is amended as follows - additions in bold. > > > IntegerTypeSuffix: one of > l L y Y s S > > > An integer literal is of type long if it is suffixed with an ASCII > letter L or l (ell), of type short if it is suffixed with an ASCII > letter S or s and of type byte if it is suffixed with an ASCII letter Y > or y; otherwise it is of type int (?4.2.1). For long literals the > suffix L is preferred, because the letter l (ell) is often hard to > distinguish from the digit 1 (one). > > > > and at the end of 3.10.1 add > > A compile-time error occurs if a decimal literal of type short is > larger than 32767 (215), or if the literal 32767 appears anywhere other > than as the operand of the unary - operator, or if a hexadecimal or > octal short literal does not fit in 16 bits. > > A compile-time error occurs if a decimal literal of type byte is > larger than 128 (27), or if the literal 128 appears anywhere other than > as the operand of the unary - operator, or if a hexadecimal or octal > byte literal does not fit in 8 bits. > > > COMPILATION: How would the feature be compiled to class files? Show how > the simple and advanced examples would be compiled. Compilation can be > expressed as at least one of a desugaring to existing source constructs > and a translation down to bytecode. If a new bytecode is used or the > semantics of an existing bytecode are changed, describe those changes, > including how they impact verification. Also discuss any new class file > attributes that are introduced. Note that there are many downstream > tools that consume class files and that they may to be updated to > support the proposal! > > TESTING: How can the feature be tested? > > LIBRARY SUPPORT: > > No library support required. > > REFLECTIVE APIS: Do any of the various and sundry reflection APIs need > to be updated? This list of reflective APIs includes but is not limited > to core reflection (java.lang.Class and java.lang.reflect.*), > javax.lang.model.*, the doclet API, and JPDA. > > OTHER CHANGES: Do any other parts of the platform need be updated too? > Possibilities include but are not limited to JNI, serialization, and > output of the javadoc tool. > > MIGRATION: Sketch how a code base could be converted, manually or > automatically, to use the new feature. > > COMPATIBILITY > BREAKING CHANGES: Are any previously valid programs now invalid? If so, > list one. > > EXISTING PROGRAMS: How do source and class files of earlier platform > versions interact with the feature? Can any new overloadings occur? Can > any new overriding occur? > > REFERENCES > EXISTING BUGS: Please include a list of any existing Sun bug ids related > to this proposal. > > URL FOR PROTOTYPE (optional): > > > From brucechapman at paradise.net.nz Tue May 19 21:04:13 2009 From: brucechapman at paradise.net.nz (brucechapman at paradise.net.nz) Date: Wed, 20 May 2009 16:04:13 +1200 (NZST) Subject: PROPOSAL: Byte and Short Integer Literal Suffixes In-Reply-To: <4A135760.20400@sun.com> References: <49C9F27F.7090006@paradise.net.nz> <4A135760.20400@sun.com> Message-ID: <1242792253.4a13813d98083@www.paradise.net.nz> Quoting Joe Darcy : > Hi Bruce. > > Between your two proposals "Byte and Short Integer Literal Suffixes" and > > "Auto Typing Hexadecimal and Binary Integer Literals," the suffixes are > > more in keeping with the existing flavor of Java literals. I'm more > inclined for support to be added for narrow (or auto) literals for bytes > > rather than shorts since my impression is short is rarely used and those > > annoying casts of values 0xF1 to byte are much more common. short was added for completeness of both proposals. I wouldn't see any practical issues if short (and char) were removed from either of these proposals. So the auto form would just be byte, int and maybe long. The suffix form if that route was chosen would be just to add byte. My personal preference would be for the auto form, unless someone can find a nice way to combine the advantages of both and avoid the missing bits from each (auto form doesn't cover decimal and octal). Bruce > > -Joe > > > On 03/25/09 01:59 AM, Bruce Chapman wrote: > > TITLE: Byte and Short Integer Literal Suffixes > > > > latest html version at > > http://docs.google.com/Doc?docid=dcvp3mkv_0fvz5gx7b&hl > > > > AUTHOR(S): Bruce Chapman > > > > OVERVIEW > > > > Problems occur when trying to create literal byte values for known > bit > > patterns because byte is signed therefore 0x80 thru 0xFF are not > valid > > byte values. > > > > Working with bytes (binary files, network communications) can be > > simplified by allowing byte size integer literals (and short for > > consistency). Specifically allow hexadecimal byte literals, others > for > > completeness. > > > > > > > > FEATURE SUMMARY: > > > > Allow byte and short integer literals by introducing 4 new integer > type > > suffixes 'y' & 'Y' for bytes, 's' & 'S' for shorts. > > > > > > MAJOR ADVANTAGE: > > > > Somewhat reduces the pain resulting from byte being a signed type, > > removes the need to downcast integer literals to byte or short. > > > > > > MAJOR BENEFIT: Why is the platform better if the proposal is adopted? > > > > cruddy code like > > > > byte[] stuff = { 0x00, 0x7F, (byte)0x80, (byte)0xFF}; > > > > can be recoded as > > > > > > > > byte[] ufum7 = { 0x00y, 0x7Fy, 0x80y, 0xFFy }; > > > > MAJOR DISADVANTAGE: > > > > Some familiarisation curve required before the syntax stops looking > > slightly odd. > > > > Would prefer to but cannot use 'B' as Integral type suffix because it > is > > a hexadecimal digit, 'Y' can be used but is slightly esoteric, but > > probably no more so than 'X' for hexadecimal prefix. > > > > > > ALTERNATIVES: > > > > An alternative language change would be to have hexadecimal integer > > literals that are typed according to the number of digits. > > > > EXAMPLES > > Show us the code! > > SIMPLE EXAMPLE: > > > > > > byte[] utf8bom7 = { 0xEFy, 0xBBy, 0xBFy }; > > > > > > ADVANCED EXAMPLE: > > > > > > byte[] buffer = ...; > > > > if(buffer[i] == 0xBBy) { // never equal with 0xBB > > > > ... > > > > } > > > > DETAILS > > SPECIFICATION: > > > > > > "3.10.1 Integer literals" is amended as follows - additions in bold. > > > > > > IntegerTypeSuffix: one of > > l L y Y s S > > > > > > An integer literal is of type long if it is suffixed with an ASCII > > letter L or l (ell), of type short if it is suffixed with an ASCII > > letter S or s and of type byte if it is suffixed with an ASCII letter > Y > > or y; otherwise it is of type int (?4.2.1). For long literals the > > suffix L is preferred, because the letter l (ell) is often hard to > > distinguish from the digit 1 (one). > > > > > > > > and at the end of 3.10.1 add > > > > A compile-time error occurs if a decimal literal of type short is > > larger than 32767 (215), or if the literal 32767 appears anywhere > other > > than as the operand of the unary - operator, or if a hexadecimal or > > octal short literal does not fit in 16 bits. > > > > A compile-time error occurs if a decimal literal of type byte is > > larger than 128 (27), or if the literal 128 appears anywhere other > than > > as the operand of the unary - operator, or if a hexadecimal or octal > > byte literal does not fit in 8 bits. > > > > > > COMPILATION: How would the feature be compiled to class files? Show > how > > the simple and advanced examples would be compiled. Compilation can > be > > expressed as at least one of a desugaring to existing source > constructs > > and a translation down to bytecode. If a new bytecode is used or the > > semantics of an existing bytecode are changed, describe those > changes, > > including how they impact verification. Also discuss any new class > file > > attributes that are introduced. Note that there are many downstream > > tools that consume class files and that they may to be updated to > > support the proposal! > > > > TESTING: How can the feature be tested? > > > > LIBRARY SUPPORT: > > > > No library support required. > > > > REFLECTIVE APIS: Do any of the various and sundry reflection APIs > need > > to be updated? This list of reflective APIs includes but is not > limited > > to core reflection (java.lang.Class and java.lang.reflect.*), > > javax.lang.model.*, the doclet API, and JPDA. > > > > OTHER CHANGES: Do any other parts of the platform need be updated > too? > > Possibilities include but are not limited to JNI, serialization, and > > output of the javadoc tool. > > > > MIGRATION: Sketch how a code base could be converted, manually or > > automatically, to use the new feature. > > > > COMPATIBILITY > > BREAKING CHANGES: Are any previously valid programs now invalid? If > so, > > list one. > > > > EXISTING PROGRAMS: How do source and class files of earlier platform > > versions interact with the feature? Can any new overloadings occur? > Can > > any new overriding occur? > > > > REFERENCES > > EXISTING BUGS: Please include a list of any existing Sun bug ids > related > > to this proposal. > > > > URL FOR PROTOTYPE (optional): > > > > > > > From reinier at zwitserloot.com Tue May 19 23:46:26 2009 From: reinier at zwitserloot.com (Reinier Zwitserloot) Date: Wed, 20 May 2009 08:46:26 +0200 Subject: UPDATED: Rethrows Clause In-Reply-To: References: <39084932-B2CC-4B91-97EA-006FE21301F0@googlemail.com> <4A1339ED.8090309@sun.com> Message-ID: <68BF955A-9796-44F7-9E97-94BBB43ADCC5@zwitserloot.com> Here's a trivially simple change to implement, though it has some far reaching repercussions for java as a whole: change the 'rethrows' clause to an ignores clause: Any checked exception in the ignores list may be thrown from the method body, but is NOT part of the method's checked exception list. It is hence also not part of the signature, just like sticking a 'synchronized' keyword on a method isn't part of its signature, but an implementation detail. example: Runnable r = new Runnable() { public void run() ignores UnsupportedEncodingException { String x = new String(inBytes, "UTF-8"); } }; This sounds like blowing up the entire point of checked exceptions, but with java moving towards more interoperation with other JVM based languages, which almost always throw checked exceptions without actually declaring them (Jython, JRuby, Scala -- I can't think of a single one other than java itself that has the notion of checked exceptions in the first place). If the whole 'java is like the assembler of the JVM' story is going to hold water, something like this is needed. For some further support: I doubt anyone seriously holds the position that java's checked exception experiment was an unmitigated success. There are pain points, here and there. The above example in fact includes two of them: The fact that runnable throws no checked exceptions is clearly a mistake in regards to threading, because Thread objects clearly should handle ANY exception falling out of its run() method (and it in fact does, via the unchecked exception handler mechanism), and there's a general mismatch between main(), which MAY throw exceptions, and run(), which may not, even though they are both 'thread start points'. Another mistake is UnsupportedEncodingExceptions, a checked exception, resulting from a call to converting byte arrays to strings using an encoding that is guaranteed by the JVM using a string literal, such as "UTF-8". The appropriate exception would be UnsupportedEncodingError("This JVM is broken. Charset UTF-8 missing. Reinstall it") - which is unchecked. In other words, while I'm not ready to write off checked exceptions as a whole, I am more than ready to acknowledge that the programmer more often knows better than the compiler, compared to how often the programmer, in laziness or inexperience, abuses this freedom. Especially considering that, on the JVM, you really DONT get checked exceptions guarantees; any class compiled by anything other than javac is free to throw checked exceptions without declaring them, and even in javac you can technically do this using 'sneaky throw' libraries, which use various workarounds, one of which will NEVER go away*. We're not losing much here, in other words. In fact, the way javac works, inexperienced java programmers may erroneously assume that checked exceptions couldn't possibly happen unless the checked exception is declared. This is not the case. *) The one that will never go away is java.lang.Class.newInstance(), which is functionally defined to sneakily throw on any exceptions thrown by the constructor, checked or not, and does NOT wrap them up into a wrapper the way java.lang.reflect.Method.invoke() does. This cannot change without breaking backwards compatibility. Another one that will never go away is constructing a class on the fly that sneaky throws, loading it with ClassLoader's load from bytes mechanism, and executing it. Attempting to solve this issue with a library requires rather a lot of ugly boilerplate: import static Utils.sneakyThrow; Runnable r = new Runnable() { public void run() { String x; try { x = new String(inBytes, "UTF-8"); } catch ( UnsupportedEncodingException e ) { sneakyThrow(e); } } }; NB: For sanity purposes, the restriction on javac that the try block MUST contain at least 1 statement that could throw a checked exception type that is listed on one of the accompanying catch blocks (other than Exception, which you can always catch), should go away; this has already been proposed before, and in fact is a backwards compatibility painpoint for the coin proposal that allows you to rethrow a final Exception as if its type is the intersection of all checked types thrown by the statements in the try body. --Reinier Zwitserloot Like it? Tip it! http://tipit.to On May 20, 2009, at 02:22, Mark Mahieu wrote: > Yeah, I suppose I did make it rather more complicated than it needed > to be. > > Thanks for the feedback. > > Mark > > > On 19 May 2009, at 23:59, Joe Darcy wrote: > >> Hello. >> >> Hmm; this strikes me as a bit involved for the potential benefits >> of the feature. >> >> -Joe >> >> On 03/30/09 05:04 PM, Mark Mahieu wrote: >>> Forgot my JLS references in the first one... >>> >>> >>> >>> HTML version + prototype available at: >>> >>> http://slm888.com >>> >>> >>> >>> >>> Rethrows Clause >>> v0.1.1 >>> >>> >>> AUTHOR(S): >>> >>> Mark Mahieu >>> >>> >>> OVERVIEW >>> >>> FEATURE SUMMARY: Should be suitable as a summary in a language >>> tutorial. >>> >>> A new clause on method declarations which allows exception >>> translations (wrapping and rethrowing as a different type) to be >>> cleanly defined separately from the body of the method. In many >>> cases, checked exception type names do not then need to be >>> repeated in a method's throws clause and in a throw statement in >>> the method body. >>> >>> >>> MAJOR ADVANTAGE: What makes the proposal a favorable change? >>> >>> The proposal adds direct support for a common idiom in daily use >>> by Java programmers worldwide, allowing them to express their >>> intentions with greater clarity and ease. In comparison with >>> some proposals, this is an attempt to make dealing with checked >>> exceptions easier by increasing the expressiveness of exception >>> handling code in general, rather than by attempting to deprecate >>> checked exceptions in favour of unchecked exceptions. >>> >>> >>> MAJOR BENEFIT: Why is the platform better if the proposal is >>> adopted? >>> >>> There is a reduction in the amount of boilerplate Java >>> programmers have to read and write for code dealing with checked >>> exceptions. Declarations specifying both thrown and rethrown >>> (wrapped) exceptions are kept together, aiding comprehension of >>> the code. >>> >>> >>> MAJOR DISADVANTAGE: There is always a cost. >>> >>> As with any syntax sugar which enables an alternative way of >>> expressing an existing idiom, programmers may be tempted to use >>> it even when the existing idiom would be more appropriate. >>> >>> >>> ALTERNATIVES: Can the benefits and advantages be had some way >>> without a language change? >>> >>> No. >>> >>> >>> EXAMPLES >>> >>> SIMPLE EXAMPLE: Show the simplest possible program utilizing the >>> new feature. >>> >>> >>> Before: >>> >>> void before() throws ConfigException { >>> try { >>> Class.forName("where.is.the.Code"); >>> } >>> catch (ClassNotFoundException e) { >>> throw new ConfigException(e); >>> } >>> } >>> >>> After: >>> >>> void after() >>> catch ClassNotFoundException throw ConfigException { >>> >>> Class.forName("here.is.the.Code"); >>> } >>> >>> >>> ADVANCED EXAMPLE: Show advanced usage(s) of the feature. >>> >>> Before: >>> >>> void suspendAccount() >>> throws AuthorizationException, >>> PersistenceException { >>> try { >>> checkMyAuthoritah(); >>> db.update(/*...*/); >>> log.recordInfo(/*...*/); >>> } >>> catch (InfernalDBException e) { >>> throw new PersistenceException(e); >>> } >>> catch (InfernalLogException e) { >>> throw new RuntimeException(e); >>> } >>> } >>> >>> After: >>> >>> void suspendAccount() >>> throws AuthorizationException >>> catch InfernalDBException throw PersistenceException, >>> InfernalLogException throw RuntimeException { >>> >>> checkMyAuthoritah(); >>> db.update(/*...*/); >>> log.recordInfo(/*...*/); >>> } >>> >>> >>> DETAILS >>> >>> SPECIFICATION: Describe how the proposal affects the grammar, >>> type system, and meaning of expressions and statements in the >>> Java Programming Language as well as any other known impacts. >>> >>> The syntactic grammar is modified to allow an optional rethrows >>> clause immediately prior to a MethodBody: >>> >>> MethodDeclaratorRest: >>> FormalParameters {[]} [throws >>> QualifiedIdentifierList] ( ( [catch ExceptionTranslationList] >>> MethodBody ) | ; ) >>> >>> ExceptionTranslationList: >>> QualifiedIdentifier throw QualifiedIdentifier >>> { , ExceptionTranslationList } >>> >>> >>> >>> JLSv3 ?8.4.6 : A rethrows clause lists one or more exception >>> translations, each translation consisting of a caught type C and >>> a translated type T for which all of the following must hold: >>> * C <: java.lang.Exception >>> * T < java.lang.Throwable >>> * Neither C nor T is a type variable. >>> * T has an accessible constructor suitable for rethrowing a >>> value of type C (see below). >>> * T is not the same type as C. >>> >>> Any exceptions thrown by the method body which are a subtype of a >>> caught exception type in the rethrows clause, are rethrown as the >>> corresponding translated exception type. >>> >>> For a given translated type T with corresponding caught type C, if >>> T has an accessible constructor accepting a value of type C, then >>> the translation is equivalent to the following: >>> >>> catch (C e) { >>> throw new T(e); >>> } >>> >>> Otherwise it must have an accessible no argument constructor, and >>> the translation is equivalent to: >>> >>> catch (C e) { >>> throw new T().initCause(e); >>> } >>> >>> >>> A rethrows clause does not restrict which types may appear in a >>> throws clause for the same method. In particular, for a given >>> caught type C in the rethrows clause, it is permitted for some >>> type C1 :> C to also be listed in the throws clause. >>> >>> >>> JLSv3 ?8.2 : The set of exception types declared to be thrown by >>> a method is the union of: >>> * the types in the throws clause >>> * the translated types in the rethrow clause >>> * the types thrown by the translated types' selected >>> constructors >>> >>> JLSv3 ?11.2.2 : For the purposes of exception analysis, the set >>> of checked exception types which may be thrown by the method's >>> body is the union of: >>> * the types in the throws clause >>> * the caught types in the rethrows clause >>> >>> JLSv3 ?11.2.3 : It is a compile-time error if a rethrows clause >>> contains a translation from a checked exception type C but there >>> exists no checked exception type E such that all of the following >>> hold: >>> * E <: C >>> * The method body can throw E >>> * No preceding translation in the rethrow clause catches E or >>> a supertype of E >>> unless C is the class java.lang.Exception. >>> >>> JLSv3 ?13.4.21 : Changes to the rethrows clause of methods or >>> constructors do not break compatibility with existing binaries; >>> these clauses are checked only at compile time. >>> >>> >>> >>> COMPILATION: How would the feature be compiled to class files? >>> Show how the simple and advanced examples would be compiled. >>> Compilation can be expressed as at least one of a desugaring to >>> existing source constructs and a translation down to bytecode. If >>> a new bytecode is used or the semantics of an existing bytecode >>> are changed, describe those changes, including how they impact >>> verification. Also discuss any new class file attributes that are >>> introduced. Note that there are many downstream tools that >>> consume class files and that they may to be updated to support >>> the proposal! >>> >>> A simple desugaring could consist of enclosing the method body's >>> statements in a try statement, with catch clauses for each >>> translated exception type. For example, the following method: >>> >>> Method findMethod() >>> catch ClassNotFoundException throw ConfigException, >>> NoSuchMethodException throw ConfigException { >>> >>> Class c = Class.forName("some.Thing"); >>> return c.getDeclaredMethod("execute", null); >>> } >>> >>> would be desugared to: >>> >>> Method findMethod() >>> throws ConfigException { >>> try { >>> Class c = Class.forName("some.Thing"); >>> return c.getDeclaredMethod("execute", null); >>> } >>> catch (ClassNotFoundException e) { >>> throw new ConfigException(e); >>> } >>> catch (MethodNotFoundException e) { >>> throw new ConfigException(e); >>> } >>> } >>> >>> No changes to the classfile format are required. >>> >>> >>> TESTING: How can the feature be tested? >>> >>> An initial set of jtreg tests is included in the prototype. >>> >>> >>> LIBRARY SUPPORT: Are any supporting libraries needed for the >>> feature? >>> >>> No >>> >>> >>> REFLECTIVE APIS: Do any of the various and sundry reflection APIs >>> need to be updated? This list of reflective APIs includes but is >>> not limited to core reflection (java.lang.Class and >>> java.lang.reflect.*), javax.lang.model.*, the doclet API, and JPDA. >>> >>> com.sun.source.tree.MethodTree would require updates to access >>> the rethrows clause's caught and translated types. >>> >>> >>> OTHER CHANGES: Do any other parts of the platform need be updated >>> too? Possibilities include but are not limited to JNI, >>> serialization, and output of the javadoc tool. >>> >>> No >>> >>> >>> MIGRATION: Sketch how a code base could be converted, manually or >>> automatically, to use the new feature. >>> >>> Catch clauses which simply wrap and rethrow an exception as >>> another exception type not caught in an enclosing scope, can be >>> trivially replaced with a rethrows clause, either manually or >>> automatically. >>> >>> It should be possible for tools to offer bidirectional >>> conversions such that an exception translation may be moved back >>> into the method body if it is subsequently decided that >>> additional logic is required. >>> >>> >>> COMPATIBILITY >>> >>> BREAKING CHANGES: Are any previously valid programs now invalid? >>> If so, list one. >>> >>> No >>> >>> >>> EXISTING PROGRAMS: How do source and class files of earlier >>> platform versions interact with the feature? Can any new >>> overloadings occur? Can any new overriding occur? >>> >>> The semantics of existing class files and legal source files are >>> unchanged by this feature. >>> >>> >>> REFERENCES >>> >>> EXISTING BUGS: Please include a list of any existing Sun bug ids >>> related to this proposal. >>> >>> http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6534270 >>> (similar, but emphasizes unchecked exceptions) >>> >>> >>> URL FOR PROTOTYPE (optional): >>> >>> http://slm888.com/javac >>> >>> >>> >> > > From rssh at gradsoft.com.ua Tue May 19 22:01:20 2009 From: rssh at gradsoft.com.ua (Ruslan Shevchenko) Date: Wed, 20 May 2009 08:01:20 +0300 (EEST) Subject: UPDATED: Rethrows Clause In-Reply-To: <68BF955A-9796-44F7-9E97-94BBB43ADCC5@zwitserloot.com> References: <39084932-B2CC-4B91-97EA-006FE21301F0@googlemail.com> <4A1339ED.8090309@sun.com> <68BF955A-9796-44F7-9E97-94BBB43ADCC5@zwitserloot.com> Message-ID: <988330f1d03fc629490d5dffa3fc2d25.squirrel@wmail.gradsoft.ua> > Here's a trivially simple change to implement, though it has some far > reaching repercussions for java as a whole: > > change the 'rethrows' clause to an ignores clause: Any checked > exception in the ignores list may be thrown from the method body, but > is NOT part of the method's checked exception list. It is hence also > not part of the signature, just like sticking a 'synchronized' keyword > on a method isn't part of its signature, but an implementation detail. > > > example: > > Runnable r = new Runnable() { > public void run() ignores UnsupportedEncodingException { > String x = new String(inBytes, "UTF-8"); > } > }; > And how actually debug such statements ? //In this example, run() method do nothing, so look on slightly complex primer: class X { String x; public void setString(byte[] inBytes) ignores UnsupportedEncodingException { x = new String(inBytes, "UUTF-8"); } public void setAndPrintString(byte[] inBytes) { setString(inBytes); System.out.println("received:"+x); } } Assume, that programmer wrote (by error) "UUTF-8" instead "UTF-8" Output of programm will be "received:null". Reasons for null x in complex programs can be millions. Debugging with ignoring exception will be extremally hard. I. e. wrapping checked exception to runtime is more or less normal; ignoring will become a very big paint-point. Alternative to ignore can be call default thread exception handler. (handle keyword ?) > This sounds like blowing up the entire point of checked exceptions, > but with java moving towards more interoperation with other JVM based > languages, which almost always throw checked exceptions without > actually declaring them (Jython, JRuby, Scala -- I can't think of a > single one other than java itself that has the notion of checked > exceptions in the first place). If the whole 'java is like the > assembler of the JVM' story is going to hold water, something like > this is needed. > Yes, this is interesting problem. In theory we have UndeclaredThowableException, but .. wrapping each invocation of foreign language into it is ineffecient. But InvokeDynamic can throws any throwable in declaration, so this problem can be solved (on other level) > For some further support: I doubt anyone seriously holds the position > that java's checked exception experiment was an unmitigated success. > There are pain points, here and there. The above example in fact > includes two of them: The fact that runnable throws no checked > exceptions is clearly a mistake in regards to threading, because > Thread objects clearly should handle ANY exception falling out of its > run() method (and it in fact does, via the unchecked exception handler > mechanism), and there's a general mismatch between main(), which MAY > throw exceptions, and run(), which may not, even though they are both > 'thread start points'. Another mistake is Adding throw exception to signature of Runnable.run does not broke anything in existent code, so this can be nice library change. > UnsupportedEncodingExceptions, a checked exception, resulting from a > call to converting byte arrays to strings using an encoding that is > guaranteed by the JVM using a string literal, such as "UTF-8". The > appropriate exception would be UnsupportedEncodingError("This JVM is > broken. Charset UTF-8 missing. Reinstall it") - which is unchecked. > Or porgrammer can write UUTF-8 instead UTF-8. It's happens ;) > In other words, while I'm not ready to write off checked exceptions as > a whole, I am more than ready to acknowledge that the programmer more > often knows better than the compiler, compared to how often the > programmer, in laziness or inexperience, abuses this freedom. > Especially considering that, on the JVM, you really DONT get checked > exceptions guarantees; any class compiled by anything other than javac > is free to throw checked exceptions without declaring them, and even > in javac you can technically do this using 'sneaky throw' libraries, > which use various workarounds, one of which will NEVER go away*. We're > not losing much here, in other words. In fact, the way javac works, > inexperienced java programmers may erroneously assume that checked > exceptions couldn't possibly happen unless the checked exception is > declared. This is not the case. > > *) The one that will never go away is java.lang.Class.newInstance(), > which is functionally defined to sneakily throw on any exceptions > thrown by the constructor, checked or not, and does NOT wrap them up > into a wrapper the way java.lang.reflect.Method.invoke() does. This Its wrapped to java.lang.ExceptionInInitializerError > cannot change without breaking backwards compatibility. Another one > that will never go away is constructing a class on the fly that sneaky > throws, loading it with ClassLoader's load from bytes mechanism, and > executing it. > And what is JVM behaviour in such case ? > > Attempting to solve this issue with a library requires rather a lot of > ugly boilerplate: > > import static Utils.sneakyThrow; > > Runnable r = new Runnable() { > public void run() { > String x; > try { > x = new String(inBytes, "UTF-8"); > } catch ( UnsupportedEncodingException e ) { > sneakyThrow(e); > } > } > }; > > > NB: For sanity purposes, the restriction on javac that the try block > MUST contain at least 1 statement that could throw a checked exception > type that is listed on one of the accompanying catch blocks (other > than Exception, which you can always catch), should go away; this has > already been proposed before, and in fact is a backwards compatibility > painpoint for the coin proposal that allows you to rethrow a final > Exception as if its type is the intersection of all checked types > thrown by the statements in the try body. > > --Reinier Zwitserloot > Like it? Tip it! > http://tipit.to > > > > On May 20, 2009, at 02:22, Mark Mahieu wrote: > >> Yeah, I suppose I did make it rather more complicated than it needed >> to be. >> >> Thanks for the feedback. >> >> Mark >> >> >> On 19 May 2009, at 23:59, Joe Darcy wrote: >> >>> Hello. >>> >>> Hmm; this strikes me as a bit involved for the potential benefits >>> of the feature. >>> >>> -Joe >>> >>> On 03/30/09 05:04 PM, Mark Mahieu wrote: >>>> Forgot my JLS references in the first one... >>>> >>>> >>>> >>>> HTML version + prototype available at: >>>> >>>> http://slm888.com >>>> >>>> >>>> >>>> >>>> Rethrows Clause >>>> v0.1.1 >>>> >>>> >>>> AUTHOR(S): >>>> >>>> Mark Mahieu >>>> >>>> >>>> OVERVIEW >>>> >>>> FEATURE SUMMARY: Should be suitable as a summary in a language >>>> tutorial. >>>> >>>> A new clause on method declarations which allows exception >>>> translations (wrapping and rethrowing as a different type) to be >>>> cleanly defined separately from the body of the method. In many >>>> cases, checked exception type names do not then need to be >>>> repeated in a method's throws clause and in a throw statement in >>>> the method body. >>>> >>>> >>>> MAJOR ADVANTAGE: What makes the proposal a favorable change? >>>> >>>> The proposal adds direct support for a common idiom in daily use >>>> by Java programmers worldwide, allowing them to express their >>>> intentions with greater clarity and ease. In comparison with >>>> some proposals, this is an attempt to make dealing with checked >>>> exceptions easier by increasing the expressiveness of exception >>>> handling code in general, rather than by attempting to deprecate >>>> checked exceptions in favour of unchecked exceptions. >>>> >>>> >>>> MAJOR BENEFIT: Why is the platform better if the proposal is >>>> adopted? >>>> >>>> There is a reduction in the amount of boilerplate Java >>>> programmers have to read and write for code dealing with checked >>>> exceptions. Declarations specifying both thrown and rethrown >>>> (wrapped) exceptions are kept together, aiding comprehension of >>>> the code. >>>> >>>> >>>> MAJOR DISADVANTAGE: There is always a cost. >>>> >>>> As with any syntax sugar which enables an alternative way of >>>> expressing an existing idiom, programmers may be tempted to use >>>> it even when the existing idiom would be more appropriate. >>>> >>>> >>>> ALTERNATIVES: Can the benefits and advantages be had some way >>>> without a language change? >>>> >>>> No. >>>> >>>> >>>> EXAMPLES >>>> >>>> SIMPLE EXAMPLE: Show the simplest possible program utilizing the >>>> new feature. >>>> >>>> >>>> Before: >>>> >>>> void before() throws ConfigException { >>>> try { >>>> Class.forName("where.is.the.Code"); >>>> } >>>> catch (ClassNotFoundException e) { >>>> throw new ConfigException(e); >>>> } >>>> } >>>> >>>> After: >>>> >>>> void after() >>>> catch ClassNotFoundException throw ConfigException { >>>> >>>> Class.forName("here.is.the.Code"); >>>> } >>>> >>>> >>>> ADVANCED EXAMPLE: Show advanced usage(s) of the feature. >>>> >>>> Before: >>>> >>>> void suspendAccount() >>>> throws AuthorizationException, >>>> PersistenceException { >>>> try { >>>> checkMyAuthoritah(); >>>> db.update(/*...*/); >>>> log.recordInfo(/*...*/); >>>> } >>>> catch (InfernalDBException e) { >>>> throw new PersistenceException(e); >>>> } >>>> catch (InfernalLogException e) { >>>> throw new RuntimeException(e); >>>> } >>>> } >>>> >>>> After: >>>> >>>> void suspendAccount() >>>> throws AuthorizationException >>>> catch InfernalDBException throw PersistenceException, >>>> InfernalLogException throw RuntimeException { >>>> >>>> checkMyAuthoritah(); >>>> db.update(/*...*/); >>>> log.recordInfo(/*...*/); >>>> } >>>> >>>> >>>> DETAILS >>>> >>>> SPECIFICATION: Describe how the proposal affects the grammar, >>>> type system, and meaning of expressions and statements in the >>>> Java Programming Language as well as any other known impacts. >>>> >>>> The syntactic grammar is modified to allow an optional rethrows >>>> clause immediately prior to a MethodBody: >>>> >>>> MethodDeclaratorRest: >>>> FormalParameters {[]} [throws >>>> QualifiedIdentifierList] ( ( [catch ExceptionTranslationList] >>>> MethodBody ) | ; ) >>>> >>>> ExceptionTranslationList: >>>> QualifiedIdentifier throw QualifiedIdentifier >>>> { , ExceptionTranslationList } >>>> >>>> >>>> >>>> JLSv3 ?8.4.6 : A rethrows clause lists one or more exception >>>> translations, each translation consisting of a caught type C and >>>> a translated type T for which all of the following must hold: >>>> * C <: java.lang.Exception >>>> * T < java.lang.Throwable >>>> * Neither C nor T is a type variable. >>>> * T has an accessible constructor suitable for rethrowing a >>>> value of type C (see below). >>>> * T is not the same type as C. >>>> >>>> Any exceptions thrown by the method body which are a subtype of a >>>> caught exception type in the rethrows clause, are rethrown as the >>>> corresponding translated exception type. >>>> >>>> For a given translated type T with corresponding caught type C, if >>>> T has an accessible constructor accepting a value of type C, then >>>> the translation is equivalent to the following: >>>> >>>> catch (C e) { >>>> throw new T(e); >>>> } >>>> >>>> Otherwise it must have an accessible no argument constructor, and >>>> the translation is equivalent to: >>>> >>>> catch (C e) { >>>> throw new T().initCause(e); >>>> } >>>> >>>> >>>> A rethrows clause does not restrict which types may appear in a >>>> throws clause for the same method. In particular, for a given >>>> caught type C in the rethrows clause, it is permitted for some >>>> type C1 :> C to also be listed in the throws clause. >>>> >>>> >>>> JLSv3 ?8.2 : The set of exception types declared to be thrown by >>>> a method is the union of: >>>> * the types in the throws clause >>>> * the translated types in the rethrow clause >>>> * the types thrown by the translated types' selected >>>> constructors >>>> >>>> JLSv3 ?11.2.2 : For the purposes of exception analysis, the set >>>> of checked exception types which may be thrown by the method's >>>> body is the union of: >>>> * the types in the throws clause >>>> * the caught types in the rethrows clause >>>> >>>> JLSv3 ?11.2.3 : It is a compile-time error if a rethrows clause >>>> contains a translation from a checked exception type C but there >>>> exists no checked exception type E such that all of the following >>>> hold: >>>> * E <: C >>>> * The method body can throw E >>>> * No preceding translation in the rethrow clause catches E or >>>> a supertype of E >>>> unless C is the class java.lang.Exception. >>>> >>>> JLSv3 ?13.4.21 : Changes to the rethrows clause of methods or >>>> constructors do not break compatibility with existing binaries; >>>> these clauses are checked only at compile time. >>>> >>>> >>>> >>>> COMPILATION: How would the feature be compiled to class files? >>>> Show how the simple and advanced examples would be compiled. >>>> Compilation can be expressed as at least one of a desugaring to >>>> existing source constructs and a translation down to bytecode. If >>>> a new bytecode is used or the semantics of an existing bytecode >>>> are changed, describe those changes, including how they impact >>>> verification. Also discuss any new class file attributes that are >>>> introduced. Note that there are many downstream tools that >>>> consume class files and that they may to be updated to support >>>> the proposal! >>>> >>>> A simple desugaring could consist of enclosing the method body's >>>> statements in a try statement, with catch clauses for each >>>> translated exception type. For example, the following method: >>>> >>>> Method findMethod() >>>> catch ClassNotFoundException throw ConfigException, >>>> NoSuchMethodException throw ConfigException { >>>> >>>> Class c = Class.forName("some.Thing"); >>>> return c.getDeclaredMethod("execute", null); >>>> } >>>> >>>> would be desugared to: >>>> >>>> Method findMethod() >>>> throws ConfigException { >>>> try { >>>> Class c = Class.forName("some.Thing"); >>>> return c.getDeclaredMethod("execute", null); >>>> } >>>> catch (ClassNotFoundException e) { >>>> throw new ConfigException(e); >>>> } >>>> catch (MethodNotFoundException e) { >>>> throw new ConfigException(e); >>>> } >>>> } >>>> >>>> No changes to the classfile format are required. >>>> >>>> >>>> TESTING: How can the feature be tested? >>>> >>>> An initial set of jtreg tests is included in the prototype. >>>> >>>> >>>> LIBRARY SUPPORT: Are any supporting libraries needed for the >>>> feature? >>>> >>>> No >>>> >>>> >>>> REFLECTIVE APIS: Do any of the various and sundry reflection APIs >>>> need to be updated? This list of reflective APIs includes but is >>>> not limited to core reflection (java.lang.Class and >>>> java.lang.reflect.*), javax.lang.model.*, the doclet API, and JPDA. >>>> >>>> com.sun.source.tree.MethodTree would require updates to access >>>> the rethrows clause's caught and translated types. >>>> >>>> >>>> OTHER CHANGES: Do any other parts of the platform need be updated >>>> too? Possibilities include but are not limited to JNI, >>>> serialization, and output of the javadoc tool. >>>> >>>> No >>>> >>>> >>>> MIGRATION: Sketch how a code base could be converted, manually or >>>> automatically, to use the new feature. >>>> >>>> Catch clauses which simply wrap and rethrow an exception as >>>> another exception type not caught in an enclosing scope, can be >>>> trivially replaced with a rethrows clause, either manually or >>>> automatically. >>>> >>>> It should be possible for tools to offer bidirectional >>>> conversions such that an exception translation may be moved back >>>> into the method body if it is subsequently decided that >>>> additional logic is required. >>>> >>>> >>>> COMPATIBILITY >>>> >>>> BREAKING CHANGES: Are any previously valid programs now invalid? >>>> If so, list one. >>>> >>>> No >>>> >>>> >>>> EXISTING PROGRAMS: How do source and class files of earlier >>>> platform versions interact with the feature? Can any new >>>> overloadings occur? Can any new overriding occur? >>>> >>>> The semantics of existing class files and legal source files are >>>> unchanged by this feature. >>>> >>>> >>>> REFERENCES >>>> >>>> EXISTING BUGS: Please include a list of any existing Sun bug ids >>>> related to this proposal. >>>> >>>> http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6534270 >>>> (similar, but emphasizes unchecked exceptions) >>>> >>>> >>>> URL FOR PROTOTYPE (optional): >>>> >>>> http://slm888.com/javac >>>> >>>> >>>> >>> >> >> > > > From howard.lovatt at iee.org Wed May 20 01:43:43 2009 From: howard.lovatt at iee.org (Howard Lovatt) Date: Wed, 20 May 2009 18:43:43 +1000 Subject: Notes on implementing concise calls to constructors with type parameters In-Reply-To: <15e8b9d20905180841n11b9825aj59d9bf6f4aa1a3f1@mail.gmail.com> References: <3dd3f56a0905132041r67710789if86d4e942987a039@mail.gmail.com> <15e8b9d20905132115r58bfe6a7naa6952e5f94c1392@mail.gmail.com> <3dd3f56a0905140543v63603bd4qed2a149fc06cb0ce@mail.gmail.com> <15e8b9d20905140932g33fbcd7atd6c6e28f95211cb4@mail.gmail.com> <3dd3f56a0905150026ta489f58lece1b35ee17df44d@mail.gmail.com> <15e8b9d20905150633n5f3cbb92q79a37a4e736b93b9@mail.gmail.com> <3dd3f56a0905180113l1b7dab5fge695caba96fdcf72@mail.gmail.com> <15e8b9d20905180841n11b9825aj59d9bf6f4aa1a3f1@mail.gmail.com> Message-ID: <3dd3f56a0905200143n15d91e77x40391c3af2d8b0d8@mail.gmail.com> Hi Neal, Sorry for the slow response - end of FY in Australia :( 2009/5/19 Neal Gafter : > I don't understand how this is all supposed to work when typeRHS is absent > and is then inferred to be a generic type involving wildcards (e.g. List extends Number>).? Are we supposed to just drop the wildcards? Use the bound or the raw type in the case of multiple bounds, e.g.: // Translation // Original Ex eues = new Ex(); // Ex eues = new(); Ex eles = new Ex(); // Ex eles = new(); > It seems madness to ignore the types of the (constructor) parameters, the > type parameter bounds, the relationship between the type parameters in > typeLHS and typeRHS, etc, in doing type inference.? That's probably not > something that can be done "later" because of compatibility. The argument goes that in Java you specify the type on the left, so that: int i = "s"; Is an error, whereas in Scala a mistake like: def i = "s" // meant to be an int Isn't caught. Therefore the following should be an error: Cell c = new( "s" ); Which implies left to right inference. If you are trying to do right to left inference, like Scala, then using the arguments to infere type is a good choice. However, the algorithm proposed doesn't do that, so that it catches errors like traditional Java does. > For an example, consider > > class Permutation implements Map { ... } > > Textual substitution cannot work with this class. I don't get the example, I must be missing something - can you elaborate please? [spin] to next email > One more thing. What if "genericParametersRHS" contain captured wildcards or conjunctive types? Did you mean LHS, can you give an example? Have you in mind something like this? class ExC> {} class ExT implements Comparable { ... } // Translation // Original ExC ct__ = new ExC(); // ExC ct__ = new(); Or are you think of something like: static > void method( Ex e ) {} method( new() ); Which would translate to: method( new Ex() ); Because new Ex> isn't ilegal. IE for multiple bounds use raw types. -- Howard. From brucechapman at paradise.net.nz Wed May 20 02:26:58 2009 From: brucechapman at paradise.net.nz (Bruce Chapman) Date: Wed, 20 May 2009 21:26:58 +1200 Subject: JCK feedback on "Strings in Switch" proposal In-Reply-To: <4A12A923.9060501@sun.com> References: <4A12A923.9060501@sun.com> Message-ID: <4A13CCE2.9070705@paradise.net.nz> Dmitry Miltsov wrote: > Hello, > > The JCK engineers have reviewed the "Strings in switch" proposal > and found one issue to clarify. > > "14.11 The switch Statement" states: > ------------------------------------------------------------------ > ... > Otherwise, execution continues by comparing the value of the > Expression with each case constant. Then there is a choice: > * If one of the case constants is equal to the value of the > expression, then we say that the case matches ... > ------------------------------------------------------------------ > > It would be good to clarify what "equal" means in case of the > String values. It would be useful to mention that in this case > the result of comparison will be "expression.equals(constant)", > not "expression == constant" as for other types. > But if expressed exactly like that, it implies that expression will be evaluated repeatedly until a match is found, whereas I would expect it to be evaluated once. Bruce > We have no special comments on testability of this feature. > The JCK team will develop conformance tests for it. > > Thanks, > Dmitry Miltsov, JCK engineer > > > From Maurizio.Cimadamore at Sun.COM Wed May 20 02:52:07 2009 From: Maurizio.Cimadamore at Sun.COM (Maurizio Cimadamore) Date: Wed, 20 May 2009 10:52:07 +0100 Subject: Proposal: Type inference for variable definition/initialization using the 'auto' keyword. In-Reply-To: <4A0D0066.1060701@sun.com> References: <4A0D0066.1060701@sun.com> Message-ID: <4A13D2C7.1010201@sun.com> Hi Tim let me start by saying that I've been working on a similar area on the JavaFX compiler. As you probably know, JavaFX supports some kind of limited variable declaration type-inference, so that, e.g. a variable declared as: var x = "Hello!" is automatically inferred to be of type String. Here's a bunch of problems that we found when implementing this feature in JavaFX - note I'm not saying that for these reason the proposal is not feasible, but I think that it should be more precise about the kind of things that the compiler should be able to infer. Let me clarify this by examples: *) inference from multiple assignments: often JavaFX users complain about the impossibility of writing code like: var x = "Hello"; x = 1; //type-error here, Integer cannot be assigned to String which means, after the type of the variable has been inferred (usually in the var initializer or in the first assignment to the variable) it is not possible to 'refine' the inferred type so that it also matches other assignments. In this case a 'complete' approach would have kept track of all the RHS {String, Integer} and inferred x to the type glb{String, Integer}, which happens to be Object & Comparable >. *) cycles in initialization preventing inference In JavaFX forward references are allowed (with warning) which means that sometimes the compiler has no clue about which type should be picked given a sequence of statements like the following: var x = y; var y = x; In Java we (luckily) have no such thing as forward reference - the compiler reports errors in such circumstances. However it's still possible to have some kind of cyclic dependency (through qualified static names): class A { static int a = B.b; } class B { static int b = A.a; } The above code is legal and it compiles without errors. If we use the 'auto' keyword we could write something like: class A { static auto a = B.b; } class B { static auto b = A.a; } Which types is the compiler supposed to infer for both a and b? I think that a proposal should deal explicitly with such 'corner' cases - they might seem a bit 'artificial' here, but they (or similar variants) are fairly common once users start to heavily rely on variable-type inference. Simply trusting the compiler to 'figure out' what the right type would be in each case is not an option :-) . Maurizio Joseph D. Darcy wrote: > Tim Lebedkov wrote: > >> Type inference for variable definition/initialization using the 'auto' keyword. >> >> AUTHOR(S): Tim Lebedkov >> >> OVERVIEW >> >> Provide a two sentence or shorter description of these five aspects of >> the feature: >> >> FEATURE SUMMARY: Should be suitable as a summary in a language tutorial. >> >> This proposal addresses the addition of type inference for >> variable definitions to the Java programming language using the 'auto' >> keyword instead of specific type name. >> >> For example, consider the following assignment statement: >> >> Map> anagrams = new HashMap>(); >> >> This is rather lengthy, so it can be replaced with this: >> >> auto anagrams = new HashMap>(); >> >> and anagrams is automatically typed as HashMap> >> >> MAJOR ADVANTAGE: What makes the proposal a favorable change? >> >> Generics have had a tremendously positive impact on type safety in the >> Java programming language. They have made it possible to provide >> static guarantees about the type of instances used by other classes, >> preventing entire classes of runtime errors from occurring. However, >> generics have added complexity to Java, making the code far more >> verbose and occasionally difficult to read. Although solving this >> problem is well outside the scope of this proposal, a limited form of >> type inference would remove unnecessary redundancy from the language. >> Even without generics it seems unnecessary to duplicate type names for >> simple variable definitions/assignments like: >> >> Integer a = new Integer(1023); >> >> MAJOR BENEFIT: Why is the platform better if the proposal is adopted? >> >> Less code and no duplication has a positive impact on many things: >> - faster typing/faster code changes >> - easier code changing without IDE assistance >> - code versioning diffs are more clear >> >> MAJOR DISADVANTAGE: There is always a cost. >> >> - it could be harder to read the code. >> - auto will be a keyword and may break some old code >> >> ALTERNATIVES: Can the benefits and advantages be had some way without >> a language change? >> >> no >> >> >> > > Catching up on proposal comments, I think the core benefits of using > "auto" or "final" on the left hand side for variables are achieved with > the diamond operator that allows one to elide type parameters on the > right hand side. IMO, the diamond solution of specifying the variable > type fully on the left and then specifying only the implementation type > without redundant, repeated type parameters on the right is more in > keeping with Java coding style. > > -Joe > > From markmahieu at googlemail.com Wed May 20 04:21:35 2009 From: markmahieu at googlemail.com (Mark Mahieu) Date: Wed, 20 May 2009 12:21:35 +0100 Subject: UPDATED: Rethrows Clause In-Reply-To: <68BF955A-9796-44F7-9E97-94BBB43ADCC5@zwitserloot.com> References: <39084932-B2CC-4B91-97EA-006FE21301F0@googlemail.com> <4A1339ED.8090309@sun.com> <68BF955A-9796-44F7-9E97-94BBB43ADCC5@zwitserloot.com> Message-ID: <5F883898-AF22-4166-A813-2ECE09538642@googlemail.com> Reinier, That seems quite a lot like the suggestion in bug 6534270 (http:// bugs.sun.com/bugdatabase/view_bug.do?bug_id=6534270). That approach may well have merit, but I personally think that any proposal which tries to 'improve' exception handling by promoting unchecked exceptions would probably involve more 'philosophical' changes to Java than Coin is able to take on. So I deliberately chose an alternative which is just as applicable when rethrowing a checked exception as another type of checked exception as it is when rethrowing as an unchecked type - in fact, it's very similar to an idea suggested by Brian Goetz a while back (http://www.briangoetz.com/blog/?p=43). But I also made the proposal more complicated than necessary in other areas, largely as a by-product of trying to include enough detail; with hindsight, a simpler formulation probably would have been better - at least as an initial basis for discussion and refinement. Mark On 20 May 2009, at 07:46, Reinier Zwitserloot wrote: > Here's a trivially simple change to implement, though it has some > far reaching repercussions for java as a whole: > > change the 'rethrows' clause to an ignores clause: Any checked > exception in the ignores list may be thrown from the method body, > but is NOT part of the method's checked exception list. It is hence > also not part of the signature, just like sticking a 'synchronized' > keyword on a method isn't part of its signature, but an > implementation detail. > > > example: > > Runnable r = new Runnable() { > public void run() ignores UnsupportedEncodingException { > String x = new String(inBytes, "UTF-8"); > } > }; > > This sounds like blowing up the entire point of checked exceptions, > but with java moving towards more interoperation with other JVM > based languages, which almost always throw checked exceptions > without actually declaring them (Jython, JRuby, Scala -- I can't > think of a single one other than java itself that has the notion of > checked exceptions in the first place). If the whole 'java is like > the assembler of the JVM' story is going to hold water, something > like this is needed. > > For some further support: I doubt anyone seriously holds the > position that java's checked exception experiment was an > unmitigated success. There are pain points, here and there. The > above example in fact includes two of them: The fact that runnable > throws no checked exceptions is clearly a mistake in regards to > threading, because Thread objects clearly should handle ANY > exception falling out of its run() method (and it in fact does, via > the unchecked exception handler mechanism), and there's a general > mismatch between main(), which MAY throw exceptions, and run(), > which may not, even though they are both 'thread start points'. > Another mistake is UnsupportedEncodingExceptions, a checked > exception, resulting from a call to converting byte arrays to > strings using an encoding that is guaranteed by the JVM using a > string literal, such as "UTF-8". The appropriate exception would be > UnsupportedEncodingError("This JVM is broken. Charset UTF-8 > missing. Reinstall it") - which is unchecked. > > In other words, while I'm not ready to write off checked exceptions > as a whole, I am more than ready to acknowledge that the programmer > more often knows better than the compiler, compared to how often > the programmer, in laziness or inexperience, abuses this freedom. > Especially considering that, on the JVM, you really DONT get > checked exceptions guarantees; any class compiled by anything other > than javac is free to throw checked exceptions without declaring > them, and even in javac you can technically do this using 'sneaky > throw' libraries, which use various workarounds, one of which will > NEVER go away*. We're not losing much here, in other words. In > fact, the way javac works, inexperienced java programmers may > erroneously assume that checked exceptions couldn't possibly happen > unless the checked exception is declared. This is not the case. > > *) The one that will never go away is java.lang.Class.newInstance > (), which is functionally defined to sneakily throw on any > exceptions thrown by the constructor, checked or not, and does NOT > wrap them up into a wrapper the way java.lang.reflect.Method.invoke > () does. This cannot change without breaking backwards > compatibility. Another one that will never go away is constructing > a class on the fly that sneaky throws, loading it with > ClassLoader's load from bytes mechanism, and executing it. > > > Attempting to solve this issue with a library requires rather a lot > of ugly boilerplate: > > import static Utils.sneakyThrow; > > Runnable r = new Runnable() { > public void run() { > String x; > try { > x = new String(inBytes, "UTF-8"); > } catch ( UnsupportedEncodingException e ) { > sneakyThrow(e); > } > } > }; > > > NB: For sanity purposes, the restriction on javac that the try > block MUST contain at least 1 statement that could throw a checked > exception type that is listed on one of the accompanying catch > blocks (other than Exception, which you can always catch), should > go away; this has already been proposed before, and in fact is a > backwards compatibility painpoint for the coin proposal that allows > you to rethrow a final Exception as if its type is the intersection > of all checked types thrown by the statements in the try body. > > --Reinier Zwitserloot > Like it? Tip it! > http://tipit.to > > > > On May 20, 2009, at 02:22, Mark Mahieu wrote: > >> Yeah, I suppose I did make it rather more complicated than it needed >> to be. >> >> Thanks for the feedback. >> >> Mark >> >> >> On 19 May 2009, at 23:59, Joe Darcy wrote: >> >>> Hello. >>> >>> Hmm; this strikes me as a bit involved for the potential benefits >>> of the feature. >>> >>> -Joe >>> >>> On 03/30/09 05:04 PM, Mark Mahieu wrote: >>>> Forgot my JLS references in the first one... >>>> >>>> >>>> >>>> HTML version + prototype available at: >>>> >>>> http://slm888.com >>>> >>>> >>>> >>>> >>>> Rethrows Clause >>>> v0.1.1 >>>> >>>> >>>> AUTHOR(S): >>>> >>>> Mark Mahieu >>>> >>>> >>>> OVERVIEW >>>> >>>> FEATURE SUMMARY: Should be suitable as a summary in a language >>>> tutorial. >>>> >>>> A new clause on method declarations which allows exception >>>> translations (wrapping and rethrowing as a different type) to be >>>> cleanly defined separately from the body of the method. In many >>>> cases, checked exception type names do not then need to be >>>> repeated in a method's throws clause and in a throw statement in >>>> the method body. >>>> >>>> >>>> MAJOR ADVANTAGE: What makes the proposal a favorable change? >>>> >>>> The proposal adds direct support for a common idiom in daily use >>>> by Java programmers worldwide, allowing them to express their >>>> intentions with greater clarity and ease. In comparison with >>>> some proposals, this is an attempt to make dealing with checked >>>> exceptions easier by increasing the expressiveness of exception >>>> handling code in general, rather than by attempting to deprecate >>>> checked exceptions in favour of unchecked exceptions. >>>> >>>> >>>> MAJOR BENEFIT: Why is the platform better if the proposal is >>>> adopted? >>>> >>>> There is a reduction in the amount of boilerplate Java >>>> programmers have to read and write for code dealing with checked >>>> exceptions. Declarations specifying both thrown and rethrown >>>> (wrapped) exceptions are kept together, aiding comprehension of >>>> the code. >>>> >>>> >>>> MAJOR DISADVANTAGE: There is always a cost. >>>> >>>> As with any syntax sugar which enables an alternative way of >>>> expressing an existing idiom, programmers may be tempted to use >>>> it even when the existing idiom would be more appropriate. >>>> >>>> >>>> ALTERNATIVES: Can the benefits and advantages be had some way >>>> without a language change? >>>> >>>> No. >>>> >>>> >>>> EXAMPLES >>>> >>>> SIMPLE EXAMPLE: Show the simplest possible program utilizing the >>>> new feature. >>>> >>>> >>>> Before: >>>> >>>> void before() throws ConfigException { >>>> try { >>>> Class.forName("where.is.the.Code"); >>>> } >>>> catch (ClassNotFoundException e) { >>>> throw new ConfigException(e); >>>> } >>>> } >>>> >>>> After: >>>> >>>> void after() >>>> catch ClassNotFoundException throw ConfigException { >>>> >>>> Class.forName("here.is.the.Code"); >>>> } >>>> >>>> >>>> ADVANCED EXAMPLE: Show advanced usage(s) of the feature. >>>> >>>> Before: >>>> >>>> void suspendAccount() >>>> throws AuthorizationException, >>>> PersistenceException { >>>> try { >>>> checkMyAuthoritah(); >>>> db.update(/*...*/); >>>> log.recordInfo(/*...*/); >>>> } >>>> catch (InfernalDBException e) { >>>> throw new PersistenceException(e); >>>> } >>>> catch (InfernalLogException e) { >>>> throw new RuntimeException(e); >>>> } >>>> } >>>> >>>> After: >>>> >>>> void suspendAccount() >>>> throws AuthorizationException >>>> catch InfernalDBException throw PersistenceException, >>>> InfernalLogException throw RuntimeException { >>>> >>>> checkMyAuthoritah(); >>>> db.update(/*...*/); >>>> log.recordInfo(/*...*/); >>>> } >>>> >>>> >>>> DETAILS >>>> >>>> SPECIFICATION: Describe how the proposal affects the grammar, >>>> type system, and meaning of expressions and statements in the >>>> Java Programming Language as well as any other known impacts. >>>> >>>> The syntactic grammar is modified to allow an optional rethrows >>>> clause immediately prior to a MethodBody: >>>> >>>> MethodDeclaratorRest: >>>> FormalParameters {[]} [throws >>>> QualifiedIdentifierList] ( ( [catch ExceptionTranslationList] >>>> MethodBody ) | ; ) >>>> >>>> ExceptionTranslationList: >>>> QualifiedIdentifier throw QualifiedIdentifier >>>> { , ExceptionTranslationList } >>>> >>>> >>>> >>>> JLSv3 ?8.4.6 : A rethrows clause lists one or more exception >>>> translations, each translation consisting of a caught type C and >>>> a translated type T for which all of the following must hold: >>>> * C <: java.lang.Exception >>>> * T < java.lang.Throwable >>>> * Neither C nor T is a type variable. >>>> * T has an accessible constructor suitable for rethrowing a >>>> value of type C (see below). >>>> * T is not the same type as C. >>>> >>>> Any exceptions thrown by the method body which are a subtype of a >>>> caught exception type in the rethrows clause, are rethrown as the >>>> corresponding translated exception type. >>>> >>>> For a given translated type T with corresponding caught type C, if >>>> T has an accessible constructor accepting a value of type C, then >>>> the translation is equivalent to the following: >>>> >>>> catch (C e) { >>>> throw new T(e); >>>> } >>>> >>>> Otherwise it must have an accessible no argument constructor, and >>>> the translation is equivalent to: >>>> >>>> catch (C e) { >>>> throw new T().initCause(e); >>>> } >>>> >>>> >>>> A rethrows clause does not restrict which types may appear in a >>>> throws clause for the same method. In particular, for a given >>>> caught type C in the rethrows clause, it is permitted for some >>>> type C1 :> C to also be listed in the throws clause. >>>> >>>> >>>> JLSv3 ?8.2 : The set of exception types declared to be thrown by >>>> a method is the union of: >>>> * the types in the throws clause >>>> * the translated types in the rethrow clause >>>> * the types thrown by the translated types' selected >>>> constructors >>>> >>>> JLSv3 ?11.2.2 : For the purposes of exception analysis, the set >>>> of checked exception types which may be thrown by the method's >>>> body is the union of: >>>> * the types in the throws clause >>>> * the caught types in the rethrows clause >>>> >>>> JLSv3 ?11.2.3 : It is a compile-time error if a rethrows clause >>>> contains a translation from a checked exception type C but there >>>> exists no checked exception type E such that all of the following >>>> hold: >>>> * E <: C >>>> * The method body can throw E >>>> * No preceding translation in the rethrow clause catches E or >>>> a supertype of E >>>> unless C is the class java.lang.Exception. >>>> >>>> JLSv3 ?13.4.21 : Changes to the rethrows clause of methods or >>>> constructors do not break compatibility with existing binaries; >>>> these clauses are checked only at compile time. >>>> >>>> >>>> >>>> COMPILATION: How would the feature be compiled to class files? >>>> Show how the simple and advanced examples would be compiled. >>>> Compilation can be expressed as at least one of a desugaring to >>>> existing source constructs and a translation down to bytecode. If >>>> a new bytecode is used or the semantics of an existing bytecode >>>> are changed, describe those changes, including how they impact >>>> verification. Also discuss any new class file attributes that are >>>> introduced. Note that there are many downstream tools that >>>> consume class files and that they may to be updated to support >>>> the proposal! >>>> >>>> A simple desugaring could consist of enclosing the method body's >>>> statements in a try statement, with catch clauses for each >>>> translated exception type. For example, the following method: >>>> >>>> Method findMethod() >>>> catch ClassNotFoundException throw ConfigException, >>>> NoSuchMethodException throw ConfigException { >>>> >>>> Class c = Class.forName("some.Thing"); >>>> return c.getDeclaredMethod("execute", null); >>>> } >>>> >>>> would be desugared to: >>>> >>>> Method findMethod() >>>> throws ConfigException { >>>> try { >>>> Class c = Class.forName("some.Thing"); >>>> return c.getDeclaredMethod("execute", null); >>>> } >>>> catch (ClassNotFoundException e) { >>>> throw new ConfigException(e); >>>> } >>>> catch (MethodNotFoundException e) { >>>> throw new ConfigException(e); >>>> } >>>> } >>>> >>>> No changes to the classfile format are required. >>>> >>>> >>>> TESTING: How can the feature be tested? >>>> >>>> An initial set of jtreg tests is included in the prototype. >>>> >>>> >>>> LIBRARY SUPPORT: Are any supporting libraries needed for the >>>> feature? >>>> >>>> No >>>> >>>> >>>> REFLECTIVE APIS: Do any of the various and sundry reflection APIs >>>> need to be updated? This list of reflective APIs includes but is >>>> not limited to core reflection (java.lang.Class and >>>> java.lang.reflect.*), javax.lang.model.*, the doclet API, and >>>> JPDA. >>>> >>>> com.sun.source.tree.MethodTree would require updates to access >>>> the rethrows clause's caught and translated types. >>>> >>>> >>>> OTHER CHANGES: Do any other parts of the platform need be updated >>>> too? Possibilities include but are not limited to JNI, >>>> serialization, and output of the javadoc tool. >>>> >>>> No >>>> >>>> >>>> MIGRATION: Sketch how a code base could be converted, manually or >>>> automatically, to use the new feature. >>>> >>>> Catch clauses which simply wrap and rethrow an exception as >>>> another exception type not caught in an enclosing scope, can be >>>> trivially replaced with a rethrows clause, either manually or >>>> automatically. >>>> >>>> It should be possible for tools to offer bidirectional >>>> conversions such that an exception translation may be moved back >>>> into the method body if it is subsequently decided that >>>> additional logic is required. >>>> >>>> >>>> COMPATIBILITY >>>> >>>> BREAKING CHANGES: Are any previously valid programs now invalid? >>>> If so, list one. >>>> >>>> No >>>> >>>> >>>> EXISTING PROGRAMS: How do source and class files of earlier >>>> platform versions interact with the feature? Can any new >>>> overloadings occur? Can any new overriding occur? >>>> >>>> The semantics of existing class files and legal source files are >>>> unchanged by this feature. >>>> >>>> >>>> REFERENCES >>>> >>>> EXISTING BUGS: Please include a list of any existing Sun bug ids >>>> related to this proposal. >>>> >>>> http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6534270 >>>> (similar, but emphasizes unchecked exceptions) >>>> >>>> >>>> URL FOR PROTOTYPE (optional): >>>> >>>> http://slm888.com/javac >>>> >>>> >>>> >>> >> >> > From rssh at gradsoft.com.ua Wed May 20 03:11:38 2009 From: rssh at gradsoft.com.ua (Ruslan Shevchenko) Date: Wed, 20 May 2009 13:11:38 +0300 (EEST) Subject: UPDATED: Rethrows Clause In-Reply-To: <988330f1d03fc629490d5dffa3fc2d25.squirrel@wmail.gradsoft.ua> References: <39084932-B2CC-4B91-97EA-006FE21301F0@googlemail.com> <4A1339ED.8090309@sun.com> <68BF955A-9796-44F7-9E97-94BBB43ADCC5@zwitserloot.com> <988330f1d03fc629490d5dffa3fc2d25.squirrel@wmail.gradsoft.ua> Message-ID: <1e687d8822ff99d4cb8f911950758c91.squirrel@wmail.gradsoft.ua> >> >> example: >> >> Runnable r = new Runnable() { >> public void run() ignores UnsupportedEncodingException { >> String x = new String(inBytes, "UTF-8"); >> } >> }; >> > Or, you means that ignore will throw LinkageError (?) But this is near the same as rethrow() and word ignore is not very intuitive. (If I was fooled, millions of other programmers also will be fulled;) >> includes two of them: The fact that runnable throws no checked >> exceptions is clearly a mistake in regards to threading, because >> Thread objects clearly should handle ANY exception falling out of its >> run() method (and it in fact does, via the unchecked exception handler >> mechanism), and there's a general mismatch between main(), which MAY >> throw exceptions, and run(), which may not, even though they are both >> 'thread start points'. Another mistake is > > Adding throw exception to signature of Runnable.run does not broke > anything in existent code, so this can be nice library change. > (it's incorrest. Of course, exists incompatibility, but only for code, which use Thread or Runnable as parameters: I guess this rare (some deep libraries), and JDK6->JDK7 transition can allows such incompatibility) >> >> NB: For sanity purposes, the restriction on javac that the try block >> MUST contain at least 1 statement that could throw a checked exception >> type that is listed on one of the accompanying catch blocks (other >> than Exception, which you can always catch), should go away; this has >> already been proposed before, and in fact is a backwards compatibility >> painpoint for the coin proposal that allows you to rethrow a final >> Exception as if its type is the intersection of all checked types >> thrown by the statements in the try body. >> That this is work for RuntimeExceptions. And Java support both runtime and checked exception. I guess, that transition to unchecked exception can be done mostly by migrating libraries from checked exception to unchecked. And, may be here we have answer: why framework code have high percentage of rethrow statements, when application code (such as e-commerce system or ERP) - not. Because on first layer all checked exceptions become runtime; than we work with runtime exceptions in more simple (and risky) manner From reinier at zwitserloot.com Wed May 20 06:26:07 2009 From: reinier at zwitserloot.com (Reinier Zwitserloot) Date: Wed, 20 May 2009 15:26:07 +0200 Subject: The 'ignoreslist' exception handling proposal. Message-ID: I'm more convinced than ever that java really needs this change, sooner rather than later. My arguments in favour: 1. Ruslan totally misunderstood my proposal, and also appears to misunderstand checked exceptions on the JVM level in general. This is in my experience an extremely common problem amongst java programmers, and this is very bad news for trying to interop javac-produced class files with scalac, groovy, JRuby, Python, and other languages' class files. By adding the concept of sneakyThrow to java, we teach java programmers that checked exceptions are only a debugging aid offered by javac, and NOT a guarantee by the JVM. This isn't a philosophical change at all: It's realism. In today's JVM world, you just cannot rely on that as a java programmer, and yet most java programmers do. NB: Ruslan and everyone else that's confused - I'll send an explanatory email in a few minutes to explain how it all works. 2. Joe Darcy, project coin, and sun routinely defend choices for the java platform by stating that java is designed for the realistic, human (e.g. fallible) programmer. We defend not adding operator overloading by stating that people will abuse it (FWIW, I agree with this mentality). And yet java (the language, not the VM!)'s current method of handling checked exceptions is geared towards the mythical perfectionist programmer! That makes no sense at all. I'll back up this point: #1: The JVM cannot, and does not, guarantee that the exceptions that fall out of a method call are only Errors, RuntimeExceptions, and any exception types declared by that method. That's simply not how the JVM works, and yet most java programmers erroneously think that it is. Being realistic for a moment, sneakyThrows occur all the time; you can have a class file mismatch (compiled against a different version of the class file vs. the version of that class file at runtime), you can be using a class compiled by scala, groovy, JRuby, Jython, or any other non-java programming language, or someone used a sneakyThrow method. Realistically, then, this isnt a philosophical change at all. We're just acknowledging something that already happened. #2: People get exception hierarchies wrong. All the time. The new String(bytes, encoding) constructor is flawed, for example. The right solution would be to have a Charset class and appropriate constructor that uses it (which string now has, since java 1.6, but the point to take home here is that the java core team it self, with all the lessons they knew by the time java 1.5 was developed, and with all that reviewed, still screwed it up), and preferably also a Charset.UTF8 constant, which java still doesn't have. Right now we have the weird situation that new String(bytes, "foo"); throws a checked exception, but new String(bytes, Charset.forName("foo")), which seems semantically equivalent, throws an unchecked exception. That cannot be the right design; we have it today because of the need for backwards compatibility. We must acknowledge that java's exception handling isn't perfect. There isn't even a proper definition of what constitutes a good situation for a checked exception, and what doesn't. Some people say that checked exceptions are appropriate only for legitimate alternative return values, where it would be a clear bug if a caller doesn't handle this code, in virtually all imaginable scenarios, such as an InsufficientBalanceException for a banking app's transferFundsFromPersonToPerson(Person A, Person B) method. In this view, IOException is mistyped (because there are whole hosts of situations where IOExceptions are either extremely unlikely, or likely, but there's nothing you can do - it is truly a program error and not an alternative return scenario; the only viable action is quitting, which an unchecked exception can do just as well). Then there's the view that a checked exception is appropriate anytime an exception is remotely likely to occur. In this view, Integer's parseInt's NumberFormatException is misclassed, because obviously non- numeric input is likely, and yet NFEx is unchecked. There is, in fact, no philosophy about checked and unchecked exceptions that would classify the various exceptions in the java core libraries the way they are in real life. It's a grab bag; some are checked, some are unchecked, and there's only a vague philosophy behind the choices. InputStream.close() throws a checked exception which most programmers find very questionable. Almost certainly a mistake, in practice (even if in theory it makes sense and is nicely symmetric with OutputStream's close, which does entirely appropriately throw IOException - at least as appopriate as write()'s throws clause). Proper use of the new String(bytes, encoding) constructor (where the input encoding is actually a variable and not a string literal) throws a checked exception, but Integer.parseInt() doesn't. yet, both are trying to parse a string where some forms are legal and some forms aren't. There's no reason for the dichotomy here; it's random. SQLException has only recently seen some work to make it a more usable construct, though the current situation amongst JDBC drivers remains troublesome. There are also many many mistakes that the entire exception hierarchy concept can make happen. Fine case in point: new String(bytes, "UUTF-8"); throws an UnsupportedEncodingException, which is a subclass of IOException. What, exactly, does this error have to do with I/O? Nothing whatsoever. The idea that UnsupportedEncodingException is a subclass of IOException is very questionable. We can also look at the other extreme and complain about the insane amount of exceptions that can fall out of reflection related calls. Bottomline: Let's be realistic - exception handling in java isn't perfect, and it never will be. Trying to protect people from abusing the throwing of exceptions by forcing rigid checked exception handling is a failed experiment, and the fact that just about every JVM language other than java itself doesn't have checked exceptions at all means we need a way to explicitly say to javac: I know better than you do, in this instance. Realistically, the number of situations where javac's advice is just wrong is formidable, and its making us write bad code. Mark, your proposal does indeed attempt to deal with this issue in a less philosophically drastic fashion, but I think the end result just isn't as good. Consider again Ruslan's typoed UUTF-8 example: If we wrap it, we're just hiding the cause behind a generic InternalError, AssertionError, or RuntimeException. I've seen them all. There's actually a decent unchecked alternative available (UnsupportedEncodingError) but that's the exception (heh, heh) rather than the rule. Sure, there's getCause(), but 'cause hell' is already causing stack traces nearing a hundred pages long, and a continuing unsolved problem in java land is finding the one cause in the massive onslaught that helps you get to real issue at hand. In this situation, the rewrap is needless noise in the exception chain. Without either your or my proposal, we get the worst of both worlds: We rethrow, adding noise to the runtime information, and we also add 4 to 5 lines of noise to the code with a semantically pointless try/ catch block that rethrows the UnsupportedEncodingEx into something else. --Reinier Zwitserloot Like it? Tip it! http://tipit.to From reinier at zwitserloot.com Wed May 20 06:35:18 2009 From: reinier at zwitserloot.com (Reinier Zwitserloot) Date: Wed, 20 May 2009 15:35:18 +0200 Subject: Checked Exceptions do not exist on the JVM. In-Reply-To: <988330f1d03fc629490d5dffa3fc2d25.squirrel@wmail.gradsoft.ua> References: <39084932-B2CC-4B91-97EA-006FE21301F0@googlemail.com> <4A1339ED.8090309@sun.com> <68BF955A-9796-44F7-9E97-94BBB43ADCC5@zwitserloot.com> <988330f1d03fc629490d5dffa3fc2d25.squirrel@wmail.gradsoft.ua> Message-ID: Ruslan, you've got it all wrong. Though, you've just proved to this list that java programmers don't really get this concept, which is one of the reasons why I want to introduce it: Make it obvious to java programmers that the JVM does *NOT* guarantee that checked exceptions are declared. Checked exceptions do not exist. That's right. They don't. There's no such thing. It's all a figment of javac. The JVM does not have checked exceptions. All it knows about is 'throws clauses', which are part of a method's signature and have ZERO impact on how a JVM runs a class file. As far as the JVM is concerned, throws clauses are just a comment. Utterly ignored by javac. You can strip every single one out of every class file and run an app, and the execution of it would be 100% the same. The only change would be in java.lang.reflect's getExceptionTypes() method. I repeat: The JVM *DOES* *NOT* know about checked exceptions. The JVM assumes all exceptions are unchecked, and assumes that javac sorted it all out. This is flawed, obviously, because javac isn't the only tool out there that can make class files. This is similar to generics in objects, which is also a figment of javac's imagination: On the JVM level, erasure occurs - that info just isn't there. If you want, you can name this 'checked exception erasure'. The notion that exceptions are checked is erased during compilation. The only application in existence that cares about this 'throws clauses' comment in class files is the application called 'javac'. Javac will refuse to compile a throws statement, or a call to a method that has a throws clause on it, unless this statement occurs in either a try block with the appropriate catch, or the method throws the exception onwards. So, let's revisit: If I take this code: public class Foo { public void foo() throws IOException { throw new IOException(); } } compile it with javac, then use a hex editor or ASM to remove the 'throws IOException' from the method signature, *nothing changes*. The Class Verifier will not complain. The JVM will just throw that exception; it won't get wrapped into an unchecked exception. It gets worse: JRuby, groovy, Jython, and scala, they ALL feature *ZERO* checked exception clauses on methods. They just generate class bytecode with throw statements without caring about the throws clause on methods. This is why, in java, anytime you interop with code not compiled by javac, you can get checked exceptions in situations where you didn't expect them. Millions of classes generated by those compilers are out there right now throwing checked exceptions that escape from methods that do NOT have a 'throws X' clause on them. In other words: There is *NO* guarantee whatsoever in the JVM that checked exceptions can only occur in situations where they are explicitly declared. If your code relies on it, then your code is buggy. Secondly, you mentioned that java wraps exceptions that occur in the constructor with Class.newInstance() into an ExceptionInInitializerError. That's not what happens at all; That exception (ExceptionInInitializerError) is for static initializers and object initializers, not constructors. A practical example will make this clear. Take the following code, save it in Foo.java, compile it, and run it: import java.io.IOException; public class Foo { public static class Test { public Test() throws IOException { throw new IOException(); } } //Note how I didn't add 'throws IOException' in the next line! public static void main(String[] args) throws InstantiationException, IllegalAccessException { Test x = Test.class.newInstance(); } } The result is an IOException. Not a ObjectInstantionException with an IOException as cause; no - an IOException. You can doublecheck this by wrapping the newInstance in a try/catch (Throwable t) block and printing the class name of the resulting t. Thirdly, you misunderstand what my ignoreslist proposal does: It does not silently swallow the exception, that'd be a very stupid way of handling exceptions that you don't -think- can occur. An ignoreslist has zero effect on the execution of a method body. The only difference is that, unlike a throws clause, you don't burden any of the methods that call you to handle the listed exception. It's a signal to javac to disable its rigid checking of making sure any checked exception thrown in the body is also present in that method's 'throws' clause. It's exactly analogous to adding the 'throws' clause, compiling the code, then using a hex editor to remove the throws clause. You're also mistaken in retrofitting Runnable with 'throws Exception': That'll break many thousands of classes out there in real life. You forget that people don't just make Runnables and hand them off to java.lang.Thread; there's plenty of code out there that *receives* Runnables, and that code presumes that its run() method does not throw any checked exceptions. It would be backwards compatible (because, as I said, the JVM doesn't know about these things), but it wouldn't be source compatible; recompiling your code would all of a sudden produce errors. e.g: public void myMethod(Runnable r) { r.run(); } would no longer compile, because all of a sudden 'r.run();' can throw Exception, which I need to catch, or declare as thrown (or, if this proposal is accepted, declare as sneakyThrown/ignore). --Reinier Zwitserloot On May 20, 2009, at 07:01, Ruslan Shevchenko wrote: >> Here's a trivially simple change to implement, though it has some far >> reaching repercussions for java as a whole: >> >> change the 'rethrows' clause to an ignores clause: Any checked >> exception in the ignores list may be thrown from the method body, but >> is NOT part of the method's checked exception list. It is hence also >> not part of the signature, just like sticking a 'synchronized' >> keyword >> on a method isn't part of its signature, but an implementation >> detail. >> >> >> example: >> >> Runnable r = new Runnable() { >> public void run() ignores UnsupportedEncodingException { >> String x = new String(inBytes, "UTF-8"); >> } >> }; >> > > And how actually debug such statements ? > //In this example, run() method do nothing, so look on slightly > complex > primer: > > class X > { > String x; > > public void setString(byte[] inBytes) > ignores UnsupportedEncodingException > { > x = new String(inBytes, "UUTF-8"); > } > > public void setAndPrintString(byte[] inBytes) > { > setString(inBytes); > System.out.println("received:"+x); > } > > > } > > Assume, that programmer wrote (by error) "UUTF-8" instead "UTF-8" > > Output of programm will be "received:null". > Reasons for null x in complex programs can be millions. Debugging with > ignoring exception will be extremally hard. > > I. e. wrapping checked exception to runtime is more or less normal; > ignoring will become a very big paint-point. > > Alternative to ignore can be call default thread exception handler. > (handle keyword ?) > >> This sounds like blowing up the entire point of checked exceptions, >> but with java moving towards more interoperation with other JVM based >> languages, which almost always throw checked exceptions without >> actually declaring them (Jython, JRuby, Scala -- I can't think of a >> single one other than java itself that has the notion of checked >> exceptions in the first place). If the whole 'java is like the >> assembler of the JVM' story is going to hold water, something like >> this is needed. >> > > Yes, this is interesting problem. > In theory we have UndeclaredThowableException, but .. wrapping each > invocation of foreign language into it is ineffecient. > > But InvokeDynamic can throws any throwable in declaration, so this > problem > can be solved (on other level) > >> For some further support: I doubt anyone seriously holds the position >> that java's checked exception experiment was an unmitigated success. >> There are pain points, here and there. The above example in fact >> includes two of them: The fact that runnable throws no checked >> exceptions is clearly a mistake in regards to threading, because >> Thread objects clearly should handle ANY exception falling out of its >> run() method (and it in fact does, via the unchecked exception >> handler >> mechanism), and there's a general mismatch between main(), which MAY >> throw exceptions, and run(), which may not, even though they are both >> 'thread start points'. Another mistake is > > Adding throw exception to signature of Runnable.run does not broke > anything in existent code, so this can be nice library change. > >> UnsupportedEncodingExceptions, a checked exception, resulting from a >> call to converting byte arrays to strings using an encoding that is >> guaranteed by the JVM using a string literal, such as "UTF-8". The >> appropriate exception would be UnsupportedEncodingError("This JVM is >> broken. Charset UTF-8 missing. Reinstall it") - which is unchecked. >> > > Or porgrammer can write UUTF-8 instead UTF-8. It's happens ;) > >> In other words, while I'm not ready to write off checked exceptions >> as >> a whole, I am more than ready to acknowledge that the programmer more >> often knows better than the compiler, compared to how often the >> programmer, in laziness or inexperience, abuses this freedom. >> Especially considering that, on the JVM, you really DONT get checked >> exceptions guarantees; any class compiled by anything other than >> javac >> is free to throw checked exceptions without declaring them, and even >> in javac you can technically do this using 'sneaky throw' libraries, >> which use various workarounds, one of which will NEVER go away*. >> We're >> not losing much here, in other words. In fact, the way javac works, >> inexperienced java programmers may erroneously assume that checked >> exceptions couldn't possibly happen unless the checked exception is >> declared. This is not the case. >> >> *) The one that will never go away is java.lang.Class.newInstance(), >> which is functionally defined to sneakily throw on any exceptions >> thrown by the constructor, checked or not, and does NOT wrap them up >> into a wrapper the way java.lang.reflect.Method.invoke() does. This > > Its wrapped to java.lang.ExceptionInInitializerError > > >> cannot change without breaking backwards compatibility. Another one >> that will never go away is constructing a class on the fly that >> sneaky >> throws, loading it with ClassLoader's load from bytes mechanism, and >> executing it. >> > > And what is JVM behaviour in such case ? > >> >> Attempting to solve this issue with a library requires rather a lot >> of >> ugly boilerplate: >> >> import static Utils.sneakyThrow; >> >> Runnable r = new Runnable() { >> public void run() { >> String x; >> try { >> x = new String(inBytes, "UTF-8"); >> } catch ( UnsupportedEncodingException e ) { >> sneakyThrow(e); >> } >> } >> }; >> >> >> NB: For sanity purposes, the restriction on javac that the try block >> MUST contain at least 1 statement that could throw a checked >> exception >> type that is listed on one of the accompanying catch blocks (other >> than Exception, which you can always catch), should go away; this has >> already been proposed before, and in fact is a backwards >> compatibility >> painpoint for the coin proposal that allows you to rethrow a final >> Exception as if its type is the intersection of all checked types >> thrown by the statements in the try body. >> >> --Reinier Zwitserloot >> Like it? Tip it! >> http://tipit.to >> >> >> >> On May 20, 2009, at 02:22, Mark Mahieu wrote: >> >>> Yeah, I suppose I did make it rather more complicated than it needed >>> to be. >>> >>> Thanks for the feedback. >>> >>> Mark >>> >>> >>> On 19 May 2009, at 23:59, Joe Darcy wrote: >>> >>>> Hello. >>>> >>>> Hmm; this strikes me as a bit involved for the potential benefits >>>> of the feature. >>>> >>>> -Joe >>>> >>>> On 03/30/09 05:04 PM, Mark Mahieu wrote: >>>>> Forgot my JLS references in the first one... >>>>> >>>>> >>>>> >>>>> HTML version + prototype available at: >>>>> >>>>> http://slm888.com >>>>> >>>>> >>>>> >>>>> >>>>> Rethrows Clause >>>>> v0.1.1 >>>>> >>>>> >>>>> AUTHOR(S): >>>>> >>>>> Mark Mahieu >>>>> >>>>> >>>>> OVERVIEW >>>>> >>>>> FEATURE SUMMARY: Should be suitable as a summary in a language >>>>> tutorial. >>>>> >>>>> A new clause on method declarations which allows exception >>>>> translations (wrapping and rethrowing as a different type) to be >>>>> cleanly defined separately from the body of the method. In many >>>>> cases, checked exception type names do not then need to be >>>>> repeated in a method's throws clause and in a throw statement in >>>>> the method body. >>>>> >>>>> >>>>> MAJOR ADVANTAGE: What makes the proposal a favorable change? >>>>> >>>>> The proposal adds direct support for a common idiom in daily use >>>>> by Java programmers worldwide, allowing them to express their >>>>> intentions with greater clarity and ease. In comparison with >>>>> some proposals, this is an attempt to make dealing with checked >>>>> exceptions easier by increasing the expressiveness of exception >>>>> handling code in general, rather than by attempting to deprecate >>>>> checked exceptions in favour of unchecked exceptions. >>>>> >>>>> >>>>> MAJOR BENEFIT: Why is the platform better if the proposal is >>>>> adopted? >>>>> >>>>> There is a reduction in the amount of boilerplate Java >>>>> programmers have to read and write for code dealing with checked >>>>> exceptions. Declarations specifying both thrown and rethrown >>>>> (wrapped) exceptions are kept together, aiding comprehension of >>>>> the code. >>>>> >>>>> >>>>> MAJOR DISADVANTAGE: There is always a cost. >>>>> >>>>> As with any syntax sugar which enables an alternative way of >>>>> expressing an existing idiom, programmers may be tempted to use >>>>> it even when the existing idiom would be more appropriate. >>>>> >>>>> >>>>> ALTERNATIVES: Can the benefits and advantages be had some way >>>>> without a language change? >>>>> >>>>> No. >>>>> >>>>> >>>>> EXAMPLES >>>>> >>>>> SIMPLE EXAMPLE: Show the simplest possible program utilizing the >>>>> new feature. >>>>> >>>>> >>>>> Before: >>>>> >>>>> void before() throws ConfigException { >>>>> try { >>>>> Class.forName("where.is.the.Code"); >>>>> } >>>>> catch (ClassNotFoundException e) { >>>>> throw new ConfigException(e); >>>>> } >>>>> } >>>>> >>>>> After: >>>>> >>>>> void after() >>>>> catch ClassNotFoundException throw ConfigException { >>>>> >>>>> Class.forName("here.is.the.Code"); >>>>> } >>>>> >>>>> >>>>> ADVANCED EXAMPLE: Show advanced usage(s) of the feature. >>>>> >>>>> Before: >>>>> >>>>> void suspendAccount() >>>>> throws AuthorizationException, >>>>> PersistenceException { >>>>> try { >>>>> checkMyAuthoritah(); >>>>> db.update(/*...*/); >>>>> log.recordInfo(/*...*/); >>>>> } >>>>> catch (InfernalDBException e) { >>>>> throw new PersistenceException(e); >>>>> } >>>>> catch (InfernalLogException e) { >>>>> throw new RuntimeException(e); >>>>> } >>>>> } >>>>> >>>>> After: >>>>> >>>>> void suspendAccount() >>>>> throws AuthorizationException >>>>> catch InfernalDBException throw PersistenceException, >>>>> InfernalLogException throw RuntimeException { >>>>> >>>>> checkMyAuthoritah(); >>>>> db.update(/*...*/); >>>>> log.recordInfo(/*...*/); >>>>> } >>>>> >>>>> >>>>> DETAILS >>>>> >>>>> SPECIFICATION: Describe how the proposal affects the grammar, >>>>> type system, and meaning of expressions and statements in the >>>>> Java Programming Language as well as any other known impacts. >>>>> >>>>> The syntactic grammar is modified to allow an optional rethrows >>>>> clause immediately prior to a MethodBody: >>>>> >>>>> MethodDeclaratorRest: >>>>> FormalParameters {[]} [throws >>>>> QualifiedIdentifierList] ( ( [catch ExceptionTranslationList] >>>>> MethodBody ) | ; ) >>>>> >>>>> ExceptionTranslationList: >>>>> QualifiedIdentifier throw QualifiedIdentifier >>>>> { , ExceptionTranslationList } >>>>> >>>>> >>>>> >>>>> JLSv3 ?8.4.6 : A rethrows clause lists one or more exception >>>>> translations, each translation consisting of a caught type C and >>>>> a translated type T for which all of the following must hold: >>>>> * C <: java.lang.Exception >>>>> * T < java.lang.Throwable >>>>> * Neither C nor T is a type variable. >>>>> * T has an accessible constructor suitable for rethrowing a >>>>> value of type C (see below). >>>>> * T is not the same type as C. >>>>> >>>>> Any exceptions thrown by the method body which are a subtype of a >>>>> caught exception type in the rethrows clause, are rethrown as the >>>>> corresponding translated exception type. >>>>> >>>>> For a given translated type T with corresponding caught type C, if >>>>> T has an accessible constructor accepting a value of type C, then >>>>> the translation is equivalent to the following: >>>>> >>>>> catch (C e) { >>>>> throw new T(e); >>>>> } >>>>> >>>>> Otherwise it must have an accessible no argument constructor, and >>>>> the translation is equivalent to: >>>>> >>>>> catch (C e) { >>>>> throw new T().initCause(e); >>>>> } >>>>> >>>>> >>>>> A rethrows clause does not restrict which types may appear in a >>>>> throws clause for the same method. In particular, for a given >>>>> caught type C in the rethrows clause, it is permitted for some >>>>> type C1 :> C to also be listed in the throws clause. >>>>> >>>>> >>>>> JLSv3 ?8.2 : The set of exception types declared to be thrown by >>>>> a method is the union of: >>>>> * the types in the throws clause >>>>> * the translated types in the rethrow clause >>>>> * the types thrown by the translated types' selected >>>>> constructors >>>>> >>>>> JLSv3 ?11.2.2 : For the purposes of exception analysis, the set >>>>> of checked exception types which may be thrown by the method's >>>>> body is the union of: >>>>> * the types in the throws clause >>>>> * the caught types in the rethrows clause >>>>> >>>>> JLSv3 ?11.2.3 : It is a compile-time error if a rethrows clause >>>>> contains a translation from a checked exception type C but there >>>>> exists no checked exception type E such that all of the following >>>>> hold: >>>>> * E <: C >>>>> * The method body can throw E >>>>> * No preceding translation in the rethrow clause catches E or >>>>> a supertype of E >>>>> unless C is the class java.lang.Exception. >>>>> >>>>> JLSv3 ?13.4.21 : Changes to the rethrows clause of methods or >>>>> constructors do not break compatibility with existing binaries; >>>>> these clauses are checked only at compile time. >>>>> >>>>> >>>>> >>>>> COMPILATION: How would the feature be compiled to class files? >>>>> Show how the simple and advanced examples would be compiled. >>>>> Compilation can be expressed as at least one of a desugaring to >>>>> existing source constructs and a translation down to bytecode. If >>>>> a new bytecode is used or the semantics of an existing bytecode >>>>> are changed, describe those changes, including how they impact >>>>> verification. Also discuss any new class file attributes that are >>>>> introduced. Note that there are many downstream tools that >>>>> consume class files and that they may to be updated to support >>>>> the proposal! >>>>> >>>>> A simple desugaring could consist of enclosing the method body's >>>>> statements in a try statement, with catch clauses for each >>>>> translated exception type. For example, the following method: >>>>> >>>>> Method findMethod() >>>>> catch ClassNotFoundException throw ConfigException, >>>>> NoSuchMethodException throw ConfigException { >>>>> >>>>> Class c = Class.forName("some.Thing"); >>>>> return c.getDeclaredMethod("execute", null); >>>>> } >>>>> >>>>> would be desugared to: >>>>> >>>>> Method findMethod() >>>>> throws ConfigException { >>>>> try { >>>>> Class c = Class.forName("some.Thing"); >>>>> return c.getDeclaredMethod("execute", null); >>>>> } >>>>> catch (ClassNotFoundException e) { >>>>> throw new ConfigException(e); >>>>> } >>>>> catch (MethodNotFoundException e) { >>>>> throw new ConfigException(e); >>>>> } >>>>> } >>>>> >>>>> No changes to the classfile format are required. >>>>> >>>>> >>>>> TESTING: How can the feature be tested? >>>>> >>>>> An initial set of jtreg tests is included in the prototype. >>>>> >>>>> >>>>> LIBRARY SUPPORT: Are any supporting libraries needed for the >>>>> feature? >>>>> >>>>> No >>>>> >>>>> >>>>> REFLECTIVE APIS: Do any of the various and sundry reflection APIs >>>>> need to be updated? This list of reflective APIs includes but is >>>>> not limited to core reflection (java.lang.Class and >>>>> java.lang.reflect.*), javax.lang.model.*, the doclet API, and >>>>> JPDA. >>>>> >>>>> com.sun.source.tree.MethodTree would require updates to access >>>>> the rethrows clause's caught and translated types. >>>>> >>>>> >>>>> OTHER CHANGES: Do any other parts of the platform need be updated >>>>> too? Possibilities include but are not limited to JNI, >>>>> serialization, and output of the javadoc tool. >>>>> >>>>> No >>>>> >>>>> >>>>> MIGRATION: Sketch how a code base could be converted, manually or >>>>> automatically, to use the new feature. >>>>> >>>>> Catch clauses which simply wrap and rethrow an exception as >>>>> another exception type not caught in an enclosing scope, can be >>>>> trivially replaced with a rethrows clause, either manually or >>>>> automatically. >>>>> >>>>> It should be possible for tools to offer bidirectional >>>>> conversions such that an exception translation may be moved back >>>>> into the method body if it is subsequently decided that >>>>> additional logic is required. >>>>> >>>>> >>>>> COMPATIBILITY >>>>> >>>>> BREAKING CHANGES: Are any previously valid programs now invalid? >>>>> If so, list one. >>>>> >>>>> No >>>>> >>>>> >>>>> EXISTING PROGRAMS: How do source and class files of earlier >>>>> platform versions interact with the feature? Can any new >>>>> overloadings occur? Can any new overriding occur? >>>>> >>>>> The semantics of existing class files and legal source files are >>>>> unchanged by this feature. >>>>> >>>>> >>>>> REFERENCES >>>>> >>>>> EXISTING BUGS: Please include a list of any existing Sun bug ids >>>>> related to this proposal. >>>>> >>>>> http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6534270 >>>>> (similar, but emphasizes unchecked exceptions) >>>>> >>>>> >>>>> URL FOR PROTOTYPE (optional): >>>>> >>>>> http://slm888.com/javac >>>>> >>>>> >>>>> >>>> >>> >>> >> >> >> > > From forax at univ-mlv.fr Wed May 20 08:02:46 2009 From: forax at univ-mlv.fr (=?ISO-8859-1?Q?R=E9mi_Forax?=) Date: Wed, 20 May 2009 17:02:46 +0200 Subject: The 'ignoreslist' exception handling proposal. In-Reply-To: References: Message-ID: <4A141B96.2070708@univ-mlv.fr> Reiner, the problem is not new String(byte, Charset) but the fact that Charset.forName() doesn't use a checked exception. The philosophy behind exception is: - If it's a developer mistake, it's a runtime exception - If it's an error that comes form outside the Java platform, i.e an error that can not be predicted without some elements from outside the Java platform, it's a checked exception. Depending on the installation, some Charsets are available or not, this is clearly an error that comes form outside of Java world so it should be handled with a checked exception. Ok, it's a mistake but I don't understand how it's related to your proposal ? R?mi Reinier Zwitserloot a ?crit : > I'm more convinced than ever that java really needs this change, > sooner rather than later. > > My arguments in favour: > > 1. Ruslan totally misunderstood my proposal, and also appears to > misunderstand checked exceptions on the JVM level in general. This is > in my experience an extremely common problem amongst java programmers, > and this is very bad news for trying to interop javac-produced class > files with scalac, groovy, JRuby, Python, and other languages' class > files. By adding the concept of sneakyThrow to java, we teach java > programmers that checked exceptions are only a debugging aid offered > by javac, and NOT a guarantee by the JVM. This isn't a philosophical > change at all: It's realism. In today's JVM world, you just cannot > rely on that as a java programmer, and yet most java programmers do. > > NB: Ruslan and everyone else that's confused - I'll send an > explanatory email in a few minutes to explain how it all works. > > 2. Joe Darcy, project coin, and sun routinely defend choices for the > java platform by stating that java is designed for the realistic, > human (e.g. fallible) programmer. We defend not adding operator > overloading by stating that people will abuse it (FWIW, I agree with > this mentality). And yet java (the language, not the VM!)'s current > method of handling checked exceptions is geared towards the mythical > perfectionist programmer! That makes no sense at all. I'll back up > this point: > > > #1: The JVM cannot, and does not, guarantee that the exceptions that > fall out of a method call are only Errors, RuntimeExceptions, and any > exception types declared by that method. That's simply not how the JVM > works, and yet most java programmers erroneously think that it is. > Being realistic for a moment, sneakyThrows occur all the time; you can > have a class file mismatch (compiled against a different version of > the class file vs. the version of that class file at runtime), you can > be using a class compiled by scala, groovy, JRuby, Jython, or any > other non-java programming language, or someone used a sneakyThrow > method. > > Realistically, then, this isnt a philosophical change at all. We're > just acknowledging something that already happened. > > #2: People get exception hierarchies wrong. All the time. The new > String(bytes, encoding) constructor is flawed, for example. The right > solution would be to have a Charset class and appropriate constructor > that uses it (which string now has, since java 1.6, but the point to > take home here is that the java core team it self, with all the > lessons they knew by the time java 1.5 was developed, and with all > that reviewed, still screwed it up), and preferably also a > Charset.UTF8 constant, which java still doesn't have. Right now we > have the weird situation that new String(bytes, "foo"); throws a > checked exception, but new String(bytes, Charset.forName("foo")), > which seems semantically equivalent, throws an unchecked exception. > That cannot be the right design; we have it today because of the need > for backwards compatibility. We must acknowledge that java's exception > handling isn't perfect. > > There isn't even a proper definition of what constitutes a good > situation for a checked exception, and what doesn't. Some people say > that checked exceptions are appropriate only for legitimate > alternative return values, where it would be a clear bug if a caller > doesn't handle this code, in virtually all imaginable scenarios, such > as an InsufficientBalanceException for a banking app's > transferFundsFromPersonToPerson(Person A, Person B) method. In this > view, IOException is mistyped (because there are whole hosts of > situations where IOExceptions are either extremely unlikely, or > likely, but there's nothing you can do - it is truly a program error > and not an alternative return scenario; the only viable action is > quitting, which an unchecked exception can do just as well). Then > there's the view that a checked exception is appropriate anytime an > exception is remotely likely to occur. In this view, Integer's > parseInt's NumberFormatException is misclassed, because obviously non- > numeric input is likely, and yet NFEx is unchecked. > > There is, in fact, no philosophy about checked and unchecked > exceptions that would classify the various exceptions in the java core > libraries the way they are in real life. It's a grab bag; some are > checked, some are unchecked, and there's only a vague philosophy > behind the choices. > > InputStream.close() throws a checked exception which most programmers > find very questionable. Almost certainly a mistake, in practice (even > if in theory it makes sense and is nicely symmetric with > OutputStream's close, which does entirely appropriately throw > IOException - at least as appopriate as write()'s throws clause). > > Proper use of the new String(bytes, encoding) constructor (where the > input encoding is actually a variable and not a string literal) throws > a checked exception, but Integer.parseInt() doesn't. yet, both are > trying to parse a string where some forms are legal and some forms > aren't. There's no reason for the dichotomy here; it's random. > > SQLException has only recently seen some work to make it a more usable > construct, though the current situation amongst JDBC drivers remains > troublesome. There are also many many mistakes that the entire > exception hierarchy concept can make happen. Fine case in point: > > new String(bytes, "UUTF-8"); throws an UnsupportedEncodingException, > which is a subclass of IOException. What, exactly, does this error > have to do with I/O? Nothing whatsoever. The idea that > UnsupportedEncodingException is a subclass of IOException is very > questionable. > > We can also look at the other extreme and complain about the insane > amount of exceptions that can fall out of reflection related calls. > > Bottomline: Let's be realistic - exception handling in java isn't > perfect, and it never will be. Trying to protect people from abusing > the throwing of exceptions by forcing rigid checked exception handling > is a failed experiment, and the fact that just about every JVM > language other than java itself doesn't have checked exceptions at all > means we need a way to explicitly say to javac: I know better than you > do, in this instance. Realistically, the number of situations where > javac's advice is just wrong is formidable, and its making us write > bad code. > > > Mark, your proposal does indeed attempt to deal with this issue in a > less philosophically drastic fashion, but I think the end result just > isn't as good. Consider again Ruslan's typoed UUTF-8 example: > > If we wrap it, we're just hiding the cause behind a generic > InternalError, AssertionError, or RuntimeException. I've seen them > all. There's actually a decent unchecked alternative available > (UnsupportedEncodingError) but that's the exception (heh, heh) rather > than the rule. Sure, there's getCause(), but 'cause hell' is already > causing stack traces nearing a hundred pages long, and a continuing > unsolved problem in java land is finding the one cause in the massive > onslaught that helps you get to real issue at hand. In this situation, > the rewrap is needless noise in the exception chain. > > Without either your or my proposal, we get the worst of both worlds: > We rethrow, adding noise to the runtime information, and we also add 4 > to 5 lines of noise to the code with a semantically pointless try/ > catch block that rethrows the UnsupportedEncodingEx into something else. > > --Reinier Zwitserloot > Like it? Tip it! > http://tipit.to > > > > > From tball at google.com Wed May 20 09:11:48 2009 From: tball at google.com (Tom Ball) Date: Wed, 20 May 2009 09:11:48 -0700 Subject: Checked Exceptions do not exist on the JVM. In-Reply-To: References: <39084932-B2CC-4B91-97EA-006FE21301F0@googlemail.com> <4A1339ED.8090309@sun.com> <68BF955A-9796-44F7-9E97-94BBB43ADCC5@zwitserloot.com> <988330f1d03fc629490d5dffa3fc2d25.squirrel@wmail.gradsoft.ua> Message-ID: On Wed, May 20, 2009 at 6:35 AM, Reinier Zwitserloot < reinier at zwitserloot.com> wrote: > Checked exceptions do not exist. Sure they do, but they are a Java language concept, not a JVM one. The same is true for lots of other Java language features. That's right. They don't. There's no such thing. It's all a figment of > javac. You must mean that checked exceptions are defined by the Java Language Specification. javac is just a compiler that adheres to the JLS, like many other Java compilers. > The JVM does not have checked exceptions. All it knows about is > 'throws clauses', which are part of a method's signature and have ZERO > impact on how a JVM runs a class file. As far as the JVM is concerned, > throws clauses are just a comment. Utterly ignored by javac. No compiler can ignore the throws part of a method signature and be a valid Java language compiler. Having worked on javac, I know for a fact that whether a class symbol is read from a source or class file, its methods include all defined throws clauses and enforces their use as the JLS dictates. The javac source is publicly available -- check out the Symbol and ClassReader classes. > You can > strip every single one out of every class file and run an app, and the > execution of it would be 100% the same. The only change would be in > java.lang.reflect's getExceptionTypes() method. > > I repeat: The JVM *DOES* *NOT* know about checked exceptions. The JVM > assumes all exceptions are unchecked, and assumes that javac sorted it > all out. This is flawed, obviously, because javac isn't the only tool > out there that can make class files. Flawed? The Java Language and the JVM have different specifications; the JLS defines checked exceptions, and the JVMS doesn't. The JVM support many different languages besides Java, most of whom don't define checked exceptions. That's not a flaw, but support for language independence. The reason the JVM considers all exceptions as runtime exceptions is because it's the runtime. > This is similar to generics in > objects, which is also a figment of javac's imagination: On the JVM > level, erasure occurs - that info just isn't there. If you want, you > can name this 'checked exception erasure'. The notion that exceptions > are checked is erased during compilation. Not true. Yes, the JVM doesn't support generics, but classfiles contain all information needed to correctly compile classes which use them. The same is true for exceptions, as the JLS requires. > The only application in existence that cares about this 'throws > clauses' comment in class files is the application called 'javac'. You are going to make engineers support other Java compilers upset with this incorrect assumption. They all have to support checked exceptions, or they aren't Java compilers. It gets worse: JRuby, groovy, Jython, and scala, they ALL feature > *ZERO* checked exception clauses on methods. They just generate class > bytecode with throw statements without caring about the throws clause > on methods. Worse? Different languages make different trade-offs between compile and runtime checking, and it's a matter of personal preference what trade-offs you want. There is no "better" or "worse", which is why the JVM doesn't require one or the other. > This is why, in java, anytime you interop with code not > compiled by javac, you can get checked exceptions in situations where > you didn't expect them. WTF? If you are calling libraries written in other languages, those libraries throw exceptions as defined by their language specifications. If you don't like the contracts of those libraries, don't use them. I give up, Tom > Millions of classes generated by those > compilers are out there right now throwing checked exceptions that > escape from methods that do NOT have a 'throws X' clause on them. > > In other words: There is *NO* guarantee whatsoever in the JVM that > checked exceptions can only occur in situations where they are > explicitly declared. If your code relies on it, then your code is buggy. > > > Secondly, you mentioned that java wraps exceptions that occur in the > constructor with Class.newInstance() into an > ExceptionInInitializerError. That's not what happens at all; That > exception (ExceptionInInitializerError) is for static initializers and > object initializers, not constructors. A practical example will make > this clear. Take the following code, save it in Foo.java, compile it, > and run it: > > import java.io.IOException; > > public class Foo { > public static class Test { > public Test() throws IOException { > throw new IOException(); > } > } > > //Note how I didn't add 'throws IOException' in the next line! > public static void main(String[] args) throws > InstantiationException, IllegalAccessException { > Test x = Test.class.newInstance(); > } > } > > > The result is an IOException. Not a ObjectInstantionException with an > IOException as cause; no - an IOException. You can doublecheck this > by wrapping the newInstance in a try/catch (Throwable t) block and > printing the class name of the resulting t. > > Thirdly, you misunderstand what my ignoreslist proposal does: It does > not silently swallow the exception, that'd be a very stupid way of > handling exceptions that you don't -think- can occur. An ignoreslist > has zero effect on the execution of a method body. The only difference > is that, unlike a throws clause, you don't burden any of the methods > that call you to handle the listed exception. It's a signal to javac > to disable its rigid checking of making sure any checked exception > thrown in the body is also present in that method's 'throws' clause. > It's exactly analogous to adding the 'throws' clause, compiling the > code, then using a hex editor to remove the throws clause. > > > You're also mistaken in retrofitting Runnable with 'throws Exception': > That'll break many thousands of classes out there in real life. You > forget that people don't just make Runnables and hand them off to > java.lang.Thread; there's plenty of code out there that *receives* > Runnables, and that code presumes that its run() method does not throw > any checked exceptions. It would be backwards compatible (because, as > I said, the JVM doesn't know about these things), but it wouldn't be > source compatible; recompiling your code would all of a sudden produce > errors. e.g: > > public void myMethod(Runnable r) { > r.run(); > } > > would no longer compile, because all of a sudden 'r.run();' can throw > Exception, which I need to catch, or declare as thrown (or, if this > proposal is accepted, declare as sneakyThrown/ignore). > > > --Reinier Zwitserloot > > > > On May 20, 2009, at 07:01, Ruslan Shevchenko wrote: > > >> Here's a trivially simple change to implement, though it has some far > >> reaching repercussions for java as a whole: > >> > >> change the 'rethrows' clause to an ignores clause: Any checked > >> exception in the ignores list may be thrown from the method body, but > >> is NOT part of the method's checked exception list. It is hence also > >> not part of the signature, just like sticking a 'synchronized' > >> keyword > >> on a method isn't part of its signature, but an implementation > >> detail. > >> > >> > >> example: > >> > >> Runnable r = new Runnable() { > >> public void run() ignores UnsupportedEncodingException { > >> String x = new String(inBytes, "UTF-8"); > >> } > >> }; > >> > > > > And how actually debug such statements ? > > //In this example, run() method do nothing, so look on slightly > > complex > > primer: > > > > class X > > { > > String x; > > > > public void setString(byte[] inBytes) > > ignores UnsupportedEncodingException > > { > > x = new String(inBytes, "UUTF-8"); > > } > > > > public void setAndPrintString(byte[] inBytes) > > { > > setString(inBytes); > > System.out.println("received:"+x); > > } > > > > > > } > > > > Assume, that programmer wrote (by error) "UUTF-8" instead "UTF-8" > > > > Output of programm will be "received:null". > > Reasons for null x in complex programs can be millions. Debugging with > > ignoring exception will be extremally hard. > > > > I. e. wrapping checked exception to runtime is more or less normal; > > ignoring will become a very big paint-point. > > > > Alternative to ignore can be call default thread exception handler. > > (handle keyword ?) > > > >> This sounds like blowing up the entire point of checked exceptions, > >> but with java moving towards more interoperation with other JVM based > >> languages, which almost always throw checked exceptions without > >> actually declaring them (Jython, JRuby, Scala -- I can't think of a > >> single one other than java itself that has the notion of checked > >> exceptions in the first place). If the whole 'java is like the > >> assembler of the JVM' story is going to hold water, something like > >> this is needed. > >> > > > > Yes, this is interesting problem. > > In theory we have UndeclaredThowableException, but .. wrapping each > > invocation of foreign language into it is ineffecient. > > > > But InvokeDynamic can throws any throwable in declaration, so this > > problem > > can be solved (on other level) > > > >> For some further support: I doubt anyone seriously holds the position > >> that java's checked exception experiment was an unmitigated success. > >> There are pain points, here and there. The above example in fact > >> includes two of them: The fact that runnable throws no checked > >> exceptions is clearly a mistake in regards to threading, because > >> Thread objects clearly should handle ANY exception falling out of its > >> run() method (and it in fact does, via the unchecked exception > >> handler > >> mechanism), and there's a general mismatch between main(), which MAY > >> throw exceptions, and run(), which may not, even though they are both > >> 'thread start points'. Another mistake is > > > > Adding throw exception to signature of Runnable.run does not broke > > anything in existent code, so this can be nice library change. > > > >> UnsupportedEncodingExceptions, a checked exception, resulting from a > >> call to converting byte arrays to strings using an encoding that is > >> guaranteed by the JVM using a string literal, such as "UTF-8". The > >> appropriate exception would be UnsupportedEncodingError("This JVM is > >> broken. Charset UTF-8 missing. Reinstall it") - which is unchecked. > >> > > > > Or porgrammer can write UUTF-8 instead UTF-8. It's happens ;) > > > >> In other words, while I'm not ready to write off checked exceptions > >> as > >> a whole, I am more than ready to acknowledge that the programmer more > >> often knows better than the compiler, compared to how often the > >> programmer, in laziness or inexperience, abuses this freedom. > >> Especially considering that, on the JVM, you really DONT get checked > >> exceptions guarantees; any class compiled by anything other than > >> javac > >> is free to throw checked exceptions without declaring them, and even > >> in javac you can technically do this using 'sneaky throw' libraries, > >> which use various workarounds, one of which will NEVER go away*. > >> We're > >> not losing much here, in other words. In fact, the way javac works, > >> inexperienced java programmers may erroneously assume that checked > >> exceptions couldn't possibly happen unless the checked exception is > >> declared. This is not the case. > >> > >> *) The one that will never go away is java.lang.Class.newInstance(), > >> which is functionally defined to sneakily throw on any exceptions > >> thrown by the constructor, checked or not, and does NOT wrap them up > >> into a wrapper the way java.lang.reflect.Method.invoke() does. This > > > > Its wrapped to java.lang.ExceptionInInitializerError > > > > > >> cannot change without breaking backwards compatibility. Another one > >> that will never go away is constructing a class on the fly that > >> sneaky > >> throws, loading it with ClassLoader's load from bytes mechanism, and > >> executing it. > >> > > > > And what is JVM behaviour in such case ? > > > >> > >> Attempting to solve this issue with a library requires rather a lot > >> of > >> ugly boilerplate: > >> > >> import static Utils.sneakyThrow; > >> > >> Runnable r = new Runnable() { > >> public void run() { > >> String x; > >> try { > >> x = new String(inBytes, "UTF-8"); > >> } catch ( UnsupportedEncodingException e ) { > >> sneakyThrow(e); > >> } > >> } > >> }; > >> > >> > >> NB: For sanity purposes, the restriction on javac that the try block > >> MUST contain at least 1 statement that could throw a checked > >> exception > >> type that is listed on one of the accompanying catch blocks (other > >> than Exception, which you can always catch), should go away; this has > >> already been proposed before, and in fact is a backwards > >> compatibility > >> painpoint for the coin proposal that allows you to rethrow a final > >> Exception as if its type is the intersection of all checked types > >> thrown by the statements in the try body. > >> > >> --Reinier Zwitserloot > >> Like it? Tip it! > >> http://tipit.to > >> > >> > >> > >> On May 20, 2009, at 02:22, Mark Mahieu wrote: > >> > >>> Yeah, I suppose I did make it rather more complicated than it needed > >>> to be. > >>> > >>> Thanks for the feedback. > >>> > >>> Mark > >>> > >>> > >>> On 19 May 2009, at 23:59, Joe Darcy wrote: > >>> > >>>> Hello. > >>>> > >>>> Hmm; this strikes me as a bit involved for the potential benefits > >>>> of the feature. > >>>> > >>>> -Joe > >>>> > >>>> On 03/30/09 05:04 PM, Mark Mahieu wrote: > >>>>> Forgot my JLS references in the first one... > >>>>> > >>>>> > >>>>> > >>>>> HTML version + prototype available at: > >>>>> > >>>>> http://slm888.com > >>>>> > >>>>> > >>>>> > >>>>> > >>>>> Rethrows Clause > >>>>> v0.1.1 > >>>>> > >>>>> > >>>>> AUTHOR(S): > >>>>> > >>>>> Mark Mahieu > >>>>> > >>>>> > >>>>> OVERVIEW > >>>>> > >>>>> FEATURE SUMMARY: Should be suitable as a summary in a language > >>>>> tutorial. > >>>>> > >>>>> A new clause on method declarations which allows exception > >>>>> translations (wrapping and rethrowing as a different type) to be > >>>>> cleanly defined separately from the body of the method. In many > >>>>> cases, checked exception type names do not then need to be > >>>>> repeated in a method's throws clause and in a throw statement in > >>>>> the method body. > >>>>> > >>>>> > >>>>> MAJOR ADVANTAGE: What makes the proposal a favorable change? > >>>>> > >>>>> The proposal adds direct support for a common idiom in daily use > >>>>> by Java programmers worldwide, allowing them to express their > >>>>> intentions with greater clarity and ease. In comparison with > >>>>> some proposals, this is an attempt to make dealing with checked > >>>>> exceptions easier by increasing the expressiveness of exception > >>>>> handling code in general, rather than by attempting to deprecate > >>>>> checked exceptions in favour of unchecked exceptions. > >>>>> > >>>>> > >>>>> MAJOR BENEFIT: Why is the platform better if the proposal is > >>>>> adopted? > >>>>> > >>>>> There is a reduction in the amount of boilerplate Java > >>>>> programmers have to read and write for code dealing with checked > >>>>> exceptions. Declarations specifying both thrown and rethrown > >>>>> (wrapped) exceptions are kept together, aiding comprehension of > >>>>> the code. > >>>>> > >>>>> > >>>>> MAJOR DISADVANTAGE: There is always a cost. > >>>>> > >>>>> As with any syntax sugar which enables an alternative way of > >>>>> expressing an existing idiom, programmers may be tempted to use > >>>>> it even when the existing idiom would be more appropriate. > >>>>> > >>>>> > >>>>> ALTERNATIVES: Can the benefits and advantages be had some way > >>>>> without a language change? > >>>>> > >>>>> No. > >>>>> > >>>>> > >>>>> EXAMPLES > >>>>> > >>>>> SIMPLE EXAMPLE: Show the simplest possible program utilizing the > >>>>> new feature. > >>>>> > >>>>> > >>>>> Before: > >>>>> > >>>>> void before() throws ConfigException { > >>>>> try { > >>>>> Class.forName("where.is.the.Code"); > >>>>> } > >>>>> catch (ClassNotFoundException e) { > >>>>> throw new ConfigException(e); > >>>>> } > >>>>> } > >>>>> > >>>>> After: > >>>>> > >>>>> void after() > >>>>> catch ClassNotFoundException throw ConfigException { > >>>>> > >>>>> Class.forName("here.is.the.Code"); > >>>>> } > >>>>> > >>>>> > >>>>> ADVANCED EXAMPLE: Show advanced usage(s) of the feature. > >>>>> > >>>>> Before: > >>>>> > >>>>> void suspendAccount() > >>>>> throws AuthorizationException, > >>>>> PersistenceException { > >>>>> try { > >>>>> checkMyAuthoritah(); > >>>>> db.update(/*...*/); > >>>>> log.recordInfo(/*...*/); > >>>>> } > >>>>> catch (InfernalDBException e) { > >>>>> throw new PersistenceException(e); > >>>>> } > >>>>> catch (InfernalLogException e) { > >>>>> throw new RuntimeException(e); > >>>>> } > >>>>> } > >>>>> > >>>>> After: > >>>>> > >>>>> void suspendAccount() > >>>>> throws AuthorizationException > >>>>> catch InfernalDBException throw PersistenceException, > >>>>> InfernalLogException throw RuntimeException { > >>>>> > >>>>> checkMyAuthoritah(); > >>>>> db.update(/*...*/); > >>>>> log.recordInfo(/*...*/); > >>>>> } > >>>>> > >>>>> > >>>>> DETAILS > >>>>> > >>>>> SPECIFICATION: Describe how the proposal affects the grammar, > >>>>> type system, and meaning of expressions and statements in the > >>>>> Java Programming Language as well as any other known impacts. > >>>>> > >>>>> The syntactic grammar is modified to allow an optional rethrows > >>>>> clause immediately prior to a MethodBody: > >>>>> > >>>>> MethodDeclaratorRest: > >>>>> FormalParameters {[]} [throws > >>>>> QualifiedIdentifierList] ( ( [catch ExceptionTranslationList] > >>>>> MethodBody ) | ; ) > >>>>> > >>>>> ExceptionTranslationList: > >>>>> QualifiedIdentifier throw QualifiedIdentifier > >>>>> { , ExceptionTranslationList } > >>>>> > >>>>> > >>>>> > >>>>> JLSv3 ?8.4.6 : A rethrows clause lists one or more exception > >>>>> translations, each translation consisting of a caught type C and > >>>>> a translated type T for which all of the following must hold: > >>>>> * C <: java.lang.Exception > >>>>> * T < java.lang.Throwable > >>>>> * Neither C nor T is a type variable. > >>>>> * T has an accessible constructor suitable for rethrowing a > >>>>> value of type C (see below). > >>>>> * T is not the same type as C. > >>>>> > >>>>> Any exceptions thrown by the method body which are a subtype of a > >>>>> caught exception type in the rethrows clause, are rethrown as the > >>>>> corresponding translated exception type. > >>>>> > >>>>> For a given translated type T with corresponding caught type C, if > >>>>> T has an accessible constructor accepting a value of type C, then > >>>>> the translation is equivalent to the following: > >>>>> > >>>>> catch (C e) { > >>>>> throw new T(e); > >>>>> } > >>>>> > >>>>> Otherwise it must have an accessible no argument constructor, and > >>>>> the translation is equivalent to: > >>>>> > >>>>> catch (C e) { > >>>>> throw new T().initCause(e); > >>>>> } > >>>>> > >>>>> > >>>>> A rethrows clause does not restrict which types may appear in a > >>>>> throws clause for the same method. In particular, for a given > >>>>> caught type C in the rethrows clause, it is permitted for some > >>>>> type C1 :> C to also be listed in the throws clause. > >>>>> > >>>>> > >>>>> JLSv3 ?8.2 : The set of exception types declared to be thrown by > >>>>> a method is the union of: > >>>>> * the types in the throws clause > >>>>> * the translated types in the rethrow clause > >>>>> * the types thrown by the translated types' selected > >>>>> constructors > >>>>> > >>>>> JLSv3 ?11.2.2 : For the purposes of exception analysis, the set > >>>>> of checked exception types which may be thrown by the method's > >>>>> body is the union of: > >>>>> * the types in the throws clause > >>>>> * the caught types in the rethrows clause > >>>>> > >>>>> JLSv3 ?11.2.3 : It is a compile-time error if a rethrows clause > >>>>> contains a translation from a checked exception type C but there > >>>>> exists no checked exception type E such that all of the following > >>>>> hold: > >>>>> * E <: C > >>>>> * The method body can throw E > >>>>> * No preceding translation in the rethrow clause catches E or > >>>>> a supertype of E > >>>>> unless C is the class java.lang.Exception. > >>>>> > >>>>> JLSv3 ?13.4.21 : Changes to the rethrows clause of methods or > >>>>> constructors do not break compatibility with existing binaries; > >>>>> these clauses are checked only at compile time. > >>>>> > >>>>> > >>>>> > >>>>> COMPILATION: How would the feature be compiled to class files? > >>>>> Show how the simple and advanced examples would be compiled. > >>>>> Compilation can be expressed as at least one of a desugaring to > >>>>> existing source constructs and a translation down to bytecode. If > >>>>> a new bytecode is used or the semantics of an existing bytecode > >>>>> are changed, describe those changes, including how they impact > >>>>> verification. Also discuss any new class file attributes that are > >>>>> introduced. Note that there are many downstream tools that > >>>>> consume class files and that they may to be updated to support > >>>>> the proposal! > >>>>> > >>>>> A simple desugaring could consist of enclosing the method body's > >>>>> statements in a try statement, with catch clauses for each > >>>>> translated exception type. For example, the following method: > >>>>> > >>>>> Method findMethod() > >>>>> catch ClassNotFoundException throw ConfigException, > >>>>> NoSuchMethodException throw ConfigException { > >>>>> > >>>>> Class c = Class.forName("some.Thing"); > >>>>> return c.getDeclaredMethod("execute", null); > >>>>> } > >>>>> > >>>>> would be desugared to: > >>>>> > >>>>> Method findMethod() > >>>>> throws ConfigException { > >>>>> try { > >>>>> Class c = Class.forName("some.Thing"); > >>>>> return c.getDeclaredMethod("execute", null); > >>>>> } > >>>>> catch (ClassNotFoundException e) { > >>>>> throw new ConfigException(e); > >>>>> } > >>>>> catch (MethodNotFoundException e) { > >>>>> throw new ConfigException(e); > >>>>> } > >>>>> } > >>>>> > >>>>> No changes to the classfile format are required. > >>>>> > >>>>> > >>>>> TESTING: How can the feature be tested? > >>>>> > >>>>> An initial set of jtreg tests is included in the prototype. > >>>>> > >>>>> > >>>>> LIBRARY SUPPORT: Are any supporting libraries needed for the > >>>>> feature? > >>>>> > >>>>> No > >>>>> > >>>>> > >>>>> REFLECTIVE APIS: Do any of the various and sundry reflection APIs > >>>>> need to be updated? This list of reflective APIs includes but is > >>>>> not limited to core reflection (java.lang.Class and > >>>>> java.lang.reflect.*), javax.lang.model.*, the doclet API, and > >>>>> JPDA. > >>>>> > >>>>> com.sun.source.tree.MethodTree would require updates to access > >>>>> the rethrows clause's caught and translated types. > >>>>> > >>>>> > >>>>> OTHER CHANGES: Do any other parts of the platform need be updated > >>>>> too? Possibilities include but are not limited to JNI, > >>>>> serialization, and output of the javadoc tool. > >>>>> > >>>>> No > >>>>> > >>>>> > >>>>> MIGRATION: Sketch how a code base could be converted, manually or > >>>>> automatically, to use the new feature. > >>>>> > >>>>> Catch clauses which simply wrap and rethrow an exception as > >>>>> another exception type not caught in an enclosing scope, can be > >>>>> trivially replaced with a rethrows clause, either manually or > >>>>> automatically. > >>>>> > >>>>> It should be possible for tools to offer bidirectional > >>>>> conversions such that an exception translation may be moved back > >>>>> into the method body if it is subsequently decided that > >>>>> additional logic is required. > >>>>> > >>>>> > >>>>> COMPATIBILITY > >>>>> > >>>>> BREAKING CHANGES: Are any previously valid programs now invalid? > >>>>> If so, list one. > >>>>> > >>>>> No > >>>>> > >>>>> > >>>>> EXISTING PROGRAMS: How do source and class files of earlier > >>>>> platform versions interact with the feature? Can any new > >>>>> overloadings occur? Can any new overriding occur? > >>>>> > >>>>> The semantics of existing class files and legal source files are > >>>>> unchanged by this feature. > >>>>> > >>>>> > >>>>> REFERENCES > >>>>> > >>>>> EXISTING BUGS: Please include a list of any existing Sun bug ids > >>>>> related to this proposal. > >>>>> > >>>>> http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6534270 > >>>>> (similar, but emphasizes unchecked exceptions) > >>>>> > >>>>> > >>>>> URL FOR PROTOTYPE (optional): > >>>>> > >>>>> http://slm888.com/javac > >>>>> > >>>>> > >>>>> > >>>> > >>> > >>> > >> > >> > >> > > > > > > > From reinier at zwitserloot.com Wed May 20 09:22:38 2009 From: reinier at zwitserloot.com (Reinier Zwitserloot) Date: Wed, 20 May 2009 18:22:38 +0200 Subject: The 'ignoreslist' exception handling proposal. In-Reply-To: <4A141B96.2070708@univ-mlv.fr> References: <4A141B96.2070708@univ-mlv.fr> Message-ID: Remi, While charsets are imported from outside the system, there are a few that are guaranteed by the JVM specs. A 'JVM' that throws an UnsupportedEncodingException on: new String(new byte[] { 65, 66, 67}, "US-ASCII"); Isn't a JVM at all, because the spec says that US-ASCII *MUST* be present. You said it: If its a developer mistake, then it should be a runtime exception. Mistyping 'US-ASCII' is a developer mistake. Also, Integer.parseInt(SomeUserInput)'s NumberFormatException is clearly NOT a developer mistake, yet that is a runtime exception. Grabbing a static file out of your deployed jar file via Class.getClassLoader().getResourceAsStream(), and reading this file caused an issue, you get a checked IOException, eventhough this is clearly the developer's error in writing his deploy script. Said differently, if reading local resources ought to fail with a checked exception, then every attempt to load a class should be a checked exception as well (after all, classes are just local resources as well!) So, yes, java's exception hierarchy is a mess sometimes. The idea behind making this point is that javac ignores reality and treats the checked exception system as holy and infallible - that is, you can NOT tell javac to stop whining about not handling checked exceptions. There are numerous situations where javac insists you handle an exception, even though as developer you know there is either A) a chance akin to the odds of a random OutOfMemoryError that the exception will actually occur, and is thus not worth the boilerplate (and due to the near impossibility of it, you have no sane route for handling the problem, so all you can do is rewrap or log it and fail), such as UnsupportedEncodingEx, or the IOExceptions falling out of resources loaded via ClassLoader.getResourceAsStream, or IOExceptions on FilterXStreams that are backed by a ByteArrayXStream, or B) You -know- it'll work itself out, such as for example throwing a checked exception out of a Runnable used as a Thread (all exceptions falling out of run() are handled by the thread unhandled exception mechanism, regardless of whether they are checked or not) - usually due to bad API design where an interface method you're supposed to override did not have a 'throws Exception' tacked on, and it can no longer be changed now due to backwards compatibility requirements. Example: java.lang.Runnable, and much in the HTTPServlet class. I posit that these situations are both common and not otherwise solvable. Therefore, I propose we are given a tool to more easily work around the failings of the hierarchy. Right now lots of java programmers would rather 'not have checked exceptions at all' because its so much hassle. By giving a cheaper way out of the system when it fails, we can let it stick around for all the times when it does work properly and catches us forgetting to handle an important exceptional situation. Being realistic, java programmers tend to -hate- the checked exception system with a passion. Unfortunately, hate translates into not paying attention to it. By crying wolf so much, we're trying java programmers to just let their IDEs fill in the boilerplate, or toss 'throws Exception' on everything just so it'll compile. This is not a good thing. Perfectionists would handle everything properly, but that's just not what's happening. That's my point; even though the opportunity for abuse is there, when you take into account that programmers aren't perfectionists and won't pen out a complete and well thought out try/catch block just to handle something they -think- is almost impossibly unlikely to happen, with ignore lists java code will be better on average. Compouding this already sizable problem: Out of the box, eclipse 'quickfixes' an uncaught exception by writing a catch block that prints the exception to standard error and then just continues silently. This is a bit like ON ERROR RESUME NEXT in visual basic. At the risk of peeving off eclipse developers: That's just retarded. I fixed the template in my eclipse, but how many programmers do that themselves? When I let eclipse quickfix an UnsupportedEncodingException, or an IOException on closing an InputStream, I usually just let this stand: try { inputStream.close(); } catch ( IOException e ) { //TODO Template catch block throw new RuntimeException(e); } eventhough that is so clearly inferior to just sneakyThrowing the IOException up the chain. less contentious alternative: add a sneakyThrow static method to Throwable in java core, and work with IDE vendors to replace the default quickfix for uncaught checked exceptions to: try { inputStream.close(); } catch ( IOException e ) { Throwable.sneakyThrow(e); } --Reinier Zwitserloot On May 20, 2009, at 17:02, R?mi Forax wrote: > Reiner, the problem is not new String(byte, Charset) but > the fact that Charset.forName() doesn't use a checked exception. > > The philosophy behind exception is: > - If it's a developer mistake, it's a runtime exception > - If it's an error that comes form outside the Java platform, > i.e an error that can not be predicted without some elements from > outside > the Java platform, it's a checked exception. > > Depending on the installation, some Charsets are available or not, > this is clearly an error that comes form outside of Java world so > it should be handled with a checked exception. > > Ok, it's a mistake > but I don't understand how it's related to your proposal ? > > R?mi > > Reinier Zwitserloot a ?crit : >> I'm more convinced than ever that java really needs this change, >> sooner rather than later. >> >> My arguments in favour: >> >> 1. Ruslan totally misunderstood my proposal, and also appears to >> misunderstand checked exceptions on the JVM level in general. This >> is in my experience an extremely common problem amongst java >> programmers, and this is very bad news for trying to interop javac- >> produced class files with scalac, groovy, JRuby, Python, and other >> languages' class files. By adding the concept of sneakyThrow to >> java, we teach java programmers that checked exceptions are only a >> debugging aid offered by javac, and NOT a guarantee by the JVM. >> This isn't a philosophical change at all: It's realism. In today's >> JVM world, you just cannot rely on that as a java programmer, and >> yet most java programmers do. >> >> NB: Ruslan and everyone else that's confused - I'll send an >> explanatory email in a few minutes to explain how it all works. >> >> 2. Joe Darcy, project coin, and sun routinely defend choices for >> the java platform by stating that java is designed for the >> realistic, human (e.g. fallible) programmer. We defend not adding >> operator overloading by stating that people will abuse it (FWIW, I >> agree with this mentality). And yet java (the language, not the >> VM!)'s current method of handling checked exceptions is geared >> towards the mythical perfectionist programmer! That makes no sense >> at all. I'll back up this point: >> >> >> #1: The JVM cannot, and does not, guarantee that the exceptions >> that fall out of a method call are only Errors, RuntimeExceptions, >> and any exception types declared by that method. That's simply not >> how the JVM works, and yet most java programmers erroneously think >> that it is. Being realistic for a moment, sneakyThrows occur all >> the time; you can have a class file mismatch (compiled against a >> different version of the class file vs. the version of that class >> file at runtime), you can be using a class compiled by scala, >> groovy, JRuby, Jython, or any other non-java programming language, >> or someone used a sneakyThrow method. >> >> Realistically, then, this isnt a philosophical change at all. >> We're just acknowledging something that already happened. >> >> #2: People get exception hierarchies wrong. All the time. The new >> String(bytes, encoding) constructor is flawed, for example. The >> right solution would be to have a Charset class and appropriate >> constructor that uses it (which string now has, since java 1.6, >> but the point to take home here is that the java core team it >> self, with all the lessons they knew by the time java 1.5 was >> developed, and with all that reviewed, still screwed it up), and >> preferably also a Charset.UTF8 constant, which java still doesn't >> have. Right now we have the weird situation that new String(bytes, >> "foo"); throws a checked exception, but new String(bytes, >> Charset.forName("foo")), which seems semantically equivalent, >> throws an unchecked exception. That cannot be the right design; we >> have it today because of the need for backwards compatibility. We >> must acknowledge that java's exception handling isn't perfect. >> >> There isn't even a proper definition of what constitutes a good >> situation for a checked exception, and what doesn't. Some people >> say that checked exceptions are appropriate only for legitimate >> alternative return values, where it would be a clear bug if a >> caller doesn't handle this code, in virtually all imaginable >> scenarios, such as an InsufficientBalanceException for a banking >> app's transferFundsFromPersonToPerson(Person A, Person B) method. >> In this view, IOException is mistyped (because there are whole >> hosts of situations where IOExceptions are either extremely >> unlikely, or likely, but there's nothing you can do - it is truly >> a program error and not an alternative return scenario; the only >> viable action is quitting, which an unchecked exception can do >> just as well). Then there's the view that a checked exception is >> appropriate anytime an exception is remotely likely to occur. In >> this view, Integer's parseInt's NumberFormatException is >> misclassed, because obviously non- numeric input is likely, and yet >> NFEx is unchecked. >> >> There is, in fact, no philosophy about checked and unchecked >> exceptions that would classify the various exceptions in the java >> core libraries the way they are in real life. It's a grab bag; >> some are checked, some are unchecked, and there's only a vague >> philosophy behind the choices. >> >> InputStream.close() throws a checked exception which most >> programmers find very questionable. Almost certainly a mistake, in >> practice (even if in theory it makes sense and is nicely symmetric >> with OutputStream's close, which does entirely appropriately >> throw IOException - at least as appopriate as write()'s throws >> clause). >> >> Proper use of the new String(bytes, encoding) constructor (where >> the input encoding is actually a variable and not a string >> literal) throws a checked exception, but Integer.parseInt() >> doesn't. yet, both are trying to parse a string where some forms >> are legal and some forms aren't. There's no reason for the >> dichotomy here; it's random. >> >> SQLException has only recently seen some work to make it a more >> usable construct, though the current situation amongst JDBC >> drivers remains troublesome. There are also many many mistakes >> that the entire exception hierarchy concept can make happen. Fine >> case in point: >> >> new String(bytes, "UUTF-8"); throws an >> UnsupportedEncodingException, which is a subclass of IOException. >> What, exactly, does this error have to do with I/O? Nothing >> whatsoever. The idea that UnsupportedEncodingException is a >> subclass of IOException is very questionable. >> >> We can also look at the other extreme and complain about the >> insane amount of exceptions that can fall out of reflection >> related calls. >> >> Bottomline: Let's be realistic - exception handling in java isn't >> perfect, and it never will be. Trying to protect people from >> abusing the throwing of exceptions by forcing rigid checked >> exception handling is a failed experiment, and the fact that just >> about every JVM language other than java itself doesn't have >> checked exceptions at all means we need a way to explicitly say to >> javac: I know better than you do, in this instance. Realistically, >> the number of situations where javac's advice is just wrong is >> formidable, and its making us write bad code. >> >> >> Mark, your proposal does indeed attempt to deal with this issue in >> a less philosophically drastic fashion, but I think the end result >> just isn't as good. Consider again Ruslan's typoed UUTF-8 example: >> >> If we wrap it, we're just hiding the cause behind a generic >> InternalError, AssertionError, or RuntimeException. I've seen them >> all. There's actually a decent unchecked alternative available >> (UnsupportedEncodingError) but that's the exception (heh, heh) >> rather than the rule. Sure, there's getCause(), but 'cause hell' >> is already causing stack traces nearing a hundred pages long, and >> a continuing unsolved problem in java land is finding the one >> cause in the massive onslaught that helps you get to real issue at >> hand. In this situation, the rewrap is needless noise in the >> exception chain. >> >> Without either your or my proposal, we get the worst of both >> worlds: We rethrow, adding noise to the runtime information, and >> we also add 4 to 5 lines of noise to the code with a semantically >> pointless try/ catch block that rethrows the UnsupportedEncodingEx >> into something else. >> >> --Reinier Zwitserloot >> Like it? Tip it! >> http://tipit.to >> >> >> >> >> > From reinier at zwitserloot.com Wed May 20 09:39:49 2009 From: reinier at zwitserloot.com (Reinier Zwitserloot) Date: Wed, 20 May 2009 18:39:49 +0200 Subject: Checked Exceptions do not exist on the JVM. In-Reply-To: References: <39084932-B2CC-4B91-97EA-006FE21301F0@googlemail.com> <4A1339ED.8090309@sun.com> <68BF955A-9796-44F7-9E97-94BBB43ADCC5@zwitserloot.com> <988330f1d03fc629490d5dffa3fc2d25.squirrel@wmail.gradsoft.ua> Message-ID: Tom, here are two class files: Foo.class Bar.class which one adheres to the JLS checked exception model, and which one has methods that leak checked exceptions without declaring them? I can't tell. Can you? You can quote me JLS specs all day long, mis-interpret my words and write in a denigrating fashion, but none of that changes the plain fact: You CAN NOT RELY ON THROWS CLAUSES. Checked exceptions can fall out of *any* method *anywhere*. Period. I thought when I mentioned "checked exceptions in situations where you didn't expect them", it was obvious from context that I meant: checked exceptions falling out of methods that don't declare them, but apparently I need to spell this out for you. You also conveniently forgot that, even if you're only using javac, you can still get sneakyThrow: You can expicitly sneakyThrow via class file construction or using the .newInstance() trick, or get accidental sneakyThrow when compiling against v1 of a class, but running with v2 (which added a bunch of checked exceptions). Point me to the entry in the JLS that makes this impossible, please. It doesn't exist, so, take your pedantic whinging about "JLS spec", print it out, and eat it*. *) I get annoyed when people write 'WTF' and 'I give up' in response to a perfectly civil email. Example: public class Foo { public static void foo() {} } as Foo.class and this: public class Bar { public static void main(String[] args) { Foo.foo(); } } as Bar.class. Then edit Foo.java to this and recompile (but don't recompile Bar.java!), then rerun Bar: public class Foo { public static void foo() throws java.io.IOException { throw new java.io.IOException("Apparently this will make Tom Ball's head explode. Whoops!"); } } ... and behold! Tom Ball's head explodes. --Reinier Zwitserloot On May 20, 2009, at 18:11, Tom Ball wrote: > On Wed, May 20, 2009 at 6:35 AM, Reinier Zwitserloot < > reinier at zwitserloot.com> wrote: > >> Checked exceptions do not exist. > > > Sure they do, but they are a Java language concept, not a JVM one. > The same > is true for lots of other Java language features. > > That's right. They don't. There's no such thing. It's all a figment of >> javac. > > > You must mean that checked exceptions are defined by the Java Language > Specification. javac is just a compiler that adheres to the JLS, > like many > other Java compilers. > > >> The JVM does not have checked exceptions. All it knows about is >> 'throws clauses', which are part of a method's signature and have >> ZERO >> impact on how a JVM runs a class file. As far as the JVM is >> concerned, >> throws clauses are just a comment. Utterly ignored by javac. > > > No compiler can ignore the throws part of a method signature and be > a valid > Java language compiler. Having worked on javac, I know for a fact > that > whether a class symbol is read from a source or class file, its > methods > include all defined throws clauses and enforces their use as the JLS > dictates. The javac source is publicly available -- check out the > Symbol > and ClassReader classes. > > >> You can >> strip every single one out of every class file and run an app, and >> the >> execution of it would be 100% the same. The only change would be in >> java.lang.reflect's getExceptionTypes() method. >> >> I repeat: The JVM *DOES* *NOT* know about checked exceptions. The JVM >> assumes all exceptions are unchecked, and assumes that javac sorted >> it >> all out. This is flawed, obviously, because javac isn't the only tool >> out there that can make class files. > > > Flawed? The Java Language and the JVM have different > specifications; the > JLS defines checked exceptions, and the JVMS doesn't. The JVM > support many > different languages besides Java, most of whom don't define checked > exceptions. That's not a flaw, but support for language > independence. The > reason the JVM considers all exceptions as runtime exceptions is > because > it's the runtime. > > >> This is similar to generics in >> objects, which is also a figment of javac's imagination: On the JVM >> level, erasure occurs - that info just isn't there. If you want, you >> can name this 'checked exception erasure'. The notion that exceptions >> are checked is erased during compilation. > > > Not true. Yes, the JVM doesn't support generics, but classfiles > contain all > information needed to correctly compile classes which use them. The > same is > true for exceptions, as the JLS requires. > > >> The only application in existence that cares about this 'throws >> clauses' comment in class files is the application called 'javac'. > > > You are going to make engineers support other Java compilers upset > with this > incorrect assumption. They all have to support checked exceptions, > or they > aren't Java compilers. > > It gets worse: JRuby, groovy, Jython, and scala, they ALL feature >> *ZERO* checked exception clauses on methods. They just generate class >> bytecode with throw statements without caring about the throws clause >> on methods. > > > Worse? Different languages make different trade-offs between > compile and > runtime checking, and it's a matter of personal preference what > trade-offs > you want. There is no "better" or "worse", which is why the JVM > doesn't > require one or the other. > > >> This is why, in java, anytime you interop with code not >> compiled by javac, you can get checked exceptions in situations where >> you didn't expect them. > > > WTF? If you are calling libraries written in other languages, those > libraries throw exceptions as defined by their language > specifications. If > you don't like the contracts of those libraries, don't use them. > > I give up, > Tom > > >> Millions of classes generated by those >> compilers are out there right now throwing checked exceptions that >> escape from methods that do NOT have a 'throws X' clause on them. >> >> In other words: There is *NO* guarantee whatsoever in the JVM that >> checked exceptions can only occur in situations where they are >> explicitly declared. If your code relies on it, then your code is >> buggy. >> >> >> Secondly, you mentioned that java wraps exceptions that occur in the >> constructor with Class.newInstance() into an >> ExceptionInInitializerError. That's not what happens at all; That >> exception (ExceptionInInitializerError) is for static initializers >> and >> object initializers, not constructors. A practical example will make >> this clear. Take the following code, save it in Foo.java, compile it, >> and run it: >> >> import java.io.IOException; >> >> public class Foo { >> public static class Test { >> public Test() throws IOException { >> throw new IOException(); >> } >> } >> >> //Note how I didn't add 'throws IOException' in the next line! >> public static void main(String[] args) throws >> InstantiationException, IllegalAccessException { >> Test x = Test.class.newInstance(); >> } >> } >> >> >> The result is an IOException. Not a ObjectInstantionException with an >> IOException as cause; no - an IOException. You can doublecheck this >> by wrapping the newInstance in a try/catch (Throwable t) block and >> printing the class name of the resulting t. >> >> Thirdly, you misunderstand what my ignoreslist proposal does: It does >> not silently swallow the exception, that'd be a very stupid way of >> handling exceptions that you don't -think- can occur. An ignoreslist >> has zero effect on the execution of a method body. The only >> difference >> is that, unlike a throws clause, you don't burden any of the methods >> that call you to handle the listed exception. It's a signal to javac >> to disable its rigid checking of making sure any checked exception >> thrown in the body is also present in that method's 'throws' clause. >> It's exactly analogous to adding the 'throws' clause, compiling the >> code, then using a hex editor to remove the throws clause. >> >> >> You're also mistaken in retrofitting Runnable with 'throws >> Exception': >> That'll break many thousands of classes out there in real life. You >> forget that people don't just make Runnables and hand them off to >> java.lang.Thread; there's plenty of code out there that *receives* >> Runnables, and that code presumes that its run() method does not >> throw >> any checked exceptions. It would be backwards compatible (because, as >> I said, the JVM doesn't know about these things), but it wouldn't be >> source compatible; recompiling your code would all of a sudden >> produce >> errors. e.g: >> >> public void myMethod(Runnable r) { >> r.run(); >> } >> >> would no longer compile, because all of a sudden 'r.run();' can throw >> Exception, which I need to catch, or declare as thrown (or, if this >> proposal is accepted, declare as sneakyThrown/ignore). >> >> >> --Reinier Zwitserloot >> >> >> >> On May 20, 2009, at 07:01, Ruslan Shevchenko wrote: >> >>>> Here's a trivially simple change to implement, though it has some >>>> far >>>> reaching repercussions for java as a whole: >>>> >>>> change the 'rethrows' clause to an ignores clause: Any checked >>>> exception in the ignores list may be thrown from the method body, >>>> but >>>> is NOT part of the method's checked exception list. It is hence >>>> also >>>> not part of the signature, just like sticking a 'synchronized' >>>> keyword >>>> on a method isn't part of its signature, but an implementation >>>> detail. >>>> >>>> >>>> example: >>>> >>>> Runnable r = new Runnable() { >>>> public void run() ignores UnsupportedEncodingException { >>>> String x = new String(inBytes, "UTF-8"); >>>> } >>>> }; >>>> >>> >>> And how actually debug such statements ? >>> //In this example, run() method do nothing, so look on slightly >>> complex >>> primer: >>> >>> class X >>> { >>> String x; >>> >>> public void setString(byte[] inBytes) >>> ignores UnsupportedEncodingException >>> { >>> x = new String(inBytes, "UUTF-8"); >>> } >>> >>> public void setAndPrintString(byte[] inBytes) >>> { >>> setString(inBytes); >>> System.out.println("received:"+x); >>> } >>> >>> >>> } >>> >>> Assume, that programmer wrote (by error) "UUTF-8" instead "UTF-8" >>> >>> Output of programm will be "received:null". >>> Reasons for null x in complex programs can be millions. Debugging >>> with >>> ignoring exception will be extremally hard. >>> >>> I. e. wrapping checked exception to runtime is more or less normal; >>> ignoring will become a very big paint-point. >>> >>> Alternative to ignore can be call default thread exception handler. >>> (handle keyword ?) >>> >>>> This sounds like blowing up the entire point of checked exceptions, >>>> but with java moving towards more interoperation with other JVM >>>> based >>>> languages, which almost always throw checked exceptions without >>>> actually declaring them (Jython, JRuby, Scala -- I can't think of a >>>> single one other than java itself that has the notion of checked >>>> exceptions in the first place). If the whole 'java is like the >>>> assembler of the JVM' story is going to hold water, something like >>>> this is needed. >>>> >>> >>> Yes, this is interesting problem. >>> In theory we have UndeclaredThowableException, but .. wrapping each >>> invocation of foreign language into it is ineffecient. >>> >>> But InvokeDynamic can throws any throwable in declaration, so this >>> problem >>> can be solved (on other level) >>> >>>> For some further support: I doubt anyone seriously holds the >>>> position >>>> that java's checked exception experiment was an unmitigated >>>> success. >>>> There are pain points, here and there. The above example in fact >>>> includes two of them: The fact that runnable throws no checked >>>> exceptions is clearly a mistake in regards to threading, because >>>> Thread objects clearly should handle ANY exception falling out of >>>> its >>>> run() method (and it in fact does, via the unchecked exception >>>> handler >>>> mechanism), and there's a general mismatch between main(), which >>>> MAY >>>> throw exceptions, and run(), which may not, even though they are >>>> both >>>> 'thread start points'. Another mistake is >>> >>> Adding throw exception to signature of Runnable.run does not broke >>> anything in existent code, so this can be nice library change. >>> >>>> UnsupportedEncodingExceptions, a checked exception, resulting >>>> from a >>>> call to converting byte arrays to strings using an encoding that is >>>> guaranteed by the JVM using a string literal, such as "UTF-8". The >>>> appropriate exception would be UnsupportedEncodingError("This JVM >>>> is >>>> broken. Charset UTF-8 missing. Reinstall it") - which is unchecked. >>>> >>> >>> Or porgrammer can write UUTF-8 instead UTF-8. It's happens ;) >>> >>>> In other words, while I'm not ready to write off checked exceptions >>>> as >>>> a whole, I am more than ready to acknowledge that the programmer >>>> more >>>> often knows better than the compiler, compared to how often the >>>> programmer, in laziness or inexperience, abuses this freedom. >>>> Especially considering that, on the JVM, you really DONT get >>>> checked >>>> exceptions guarantees; any class compiled by anything other than >>>> javac >>>> is free to throw checked exceptions without declaring them, and >>>> even >>>> in javac you can technically do this using 'sneaky throw' >>>> libraries, >>>> which use various workarounds, one of which will NEVER go away*. >>>> We're >>>> not losing much here, in other words. In fact, the way javac works, >>>> inexperienced java programmers may erroneously assume that checked >>>> exceptions couldn't possibly happen unless the checked exception is >>>> declared. This is not the case. >>>> >>>> *) The one that will never go away is >>>> java.lang.Class.newInstance(), >>>> which is functionally defined to sneakily throw on any exceptions >>>> thrown by the constructor, checked or not, and does NOT wrap them >>>> up >>>> into a wrapper the way java.lang.reflect.Method.invoke() does. This >>> >>> Its wrapped to java.lang.ExceptionInInitializerError >>> >>> >>>> cannot change without breaking backwards compatibility. Another one >>>> that will never go away is constructing a class on the fly that >>>> sneaky >>>> throws, loading it with ClassLoader's load from bytes mechanism, >>>> and >>>> executing it. >>>> >>> >>> And what is JVM behaviour in such case ? >>> >>>> >>>> Attempting to solve this issue with a library requires rather a lot >>>> of >>>> ugly boilerplate: >>>> >>>> import static Utils.sneakyThrow; >>>> >>>> Runnable r = new Runnable() { >>>> public void run() { >>>> String x; >>>> try { >>>> x = new String(inBytes, "UTF-8"); >>>> } catch ( UnsupportedEncodingException e ) { >>>> sneakyThrow(e); >>>> } >>>> } >>>> }; >>>> >>>> >>>> NB: For sanity purposes, the restriction on javac that the try >>>> block >>>> MUST contain at least 1 statement that could throw a checked >>>> exception >>>> type that is listed on one of the accompanying catch blocks (other >>>> than Exception, which you can always catch), should go away; this >>>> has >>>> already been proposed before, and in fact is a backwards >>>> compatibility >>>> painpoint for the coin proposal that allows you to rethrow a final >>>> Exception as if its type is the intersection of all checked types >>>> thrown by the statements in the try body. >>>> >>>> --Reinier Zwitserloot >>>> Like it? Tip it! >>>> http://tipit.to >>>> >>>> >>>> >>>> On May 20, 2009, at 02:22, Mark Mahieu wrote: >>>> >>>>> Yeah, I suppose I did make it rather more complicated than it >>>>> needed >>>>> to be. >>>>> >>>>> Thanks for the feedback. >>>>> >>>>> Mark >>>>> >>>>> >>>>> On 19 May 2009, at 23:59, Joe Darcy wrote: >>>>> >>>>>> Hello. >>>>>> >>>>>> Hmm; this strikes me as a bit involved for the potential benefits >>>>>> of the feature. >>>>>> >>>>>> -Joe >>>>>> >>>>>> On 03/30/09 05:04 PM, Mark Mahieu wrote: >>>>>>> Forgot my JLS references in the first one... >>>>>>> >>>>>>> >>>>>>> >>>>>>> HTML version + prototype available at: >>>>>>> >>>>>>> http://slm888.com >>>>>>> >>>>>>> >>>>>>> >>>>>>> >>>>>>> Rethrows Clause >>>>>>> v0.1.1 >>>>>>> >>>>>>> >>>>>>> AUTHOR(S): >>>>>>> >>>>>>> Mark Mahieu >>>>>>> >>>>>>> >>>>>>> OVERVIEW >>>>>>> >>>>>>> FEATURE SUMMARY: Should be suitable as a summary in a language >>>>>>> tutorial. >>>>>>> >>>>>>> A new clause on method declarations which allows exception >>>>>>> translations (wrapping and rethrowing as a different type) to be >>>>>>> cleanly defined separately from the body of the method. In many >>>>>>> cases, checked exception type names do not then need to be >>>>>>> repeated in a method's throws clause and in a throw statement >>>>>>> in >>>>>>> the method body. >>>>>>> >>>>>>> >>>>>>> MAJOR ADVANTAGE: What makes the proposal a favorable change? >>>>>>> >>>>>>> The proposal adds direct support for a common idiom in daily use >>>>>>> by Java programmers worldwide, allowing them to express their >>>>>>> intentions with greater clarity and ease. In comparison with >>>>>>> some proposals, this is an attempt to make dealing with checked >>>>>>> exceptions easier by increasing the expressiveness of exception >>>>>>> handling code in general, rather than by attempting to >>>>>>> deprecate >>>>>>> checked exceptions in favour of unchecked exceptions. >>>>>>> >>>>>>> >>>>>>> MAJOR BENEFIT: Why is the platform better if the proposal is >>>>>>> adopted? >>>>>>> >>>>>>> There is a reduction in the amount of boilerplate Java >>>>>>> programmers have to read and write for code dealing with >>>>>>> checked >>>>>>> exceptions. Declarations specifying both thrown and rethrown >>>>>>> (wrapped) exceptions are kept together, aiding comprehension of >>>>>>> the code. >>>>>>> >>>>>>> >>>>>>> MAJOR DISADVANTAGE: There is always a cost. >>>>>>> >>>>>>> As with any syntax sugar which enables an alternative way of >>>>>>> expressing an existing idiom, programmers may be tempted to use >>>>>>> it even when the existing idiom would be more appropriate. >>>>>>> >>>>>>> >>>>>>> ALTERNATIVES: Can the benefits and advantages be had some way >>>>>>> without a language change? >>>>>>> >>>>>>> No. >>>>>>> >>>>>>> >>>>>>> EXAMPLES >>>>>>> >>>>>>> SIMPLE EXAMPLE: Show the simplest possible program utilizing the >>>>>>> new feature. >>>>>>> >>>>>>> >>>>>>> Before: >>>>>>> >>>>>>> void before() throws ConfigException { >>>>>>> try { >>>>>>> Class.forName("where.is.the.Code"); >>>>>>> } >>>>>>> catch (ClassNotFoundException e) { >>>>>>> throw new ConfigException(e); >>>>>>> } >>>>>>> } >>>>>>> >>>>>>> After: >>>>>>> >>>>>>> void after() >>>>>>> catch ClassNotFoundException throw ConfigException { >>>>>>> >>>>>>> Class.forName("here.is.the.Code"); >>>>>>> } >>>>>>> >>>>>>> >>>>>>> ADVANCED EXAMPLE: Show advanced usage(s) of the feature. >>>>>>> >>>>>>> Before: >>>>>>> >>>>>>> void suspendAccount() >>>>>>> throws AuthorizationException, >>>>>>> PersistenceException { >>>>>>> try { >>>>>>> checkMyAuthoritah(); >>>>>>> db.update(/*...*/); >>>>>>> log.recordInfo(/*...*/); >>>>>>> } >>>>>>> catch (InfernalDBException e) { >>>>>>> throw new PersistenceException(e); >>>>>>> } >>>>>>> catch (InfernalLogException e) { >>>>>>> throw new RuntimeException(e); >>>>>>> } >>>>>>> } >>>>>>> >>>>>>> After: >>>>>>> >>>>>>> void suspendAccount() >>>>>>> throws AuthorizationException >>>>>>> catch InfernalDBException throw PersistenceException, >>>>>>> InfernalLogException throw RuntimeException { >>>>>>> >>>>>>> checkMyAuthoritah(); >>>>>>> db.update(/*...*/); >>>>>>> log.recordInfo(/*...*/); >>>>>>> } >>>>>>> >>>>>>> >>>>>>> DETAILS >>>>>>> >>>>>>> SPECIFICATION: Describe how the proposal affects the grammar, >>>>>>> type system, and meaning of expressions and statements in the >>>>>>> Java Programming Language as well as any other known impacts. >>>>>>> >>>>>>> The syntactic grammar is modified to allow an optional rethrows >>>>>>> clause immediately prior to a MethodBody: >>>>>>> >>>>>>> MethodDeclaratorRest: >>>>>>> FormalParameters {[]} [throws >>>>>>> QualifiedIdentifierList] ( ( [catch ExceptionTranslationList] >>>>>>> MethodBody ) | ; ) >>>>>>> >>>>>>> ExceptionTranslationList: >>>>>>> QualifiedIdentifier throw QualifiedIdentifier >>>>>>> { , ExceptionTranslationList } >>>>>>> >>>>>>> >>>>>>> >>>>>>> JLSv3 ?8.4.6 : A rethrows clause lists one or more exception >>>>>>> translations, each translation consisting of a caught type C and >>>>>>> a translated type T for which all of the following must hold: >>>>>>> * C <: java.lang.Exception >>>>>>> * T < java.lang.Throwable >>>>>>> * Neither C nor T is a type variable. >>>>>>> * T has an accessible constructor suitable for rethrowing a >>>>>>> value of type C (see below). >>>>>>> * T is not the same type as C. >>>>>>> >>>>>>> Any exceptions thrown by the method body which are a subtype >>>>>>> of a >>>>>>> caught exception type in the rethrows clause, are rethrown as >>>>>>> the >>>>>>> corresponding translated exception type. >>>>>>> >>>>>>> For a given translated type T with corresponding caught type >>>>>>> C, if >>>>>>> T has an accessible constructor accepting a value of type C, >>>>>>> then >>>>>>> the translation is equivalent to the following: >>>>>>> >>>>>>> catch (C e) { >>>>>>> throw new T(e); >>>>>>> } >>>>>>> >>>>>>> Otherwise it must have an accessible no argument constructor, >>>>>>> and >>>>>>> the translation is equivalent to: >>>>>>> >>>>>>> catch (C e) { >>>>>>> throw new T().initCause(e); >>>>>>> } >>>>>>> >>>>>>> >>>>>>> A rethrows clause does not restrict which types may appear in a >>>>>>> throws clause for the same method. In particular, for a given >>>>>>> caught type C in the rethrows clause, it is permitted for some >>>>>>> type C1 :> C to also be listed in the throws clause. >>>>>>> >>>>>>> >>>>>>> JLSv3 ?8.2 : The set of exception types declared to be thrown >>>>>>> by >>>>>>> a method is the union of: >>>>>>> * the types in the throws clause >>>>>>> * the translated types in the rethrow clause >>>>>>> * the types thrown by the translated types' selected >>>>>>> constructors >>>>>>> >>>>>>> JLSv3 ?11.2.2 : For the purposes of exception analysis, the set >>>>>>> of checked exception types which may be thrown by the method's >>>>>>> body is the union of: >>>>>>> * the types in the throws clause >>>>>>> * the caught types in the rethrows clause >>>>>>> >>>>>>> JLSv3 ?11.2.3 : It is a compile-time error if a rethrows clause >>>>>>> contains a translation from a checked exception type C but there >>>>>>> exists no checked exception type E such that all of the >>>>>>> following >>>>>>> hold: >>>>>>> * E <: C >>>>>>> * The method body can throw E >>>>>>> * No preceding translation in the rethrow clause catches E or >>>>>>> a supertype of E >>>>>>> unless C is the class java.lang.Exception. >>>>>>> >>>>>>> JLSv3 ?13.4.21 : Changes to the rethrows clause of methods or >>>>>>> constructors do not break compatibility with existing binaries; >>>>>>> these clauses are checked only at compile time. >>>>>>> >>>>>>> >>>>>>> >>>>>>> COMPILATION: How would the feature be compiled to class files? >>>>>>> Show how the simple and advanced examples would be compiled. >>>>>>> Compilation can be expressed as at least one of a desugaring to >>>>>>> existing source constructs and a translation down to >>>>>>> bytecode. If >>>>>>> a new bytecode is used or the semantics of an existing bytecode >>>>>>> are changed, describe those changes, including how they impact >>>>>>> verification. Also discuss any new class file attributes that >>>>>>> are >>>>>>> introduced. Note that there are many downstream tools that >>>>>>> consume class files and that they may to be updated to support >>>>>>> the proposal! >>>>>>> >>>>>>> A simple desugaring could consist of enclosing the method body's >>>>>>> statements in a try statement, with catch clauses for each >>>>>>> translated exception type. For example, the following method: >>>>>>> >>>>>>> Method findMethod() >>>>>>> catch ClassNotFoundException throw ConfigException, >>>>>>> NoSuchMethodException throw ConfigException { >>>>>>> >>>>>>> Class c = Class.forName("some.Thing"); >>>>>>> return c.getDeclaredMethod("execute", null); >>>>>>> } >>>>>>> >>>>>>> would be desugared to: >>>>>>> >>>>>>> Method findMethod() >>>>>>> throws ConfigException { >>>>>>> try { >>>>>>> Class c = Class.forName("some.Thing"); >>>>>>> return c.getDeclaredMethod("execute", null); >>>>>>> } >>>>>>> catch (ClassNotFoundException e) { >>>>>>> throw new ConfigException(e); >>>>>>> } >>>>>>> catch (MethodNotFoundException e) { >>>>>>> throw new ConfigException(e); >>>>>>> } >>>>>>> } >>>>>>> >>>>>>> No changes to the classfile format are required. >>>>>>> >>>>>>> >>>>>>> TESTING: How can the feature be tested? >>>>>>> >>>>>>> An initial set of jtreg tests is included in the prototype. >>>>>>> >>>>>>> >>>>>>> LIBRARY SUPPORT: Are any supporting libraries needed for the >>>>>>> feature? >>>>>>> >>>>>>> No >>>>>>> >>>>>>> >>>>>>> REFLECTIVE APIS: Do any of the various and sundry reflection >>>>>>> APIs >>>>>>> need to be updated? This list of reflective APIs includes but is >>>>>>> not limited to core reflection (java.lang.Class and >>>>>>> java.lang.reflect.*), javax.lang.model.*, the doclet API, and >>>>>>> JPDA. >>>>>>> >>>>>>> com.sun.source.tree.MethodTree would require updates to access >>>>>>> the rethrows clause's caught and translated types. >>>>>>> >>>>>>> >>>>>>> OTHER CHANGES: Do any other parts of the platform need be >>>>>>> updated >>>>>>> too? Possibilities include but are not limited to JNI, >>>>>>> serialization, and output of the javadoc tool. >>>>>>> >>>>>>> No >>>>>>> >>>>>>> >>>>>>> MIGRATION: Sketch how a code base could be converted, manually >>>>>>> or >>>>>>> automatically, to use the new feature. >>>>>>> >>>>>>> Catch clauses which simply wrap and rethrow an exception as >>>>>>> another exception type not caught in an enclosing scope, can be >>>>>>> trivially replaced with a rethrows clause, either manually or >>>>>>> automatically. >>>>>>> >>>>>>> It should be possible for tools to offer bidirectional >>>>>>> conversions such that an exception translation may be moved >>>>>>> back >>>>>>> into the method body if it is subsequently decided that >>>>>>> additional logic is required. >>>>>>> >>>>>>> >>>>>>> COMPATIBILITY >>>>>>> >>>>>>> BREAKING CHANGES: Are any previously valid programs now invalid? >>>>>>> If so, list one. >>>>>>> >>>>>>> No >>>>>>> >>>>>>> >>>>>>> EXISTING PROGRAMS: How do source and class files of earlier >>>>>>> platform versions interact with the feature? Can any new >>>>>>> overloadings occur? Can any new overriding occur? >>>>>>> >>>>>>> The semantics of existing class files and legal source files are >>>>>>> unchanged by this feature. >>>>>>> >>>>>>> >>>>>>> REFERENCES >>>>>>> >>>>>>> EXISTING BUGS: Please include a list of any existing Sun bug ids >>>>>>> related to this proposal. >>>>>>> >>>>>>> http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6534270 >>>>>>> (similar, but emphasizes unchecked exceptions) >>>>>>> >>>>>>> >>>>>>> URL FOR PROTOTYPE (optional): >>>>>>> >>>>>>> http://slm888.com/javac >>>>>>> >>>>>>> >>>>>>> >>>>>> >>>>> >>>>> >>>> >>>> >>>> >>> >>> >> >> >> > From rssh at gradsoft.com.ua Wed May 20 06:47:28 2009 From: rssh at gradsoft.com.ua (Ruslan Shevchenko) Date: Wed, 20 May 2009 16:47:28 +0300 (EEST) Subject: Checked Exceptions do not exist on the JVM. In-Reply-To: References: <39084932-B2CC-4B91-97EA-006FE21301F0@googlemail.com> <4A1339ED.8090309@sun.com> <68BF955A-9796-44F7-9E97-94BBB43ADCC5@zwitserloot.com> <988330f1d03fc629490d5dffa3fc2d25.squirrel@wmail.gradsoft.ua> Message-ID: > Ruslan, you've got it all wrong. Though, you've just proved to this > list that java programmers don't really get this concept, which is one > of the reasons why I want to introduce it: Make it obvious to java > programmers that the JVM does *NOT* guarantee that checked exceptions > are declared. > > Checked exceptions do not exist. > > That's right. They don't. There's no such thing. It's all a figment of > javac. The JVM does not have checked exceptions. All it knows about is > 'throws clauses', which are part of a method's signature and have ZERO > impact on how a JVM runs a class file. As far as the JVM is concerned, > throws clauses are just a comment. Utterly ignored by javac. You can > strip every single one out of every class file and run an app, and the > execution of it would be 100% the same. The only change would be in > java.lang.reflect's getExceptionTypes() method. > What means 'really' ? Can we say, that ... for examples, 'for' construct does not exists, because it emulated by 'if-s' on JVM level ? > > In other words: There is *NO* guarantee whatsoever in the JVM that > checked exceptions can only occur in situations where they are > explicitly declared. If your code relies on it, then your code is buggy. > Java (as language) give me some isolation level. Of course not 100%, (Class.newInstance() is a hole. //I misread documentation, because I was not able to imagine that such //hole exists (!). But you propose to destroy building because exists one hole, instead fixing building ? Better fix - is declare Class.newInstance() to throw Throwable. Can I ask community: anybody know, why such situation exists and reason not to fix Class.newInstance() ? > > Thirdly, you misunderstand what my ignoreslist proposal does: It does > not silently swallow the exception, that'd be a very stupid way of > handling exceptions that you don't -think- can occur. An ignoreslist Yes, (I wrote this in my next letter). // word 'ignore' fooled me and will fool others. Let's speak 'not-care' instead 'ignore' So int f() not-care MyException { } will throw MyException, which will be not handled for JVM, for programmer this mean, that this code: 1. will throw LinkageError, when f is not called inside some try blocks, where MyException is not catched. 2. will throw MyException, when f is called inside some try blocks, where MyException (or generic Exception or Throwable) is cathed. > > You're also mistaken in retrofitting Runnable with 'throws Exception': > That'll break many thousands of classes out there in real life. You > forget that people don't just make Runnables and hand them off to > java.lang.Thread; there's plenty of code out there that *receives* > Runnables, and that code presumes that its run() method does not throw > any checked exceptions. It would be backwards compatible (because, as > I said, the JVM doesn't know about these things), but it wouldn't be // Hmm, looks like my next letter was not in list. (in which I correct self //in this points) //I guess 1.6 -> 1.7 transition can break API compatibility: it's major //revision change. Java (as language) support *both* checked and unchecked exception. More realistic approach for transition 'all exceptions unchecked' is change API to throw unchecked exception. (Which we see on practice in layered software system, and where rethrow proposal good for). From tball at google.com Wed May 20 10:55:11 2009 From: tball at google.com (Tom Ball) Date: Wed, 20 May 2009 10:55:11 -0700 Subject: Checked Exceptions do not exist on the JVM. In-Reply-To: References: <39084932-B2CC-4B91-97EA-006FE21301F0@googlemail.com> <4A1339ED.8090309@sun.com> <68BF955A-9796-44F7-9E97-94BBB43ADCC5@zwitserloot.com> <988330f1d03fc629490d5dffa3fc2d25.squirrel@wmail.gradsoft.ua> Message-ID: I don't consider "Ruslan, you've got it all wrong" an example of opening a "perfectly civil email", it sounds like bullying. This isn't slashdot, it's a forum for discussions on possible small improvements to the Java language. So I shouldn't have responded with the same tone as your message, and for that I apologize to the wider group. An "it's possible to write bad code" argument doesn't refute other people's valid arguments. Developers are always capable of writing bad code, and anyone who designs a language or runtime where it's impossible will have trouble finding adoption because it's too restrictive. Who cares if sneaky throw works? If a library abuses that hack, don't use it. The purpose of throws clauses is to better describe the contract a method offers for its callers: it only accepts parameters of a certain type, it returns an instance of a specific type, and under certain (hopefully documented) conditions it may throw specific exceptions. Checked exceptions are intended to call out specific exceptions that the library writer believes the caller should be able to recover from, and therefore should handle or forward. If a library writer subverts the contract of his own method, well, that's a shame but doesn't necessarily call for changes to the language. If a non-Java language has libraries which throw what are in Java checked exceptions, then write Java code which does more checking at runtime since that's apparently what the other language requires (or don't use those libraries). This isn't a problem, and so there is nothing about it that needs fixing in Java 7. Tom On Wed, May 20, 2009 at 9:39 AM, Reinier Zwitserloot < reinier at zwitserloot.com> wrote: > Tom, here are two class files: > > Foo.class > Bar.class > > which one adheres to the JLS checked exception model, and which one has > methods that leak checked exceptions without declaring them? > > I can't tell. Can you? > > You can quote me JLS specs all day long, mis-interpret my words and write > in a denigrating fashion, but none of that changes the plain fact: > > You CAN NOT RELY ON THROWS CLAUSES. Checked exceptions can fall out of > *any* method *anywhere*. Period. I thought when I mentioned "checked > exceptions in situations where you didn't expect them", it was obvious from > context that I meant: checked exceptions falling out of methods that don't > declare them, but apparently I need to spell this out for you. > > You also conveniently forgot that, even if you're only using javac, you can > still get sneakyThrow: You can expicitly sneakyThrow via class file > construction or using the .newInstance() trick, or get accidental > sneakyThrow when compiling against v1 of a class, but running with v2 (which > added a bunch of checked exceptions). Point me to the entry in the JLS that > makes this impossible, please. It doesn't exist, so, take your pedantic > whinging about "JLS spec", print it out, and eat it*. > > > *) I get annoyed when people write 'WTF' and 'I give up' in response to a > perfectly civil email. > > > Example: > > public class Foo { > public static void foo() {} > } > > as Foo.class > > and this: > > public class Bar { > public static void main(String[] args) { > Foo.foo(); > } > } > > as Bar.class. > > Then edit Foo.java to this and recompile (but don't recompile Bar.java!), > then rerun Bar: > > public class Foo { > public static void foo() throws java.io.IOException { > throw new java.io.IOException("Apparently this will make Tom Ball's > head explode. Whoops!"); > } > } > > ... and behold! Tom Ball's head explodes. > > --Reinier Zwitserloot > > > > > On May 20, 2009, at 18:11, Tom Ball wrote: > > On Wed, May 20, 2009 at 6:35 AM, Reinier Zwitserloot < >> reinier at zwitserloot.com> wrote: >> >> Checked exceptions do not exist. >>> >> >> >> Sure they do, but they are a Java language concept, not a JVM one. The >> same >> is true for lots of other Java language features. >> >> That's right. They don't. There's no such thing. It's all a figment of >> >>> javac. >>> >> >> >> You must mean that checked exceptions are defined by the Java Language >> Specification. javac is just a compiler that adheres to the JLS, like >> many >> other Java compilers. >> >> >> The JVM does not have checked exceptions. All it knows about is >>> 'throws clauses', which are part of a method's signature and have ZERO >>> impact on how a JVM runs a class file. As far as the JVM is concerned, >>> throws clauses are just a comment. Utterly ignored by javac. >>> >> >> >> No compiler can ignore the throws part of a method signature and be a >> valid >> Java language compiler. Having worked on javac, I know for a fact that >> whether a class symbol is read from a source or class file, its methods >> include all defined throws clauses and enforces their use as the JLS >> dictates. The javac source is publicly available -- check out the Symbol >> and ClassReader classes. >> >> >> You can >>> strip every single one out of every class file and run an app, and the >>> execution of it would be 100% the same. The only change would be in >>> java.lang.reflect's getExceptionTypes() method. >>> >>> I repeat: The JVM *DOES* *NOT* know about checked exceptions. The JVM >>> assumes all exceptions are unchecked, and assumes that javac sorted it >>> all out. This is flawed, obviously, because javac isn't the only tool >>> out there that can make class files. >>> >> >> >> Flawed? The Java Language and the JVM have different specifications; the >> JLS defines checked exceptions, and the JVMS doesn't. The JVM support >> many >> different languages besides Java, most of whom don't define checked >> exceptions. That's not a flaw, but support for language independence. >> The >> reason the JVM considers all exceptions as runtime exceptions is because >> it's the runtime. >> >> >> This is similar to generics in >>> objects, which is also a figment of javac's imagination: On the JVM >>> level, erasure occurs - that info just isn't there. If you want, you >>> can name this 'checked exception erasure'. The notion that exceptions >>> are checked is erased during compilation. >>> >> >> >> Not true. Yes, the JVM doesn't support generics, but classfiles contain >> all >> information needed to correctly compile classes which use them. The same >> is >> true for exceptions, as the JLS requires. >> >> >> The only application in existence that cares about this 'throws >>> clauses' comment in class files is the application called 'javac'. >>> >> >> >> You are going to make engineers support other Java compilers upset with >> this >> incorrect assumption. They all have to support checked exceptions, or >> they >> aren't Java compilers. >> >> It gets worse: JRuby, groovy, Jython, and scala, they ALL feature >> >>> *ZERO* checked exception clauses on methods. They just generate class >>> bytecode with throw statements without caring about the throws clause >>> on methods. >>> >> >> >> Worse? Different languages make different trade-offs between compile and >> runtime checking, and it's a matter of personal preference what trade-offs >> you want. There is no "better" or "worse", which is why the JVM doesn't >> require one or the other. >> >> >> This is why, in java, anytime you interop with code not >>> compiled by javac, you can get checked exceptions in situations where >>> you didn't expect them. >>> >> >> >> WTF? If you are calling libraries written in other languages, those >> libraries throw exceptions as defined by their language specifications. >> If >> you don't like the contracts of those libraries, don't use them. >> >> I give up, >> Tom >> >> >> Millions of classes generated by those >>> compilers are out there right now throwing checked exceptions that >>> escape from methods that do NOT have a 'throws X' clause on them. >>> >>> In other words: There is *NO* guarantee whatsoever in the JVM that >>> checked exceptions can only occur in situations where they are >>> explicitly declared. If your code relies on it, then your code is buggy. >>> >>> >>> Secondly, you mentioned that java wraps exceptions that occur in the >>> constructor with Class.newInstance() into an >>> ExceptionInInitializerError. That's not what happens at all; That >>> exception (ExceptionInInitializerError) is for static initializers and >>> object initializers, not constructors. A practical example will make >>> this clear. Take the following code, save it in Foo.java, compile it, >>> and run it: >>> >>> import java.io.IOException; >>> >>> public class Foo { >>> public static class Test { >>> public Test() throws IOException { >>> throw new IOException(); >>> } >>> } >>> >>> //Note how I didn't add 'throws IOException' in the next line! >>> public static void main(String[] args) throws >>> InstantiationException, IllegalAccessException { >>> Test x = Test.class.newInstance(); >>> } >>> } >>> >>> >>> The result is an IOException. Not a ObjectInstantionException with an >>> IOException as cause; no - an IOException. You can doublecheck this >>> by wrapping the newInstance in a try/catch (Throwable t) block and >>> printing the class name of the resulting t. >>> >>> Thirdly, you misunderstand what my ignoreslist proposal does: It does >>> not silently swallow the exception, that'd be a very stupid way of >>> handling exceptions that you don't -think- can occur. An ignoreslist >>> has zero effect on the execution of a method body. The only difference >>> is that, unlike a throws clause, you don't burden any of the methods >>> that call you to handle the listed exception. It's a signal to javac >>> to disable its rigid checking of making sure any checked exception >>> thrown in the body is also present in that method's 'throws' clause. >>> It's exactly analogous to adding the 'throws' clause, compiling the >>> code, then using a hex editor to remove the throws clause. >>> >>> >>> You're also mistaken in retrofitting Runnable with 'throws Exception': >>> That'll break many thousands of classes out there in real life. You >>> forget that people don't just make Runnables and hand them off to >>> java.lang.Thread; there's plenty of code out there that *receives* >>> Runnables, and that code presumes that its run() method does not throw >>> any checked exceptions. It would be backwards compatible (because, as >>> I said, the JVM doesn't know about these things), but it wouldn't be >>> source compatible; recompiling your code would all of a sudden produce >>> errors. e.g: >>> >>> public void myMethod(Runnable r) { >>> r.run(); >>> } >>> >>> would no longer compile, because all of a sudden 'r.run();' can throw >>> Exception, which I need to catch, or declare as thrown (or, if this >>> proposal is accepted, declare as sneakyThrown/ignore). >>> >>> >>> --Reinier Zwitserloot >>> >>> >>> >>> On May 20, 2009, at 07:01, Ruslan Shevchenko wrote: >>> >>> Here's a trivially simple change to implement, though it has some far >>>>> reaching repercussions for java as a whole: >>>>> >>>>> change the 'rethrows' clause to an ignores clause: Any checked >>>>> exception in the ignores list may be thrown from the method body, but >>>>> is NOT part of the method's checked exception list. It is hence also >>>>> not part of the signature, just like sticking a 'synchronized' >>>>> keyword >>>>> on a method isn't part of its signature, but an implementation >>>>> detail. >>>>> >>>>> >>>>> example: >>>>> >>>>> Runnable r = new Runnable() { >>>>> public void run() ignores UnsupportedEncodingException { >>>>> String x = new String(inBytes, "UTF-8"); >>>>> } >>>>> }; >>>>> >>>>> >>>> And how actually debug such statements ? >>>> //In this example, run() method do nothing, so look on slightly >>>> complex >>>> primer: >>>> >>>> class X >>>> { >>>> String x; >>>> >>>> public void setString(byte[] inBytes) >>>> ignores UnsupportedEncodingException >>>> { >>>> x = new String(inBytes, "UUTF-8"); >>>> } >>>> >>>> public void setAndPrintString(byte[] inBytes) >>>> { >>>> setString(inBytes); >>>> System.out.println("received:"+x); >>>> } >>>> >>>> >>>> } >>>> >>>> Assume, that programmer wrote (by error) "UUTF-8" instead "UTF-8" >>>> >>>> Output of programm will be "received:null". >>>> Reasons for null x in complex programs can be millions. Debugging with >>>> ignoring exception will be extremally hard. >>>> >>>> I. e. wrapping checked exception to runtime is more or less normal; >>>> ignoring will become a very big paint-point. >>>> >>>> Alternative to ignore can be call default thread exception handler. >>>> (handle keyword ?) >>>> >>>> This sounds like blowing up the entire point of checked exceptions, >>>>> but with java moving towards more interoperation with other JVM based >>>>> languages, which almost always throw checked exceptions without >>>>> actually declaring them (Jython, JRuby, Scala -- I can't think of a >>>>> single one other than java itself that has the notion of checked >>>>> exceptions in the first place). If the whole 'java is like the >>>>> assembler of the JVM' story is going to hold water, something like >>>>> this is needed. >>>>> >>>>> >>>> Yes, this is interesting problem. >>>> In theory we have UndeclaredThowableException, but .. wrapping each >>>> invocation of foreign language into it is ineffecient. >>>> >>>> But InvokeDynamic can throws any throwable in declaration, so this >>>> problem >>>> can be solved (on other level) >>>> >>>> For some further support: I doubt anyone seriously holds the position >>>>> that java's checked exception experiment was an unmitigated success. >>>>> There are pain points, here and there. The above example in fact >>>>> includes two of them: The fact that runnable throws no checked >>>>> exceptions is clearly a mistake in regards to threading, because >>>>> Thread objects clearly should handle ANY exception falling out of its >>>>> run() method (and it in fact does, via the unchecked exception >>>>> handler >>>>> mechanism), and there's a general mismatch between main(), which MAY >>>>> throw exceptions, and run(), which may not, even though they are both >>>>> 'thread start points'. Another mistake is >>>>> >>>> >>>> Adding throw exception to signature of Runnable.run does not broke >>>> anything in existent code, so this can be nice library change. >>>> >>>> UnsupportedEncodingExceptions, a checked exception, resulting from a >>>>> call to converting byte arrays to strings using an encoding that is >>>>> guaranteed by the JVM using a string literal, such as "UTF-8". The >>>>> appropriate exception would be UnsupportedEncodingError("This JVM is >>>>> broken. Charset UTF-8 missing. Reinstall it") - which is unchecked. >>>>> >>>>> >>>> Or porgrammer can write UUTF-8 instead UTF-8. It's happens ;) >>>> >>>> In other words, while I'm not ready to write off checked exceptions >>>>> as >>>>> a whole, I am more than ready to acknowledge that the programmer more >>>>> often knows better than the compiler, compared to how often the >>>>> programmer, in laziness or inexperience, abuses this freedom. >>>>> Especially considering that, on the JVM, you really DONT get checked >>>>> exceptions guarantees; any class compiled by anything other than >>>>> javac >>>>> is free to throw checked exceptions without declaring them, and even >>>>> in javac you can technically do this using 'sneaky throw' libraries, >>>>> which use various workarounds, one of which will NEVER go away*. >>>>> We're >>>>> not losing much here, in other words. In fact, the way javac works, >>>>> inexperienced java programmers may erroneously assume that checked >>>>> exceptions couldn't possibly happen unless the checked exception is >>>>> declared. This is not the case. >>>>> >>>>> *) The one that will never go away is java.lang.Class.newInstance(), >>>>> which is functionally defined to sneakily throw on any exceptions >>>>> thrown by the constructor, checked or not, and does NOT wrap them up >>>>> into a wrapper the way java.lang.reflect.Method.invoke() does. This >>>>> >>>> >>>> Its wrapped to java.lang.ExceptionInInitializerError >>>> >>>> >>>> cannot change without breaking backwards compatibility. Another one >>>>> that will never go away is constructing a class on the fly that >>>>> sneaky >>>>> throws, loading it with ClassLoader's load from bytes mechanism, and >>>>> executing it. >>>>> >>>>> >>>> And what is JVM behaviour in such case ? >>>> >>>> >>>>> Attempting to solve this issue with a library requires rather a lot >>>>> of >>>>> ugly boilerplate: >>>>> >>>>> import static Utils.sneakyThrow; >>>>> >>>>> Runnable r = new Runnable() { >>>>> public void run() { >>>>> String x; >>>>> try { >>>>> x = new String(inBytes, "UTF-8"); >>>>> } catch ( UnsupportedEncodingException e ) { >>>>> sneakyThrow(e); >>>>> } >>>>> } >>>>> }; >>>>> >>>>> >>>>> NB: For sanity purposes, the restriction on javac that the try block >>>>> MUST contain at least 1 statement that could throw a checked >>>>> exception >>>>> type that is listed on one of the accompanying catch blocks (other >>>>> than Exception, which you can always catch), should go away; this has >>>>> already been proposed before, and in fact is a backwards >>>>> compatibility >>>>> painpoint for the coin proposal that allows you to rethrow a final >>>>> Exception as if its type is the intersection of all checked types >>>>> thrown by the statements in the try body. >>>>> >>>>> --Reinier Zwitserloot >>>>> Like it? Tip it! >>>>> http://tipit.to >>>>> >>>>> >>>>> >>>>> On May 20, 2009, at 02:22, Mark Mahieu wrote: >>>>> >>>>> Yeah, I suppose I did make it rather more complicated than it needed >>>>>> to be. >>>>>> >>>>>> Thanks for the feedback. >>>>>> >>>>>> Mark >>>>>> >>>>>> >>>>>> On 19 May 2009, at 23:59, Joe Darcy wrote: >>>>>> >>>>>> Hello. >>>>>>> >>>>>>> Hmm; this strikes me as a bit involved for the potential benefits >>>>>>> of the feature. >>>>>>> >>>>>>> -Joe >>>>>>> >>>>>>> On 03/30/09 05:04 PM, Mark Mahieu wrote: >>>>>>> >>>>>>>> Forgot my JLS references in the first one... >>>>>>>> >>>>>>>> >>>>>>>> >>>>>>>> HTML version + prototype available at: >>>>>>>> >>>>>>>> http://slm888.com >>>>>>>> >>>>>>>> >>>>>>>> >>>>>>>> >>>>>>>> Rethrows Clause >>>>>>>> v0.1.1 >>>>>>>> >>>>>>>> >>>>>>>> AUTHOR(S): >>>>>>>> >>>>>>>> Mark Mahieu >>>>>>>> >>>>>>>> >>>>>>>> OVERVIEW >>>>>>>> >>>>>>>> FEATURE SUMMARY: Should be suitable as a summary in a language >>>>>>>> tutorial. >>>>>>>> >>>>>>>> A new clause on method declarations which allows exception >>>>>>>> translations (wrapping and rethrowing as a different type) to be >>>>>>>> cleanly defined separately from the body of the method. In many >>>>>>>> cases, checked exception type names do not then need to be >>>>>>>> repeated in a method's throws clause and in a throw statement in >>>>>>>> the method body. >>>>>>>> >>>>>>>> >>>>>>>> MAJOR ADVANTAGE: What makes the proposal a favorable change? >>>>>>>> >>>>>>>> The proposal adds direct support for a common idiom in daily use >>>>>>>> by Java programmers worldwide, allowing them to express their >>>>>>>> intentions with greater clarity and ease. In comparison with >>>>>>>> some proposals, this is an attempt to make dealing with checked >>>>>>>> exceptions easier by increasing the expressiveness of exception >>>>>>>> handling code in general, rather than by attempting to deprecate >>>>>>>> checked exceptions in favour of unchecked exceptions. >>>>>>>> >>>>>>>> >>>>>>>> MAJOR BENEFIT: Why is the platform better if the proposal is >>>>>>>> adopted? >>>>>>>> >>>>>>>> There is a reduction in the amount of boilerplate Java >>>>>>>> programmers have to read and write for code dealing with checked >>>>>>>> exceptions. Declarations specifying both thrown and rethrown >>>>>>>> (wrapped) exceptions are kept together, aiding comprehension of >>>>>>>> the code. >>>>>>>> >>>>>>>> >>>>>>>> MAJOR DISADVANTAGE: There is always a cost. >>>>>>>> >>>>>>>> As with any syntax sugar which enables an alternative way of >>>>>>>> expressing an existing idiom, programmers may be tempted to use >>>>>>>> it even when the existing idiom would be more appropriate. >>>>>>>> >>>>>>>> >>>>>>>> ALTERNATIVES: Can the benefits and advantages be had some way >>>>>>>> without a language change? >>>>>>>> >>>>>>>> No. >>>>>>>> >>>>>>>> >>>>>>>> EXAMPLES >>>>>>>> >>>>>>>> SIMPLE EXAMPLE: Show the simplest possible program utilizing the >>>>>>>> new feature. >>>>>>>> >>>>>>>> >>>>>>>> Before: >>>>>>>> >>>>>>>> void before() throws ConfigException { >>>>>>>> try { >>>>>>>> Class.forName("where.is.the.Code"); >>>>>>>> } >>>>>>>> catch (ClassNotFoundException e) { >>>>>>>> throw new ConfigException(e); >>>>>>>> } >>>>>>>> } >>>>>>>> >>>>>>>> After: >>>>>>>> >>>>>>>> void after() >>>>>>>> catch ClassNotFoundException throw ConfigException { >>>>>>>> >>>>>>>> Class.forName("here.is.the.Code"); >>>>>>>> } >>>>>>>> >>>>>>>> >>>>>>>> ADVANCED EXAMPLE: Show advanced usage(s) of the feature. >>>>>>>> >>>>>>>> Before: >>>>>>>> >>>>>>>> void suspendAccount() >>>>>>>> throws AuthorizationException, >>>>>>>> PersistenceException { >>>>>>>> try { >>>>>>>> checkMyAuthoritah(); >>>>>>>> db.update(/*...*/); >>>>>>>> log.recordInfo(/*...*/); >>>>>>>> } >>>>>>>> catch (InfernalDBException e) { >>>>>>>> throw new PersistenceException(e); >>>>>>>> } >>>>>>>> catch (InfernalLogException e) { >>>>>>>> throw new RuntimeException(e); >>>>>>>> } >>>>>>>> } >>>>>>>> >>>>>>>> After: >>>>>>>> >>>>>>>> void suspendAccount() >>>>>>>> throws AuthorizationException >>>>>>>> catch InfernalDBException throw PersistenceException, >>>>>>>> InfernalLogException throw RuntimeException { >>>>>>>> >>>>>>>> checkMyAuthoritah(); >>>>>>>> db.update(/*...*/); >>>>>>>> log.recordInfo(/*...*/); >>>>>>>> } >>>>>>>> >>>>>>>> >>>>>>>> DETAILS >>>>>>>> >>>>>>>> SPECIFICATION: Describe how the proposal affects the grammar, >>>>>>>> type system, and meaning of expressions and statements in the >>>>>>>> Java Programming Language as well as any other known impacts. >>>>>>>> >>>>>>>> The syntactic grammar is modified to allow an optional rethrows >>>>>>>> clause immediately prior to a MethodBody: >>>>>>>> >>>>>>>> MethodDeclaratorRest: >>>>>>>> FormalParameters {[]} [throws >>>>>>>> QualifiedIdentifierList] ( ( [catch ExceptionTranslationList] >>>>>>>> MethodBody ) | ; ) >>>>>>>> >>>>>>>> ExceptionTranslationList: >>>>>>>> QualifiedIdentifier throw QualifiedIdentifier >>>>>>>> { , ExceptionTranslationList } >>>>>>>> >>>>>>>> >>>>>>>> >>>>>>>> JLSv3 ?8.4.6 : A rethrows clause lists one or more exception >>>>>>>> translations, each translation consisting of a caught type C and >>>>>>>> a translated type T for which all of the following must hold: >>>>>>>> * C <: java.lang.Exception >>>>>>>> * T < java.lang.Throwable >>>>>>>> * Neither C nor T is a type variable. >>>>>>>> * T has an accessible constructor suitable for rethrowing a >>>>>>>> value of type C (see below). >>>>>>>> * T is not the same type as C. >>>>>>>> >>>>>>>> Any exceptions thrown by the method body which are a subtype of a >>>>>>>> caught exception type in the rethrows clause, are rethrown as the >>>>>>>> corresponding translated exception type. >>>>>>>> >>>>>>>> For a given translated type T with corresponding caught type C, if >>>>>>>> T has an accessible constructor accepting a value of type C, then >>>>>>>> the translation is equivalent to the following: >>>>>>>> >>>>>>>> catch (C e) { >>>>>>>> throw new T(e); >>>>>>>> } >>>>>>>> >>>>>>>> Otherwise it must have an accessible no argument constructor, and >>>>>>>> the translation is equivalent to: >>>>>>>> >>>>>>>> catch (C e) { >>>>>>>> throw new T().initCause(e); >>>>>>>> } >>>>>>>> >>>>>>>> >>>>>>>> A rethrows clause does not restrict which types may appear in a >>>>>>>> throws clause for the same method. In particular, for a given >>>>>>>> caught type C in the rethrows clause, it is permitted for some >>>>>>>> type C1 :> C to also be listed in the throws clause. >>>>>>>> >>>>>>>> >>>>>>>> JLSv3 ?8.2 : The set of exception types declared to be thrown by >>>>>>>> a method is the union of: >>>>>>>> * the types in the throws clause >>>>>>>> * the translated types in the rethrow clause >>>>>>>> * the types thrown by the translated types' selected >>>>>>>> constructors >>>>>>>> >>>>>>>> JLSv3 ?11.2.2 : For the purposes of exception analysis, the set >>>>>>>> of checked exception types which may be thrown by the method's >>>>>>>> body is the union of: >>>>>>>> * the types in the throws clause >>>>>>>> * the caught types in the rethrows clause >>>>>>>> >>>>>>>> JLSv3 ?11.2.3 : It is a compile-time error if a rethrows clause >>>>>>>> contains a translation from a checked exception type C but there >>>>>>>> exists no checked exception type E such that all of the following >>>>>>>> hold: >>>>>>>> * E <: C >>>>>>>> * The method body can throw E >>>>>>>> * No preceding translation in the rethrow clause catches E or >>>>>>>> a supertype of E >>>>>>>> unless C is the class java.lang.Exception. >>>>>>>> >>>>>>>> JLSv3 ?13.4.21 : Changes to the rethrows clause of methods or >>>>>>>> constructors do not break compatibility with existing binaries; >>>>>>>> these clauses are checked only at compile time. >>>>>>>> >>>>>>>> >>>>>>>> >>>>>>>> COMPILATION: How would the feature be compiled to class files? >>>>>>>> Show how the simple and advanced examples would be compiled. >>>>>>>> Compilation can be expressed as at least one of a desugaring to >>>>>>>> existing source constructs and a translation down to bytecode. If >>>>>>>> a new bytecode is used or the semantics of an existing bytecode >>>>>>>> are changed, describe those changes, including how they impact >>>>>>>> verification. Also discuss any new class file attributes that are >>>>>>>> introduced. Note that there are many downstream tools that >>>>>>>> consume class files and that they may to be updated to support >>>>>>>> the proposal! >>>>>>>> >>>>>>>> A simple desugaring could consist of enclosing the method body's >>>>>>>> statements in a try statement, with catch clauses for each >>>>>>>> translated exception type. For example, the following method: >>>>>>>> >>>>>>>> Method findMethod() >>>>>>>> catch ClassNotFoundException throw ConfigException, >>>>>>>> NoSuchMethodException throw ConfigException { >>>>>>>> >>>>>>>> Class c = Class.forName("some.Thing"); >>>>>>>> return c.getDeclaredMethod("execute", null); >>>>>>>> } >>>>>>>> >>>>>>>> would be desugared to: >>>>>>>> >>>>>>>> Method findMethod() >>>>>>>> throws ConfigException { >>>>>>>> try { >>>>>>>> Class c = Class.forName("some.Thing"); >>>>>>>> return c.getDeclaredMethod("execute", null); >>>>>>>> } >>>>>>>> catch (ClassNotFoundException e) { >>>>>>>> throw new ConfigException(e); >>>>>>>> } >>>>>>>> catch (MethodNotFoundException e) { >>>>>>>> throw new ConfigException(e); >>>>>>>> } >>>>>>>> } >>>>>>>> >>>>>>>> No changes to the classfile format are required. >>>>>>>> >>>>>>>> >>>>>>>> TESTING: How can the feature be tested? >>>>>>>> >>>>>>>> An initial set of jtreg tests is included in the prototype. >>>>>>>> >>>>>>>> >>>>>>>> LIBRARY SUPPORT: Are any supporting libraries needed for the >>>>>>>> feature? >>>>>>>> >>>>>>>> No >>>>>>>> >>>>>>>> >>>>>>>> REFLECTIVE APIS: Do any of the various and sundry reflection APIs >>>>>>>> need to be updated? This list of reflective APIs includes but is >>>>>>>> not limited to core reflection (java.lang.Class and >>>>>>>> java.lang.reflect.*), javax.lang.model.*, the doclet API, and >>>>>>>> JPDA. >>>>>>>> >>>>>>>> com.sun.source.tree.MethodTree would require updates to access >>>>>>>> the rethrows clause's caught and translated types. >>>>>>>> >>>>>>>> >>>>>>>> OTHER CHANGES: Do any other parts of the platform need be updated >>>>>>>> too? Possibilities include but are not limited to JNI, >>>>>>>> serialization, and output of the javadoc tool. >>>>>>>> >>>>>>>> No >>>>>>>> >>>>>>>> >>>>>>>> MIGRATION: Sketch how a code base could be converted, manually or >>>>>>>> automatically, to use the new feature. >>>>>>>> >>>>>>>> Catch clauses which simply wrap and rethrow an exception as >>>>>>>> another exception type not caught in an enclosing scope, can be >>>>>>>> trivially replaced with a rethrows clause, either manually or >>>>>>>> automatically. >>>>>>>> >>>>>>>> It should be possible for tools to offer bidirectional >>>>>>>> conversions such that an exception translation may be moved back >>>>>>>> into the method body if it is subsequently decided that >>>>>>>> additional logic is required. >>>>>>>> >>>>>>>> >>>>>>>> COMPATIBILITY >>>>>>>> >>>>>>>> BREAKING CHANGES: Are any previously valid programs now invalid? >>>>>>>> If so, list one. >>>>>>>> >>>>>>>> No >>>>>>>> >>>>>>>> >>>>>>>> EXISTING PROGRAMS: How do source and class files of earlier >>>>>>>> platform versions interact with the feature? Can any new >>>>>>>> overloadings occur? Can any new overriding occur? >>>>>>>> >>>>>>>> The semantics of existing class files and legal source files are >>>>>>>> unchanged by this feature. >>>>>>>> >>>>>>>> >>>>>>>> REFERENCES >>>>>>>> >>>>>>>> EXISTING BUGS: Please include a list of any existing Sun bug ids >>>>>>>> related to this proposal. >>>>>>>> >>>>>>>> http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6534270 >>>>>>>> (similar, but emphasizes unchecked exceptions) >>>>>>>> >>>>>>>> >>>>>>>> URL FOR PROTOTYPE (optional): >>>>>>>> >>>>>>>> http://slm888.com/javac >>>>>>>> >>>>>>>> >>>>>>>> >>>>>>>> >>>>>>> >>>>>> >>>>>> >>>>> >>>>> >>>>> >>>> >>>> >>> >>> >>> >> > From Joe.Darcy at Sun.COM Wed May 20 11:02:26 2009 From: Joe.Darcy at Sun.COM (Joseph D. Darcy) Date: Wed, 20 May 2009 11:02:26 -0700 Subject: Checked Exceptions do not exist on the JVM. In-Reply-To: References: <39084932-B2CC-4B91-97EA-006FE21301F0@googlemail.com> <4A1339ED.8090309@sun.com> <68BF955A-9796-44F7-9E97-94BBB43ADCC5@zwitserloot.com> <988330f1d03fc629490d5dffa3fc2d25.squirrel@wmail.gradsoft.ua> Message-ID: <4A1445B2.3070304@sun.com> Well said Tom. Additionally, on the point of interfacing with other language in Java, the possibility of having what are in Java checked exceptions thrown by the caller argue for Dynamic call sites to be regarded as being able to throw Exception so that the existing Java semantics and checking can be preserved. -Joe Tom Ball wrote: > I don't consider "Ruslan, you've got it all wrong" an example of opening a > "perfectly civil email", it sounds like bullying. This isn't slashdot, it's > a forum for discussions on possible small improvements to the Java > language. So I shouldn't have responded with the same tone as your message, > and for that I apologize to the wider group. > > An "it's possible to write bad code" argument doesn't refute other people's > valid arguments. Developers are always capable of writing bad code, and > anyone who designs a language or runtime where it's impossible will have > trouble finding adoption because it's too restrictive. Who cares if sneaky > throw works? If a library abuses that hack, don't use it. > > The purpose of throws clauses is to better describe the contract a method > offers for its callers: it only accepts parameters of a certain type, it > returns an instance of a specific type, and under certain (hopefully > documented) conditions it may throw specific exceptions. Checked exceptions > are intended to call out specific exceptions that the library writer > believes the caller should be able to recover from, and therefore should > handle or forward. If a library writer subverts the contract of his own > method, well, that's a shame but doesn't necessarily call for changes to the > language. If a non-Java language has libraries which throw what are in Java > checked exceptions, then write Java code which does more checking at runtime > since that's apparently what the other language requires (or don't use those > libraries). > > This isn't a problem, and so there is nothing about it that needs fixing in > Java 7. > > Tom > > On Wed, May 20, 2009 at 9:39 AM, Reinier Zwitserloot < > reinier at zwitserloot.com> wrote: > > >> Tom, here are two class files: >> >> Foo.class >> Bar.class >> >> which one adheres to the JLS checked exception model, and which one has >> methods that leak checked exceptions without declaring them? >> >> I can't tell. Can you? >> >> You can quote me JLS specs all day long, mis-interpret my words and write >> in a denigrating fashion, but none of that changes the plain fact: >> >> You CAN NOT RELY ON THROWS CLAUSES. Checked exceptions can fall out of >> *any* method *anywhere*. Period. I thought when I mentioned "checked >> exceptions in situations where you didn't expect them", it was obvious from >> context that I meant: checked exceptions falling out of methods that don't >> declare them, but apparently I need to spell this out for you. >> >> You also conveniently forgot that, even if you're only using javac, you can >> still get sneakyThrow: You can expicitly sneakyThrow via class file >> construction or using the .newInstance() trick, or get accidental >> sneakyThrow when compiling against v1 of a class, but running with v2 (which >> added a bunch of checked exceptions). Point me to the entry in the JLS that >> makes this impossible, please. It doesn't exist, so, take your pedantic >> whinging about "JLS spec", print it out, and eat it*. >> >> >> *) I get annoyed when people write 'WTF' and 'I give up' in response to a >> perfectly civil email. >> >> >> Example: >> >> public class Foo { >> public static void foo() {} >> } >> >> as Foo.class >> >> and this: >> >> public class Bar { >> public static void main(String[] args) { >> Foo.foo(); >> } >> } >> >> as Bar.class. >> >> Then edit Foo.java to this and recompile (but don't recompile Bar.java!), >> then rerun Bar: >> >> public class Foo { >> public static void foo() throws java.io.IOException { >> throw new java.io.IOException("Apparently this will make Tom Ball's >> head explode. Whoops!"); >> } >> } >> >> ... and behold! Tom Ball's head explodes. >> >> --Reinier Zwitserloot >> >> >> >> >> On May 20, 2009, at 18:11, Tom Ball wrote: >> >> On Wed, May 20, 2009 at 6:35 AM, Reinier Zwitserloot < >> >>> reinier at zwitserloot.com> wrote: >>> >>> Checked exceptions do not exist. >>> >>> Sure they do, but they are a Java language concept, not a JVM one. The >>> same >>> is true for lots of other Java language features. >>> >>> That's right. They don't. There's no such thing. It's all a figment of >>> >>> >>>> javac. >>>> >>>> >>> You must mean that checked exceptions are defined by the Java Language >>> Specification. javac is just a compiler that adheres to the JLS, like >>> many >>> other Java compilers. >>> >>> >>> The JVM does not have checked exceptions. All it knows about is >>> >>>> 'throws clauses', which are part of a method's signature and have ZERO >>>> impact on how a JVM runs a class file. As far as the JVM is concerned, >>>> throws clauses are just a comment. Utterly ignored by javac. >>>> >>>> >>> No compiler can ignore the throws part of a method signature and be a >>> valid >>> Java language compiler. Having worked on javac, I know for a fact that >>> whether a class symbol is read from a source or class file, its methods >>> include all defined throws clauses and enforces their use as the JLS >>> dictates. The javac source is publicly available -- check out the Symbol >>> and ClassReader classes. >>> >>> >>> You can >>> >>>> strip every single one out of every class file and run an app, and the >>>> execution of it would be 100% the same. The only change would be in >>>> java.lang.reflect's getExceptionTypes() method. >>>> >>>> I repeat: The JVM *DOES* *NOT* know about checked exceptions. The JVM >>>> assumes all exceptions are unchecked, and assumes that javac sorted it >>>> all out. This is flawed, obviously, because javac isn't the only tool >>>> out there that can make class files. >>>> >>>> >>> Flawed? The Java Language and the JVM have different specifications; the >>> JLS defines checked exceptions, and the JVMS doesn't. The JVM support >>> many >>> different languages besides Java, most of whom don't define checked >>> exceptions. That's not a flaw, but support for language independence. >>> The >>> reason the JVM considers all exceptions as runtime exceptions is because >>> it's the runtime. >>> >>> >>> This is similar to generics in >>> >>>> objects, which is also a figment of javac's imagination: On the JVM >>>> level, erasure occurs - that info just isn't there. If you want, you >>>> can name this 'checked exception erasure'. The notion that exceptions >>>> are checked is erased during compilation. >>>> >>>> >>> Not true. Yes, the JVM doesn't support generics, but classfiles contain >>> all >>> information needed to correctly compile classes which use them. The same >>> is >>> true for exceptions, as the JLS requires. >>> >>> >>> The only application in existence that cares about this 'throws >>> >>>> clauses' comment in class files is the application called 'javac'. >>>> >>>> >>> You are going to make engineers support other Java compilers upset with >>> this >>> incorrect assumption. They all have to support checked exceptions, or >>> they >>> aren't Java compilers. >>> >>> It gets worse: JRuby, groovy, Jython, and scala, they ALL feature >>> >>> >>>> *ZERO* checked exception clauses on methods. They just generate class >>>> bytecode with throw statements without caring about the throws clause >>>> on methods. >>>> >>>> >>> Worse? Different languages make different trade-offs between compile and >>> runtime checking, and it's a matter of personal preference what trade-offs >>> you want. There is no "better" or "worse", which is why the JVM doesn't >>> require one or the other. >>> >>> >>> This is why, in java, anytime you interop with code not >>> >>>> compiled by javac, you can get checked exceptions in situations where >>>> you didn't expect them. >>>> >>>> >>> WTF? If you are calling libraries written in other languages, those >>> libraries throw exceptions as defined by their language specifications. >>> If >>> you don't like the contracts of those libraries, don't use them. >>> >>> I give up, >>> Tom >>> >>> >>> Millions of classes generated by those >>> >>>> compilers are out there right now throwing checked exceptions that >>>> escape from methods that do NOT have a 'throws X' clause on them. >>>> >>>> In other words: There is *NO* guarantee whatsoever in the JVM that >>>> checked exceptions can only occur in situations where they are >>>> explicitly declared. If your code relies on it, then your code is buggy. >>>> >>>> >>>> Secondly, you mentioned that java wraps exceptions that occur in the >>>> constructor with Class.newInstance() into an >>>> ExceptionInInitializerError. That's not what happens at all; That >>>> exception (ExceptionInInitializerError) is for static initializers and >>>> object initializers, not constructors. A practical example will make >>>> this clear. Take the following code, save it in Foo.java, compile it, >>>> and run it: >>>> >>>> import java.io.IOException; >>>> >>>> public class Foo { >>>> public static class Test { >>>> public Test() throws IOException { >>>> throw new IOException(); >>>> } >>>> } >>>> >>>> //Note how I didn't add 'throws IOException' in the next line! >>>> public static void main(String[] args) throws >>>> InstantiationException, IllegalAccessException { >>>> Test x = Test.class.newInstance(); >>>> } >>>> } >>>> >>>> >>>> The result is an IOException. Not a ObjectInstantionException with an >>>> IOException as cause; no - an IOException. You can doublecheck this >>>> by wrapping the newInstance in a try/catch (Throwable t) block and >>>> printing the class name of the resulting t. >>>> >>>> Thirdly, you misunderstand what my ignoreslist proposal does: It does >>>> not silently swallow the exception, that'd be a very stupid way of >>>> handling exceptions that you don't -think- can occur. An ignoreslist >>>> has zero effect on the execution of a method body. The only difference >>>> is that, unlike a throws clause, you don't burden any of the methods >>>> that call you to handle the listed exception. It's a signal to javac >>>> to disable its rigid checking of making sure any checked exception >>>> thrown in the body is also present in that method's 'throws' clause. >>>> It's exactly analogous to adding the 'throws' clause, compiling the >>>> code, then using a hex editor to remove the throws clause. >>>> >>>> >>>> You're also mistaken in retrofitting Runnable with 'throws Exception': >>>> That'll break many thousands of classes out there in real life. You >>>> forget that people don't just make Runnables and hand them off to >>>> java.lang.Thread; there's plenty of code out there that *receives* >>>> Runnables, and that code presumes that its run() method does not throw >>>> any checked exceptions. It would be backwards compatible (because, as >>>> I said, the JVM doesn't know about these things), but it wouldn't be >>>> source compatible; recompiling your code would all of a sudden produce >>>> errors. e.g: >>>> >>>> public void myMethod(Runnable r) { >>>> r.run(); >>>> } >>>> >>>> would no longer compile, because all of a sudden 'r.run();' can throw >>>> Exception, which I need to catch, or declare as thrown (or, if this >>>> proposal is accepted, declare as sneakyThrown/ignore). >>>> >>>> >>>> --Reinier Zwitserloot >>>> >>>> >>>> >>>> On May 20, 2009, at 07:01, Ruslan Shevchenko wrote: >>>> >>>> Here's a trivially simple change to implement, though it has some far >>>> >>>>>> reaching repercussions for java as a whole: >>>>>> >>>>>> change the 'rethrows' clause to an ignores clause: Any checked >>>>>> exception in the ignores list may be thrown from the method body, but >>>>>> is NOT part of the method's checked exception list. It is hence also >>>>>> not part of the signature, just like sticking a 'synchronized' >>>>>> keyword >>>>>> on a method isn't part of its signature, but an implementation >>>>>> detail. >>>>>> >>>>>> >>>>>> example: >>>>>> >>>>>> Runnable r = new Runnable() { >>>>>> public void run() ignores UnsupportedEncodingException { >>>>>> String x = new String(inBytes, "UTF-8"); >>>>>> } >>>>>> }; >>>>>> >>>>>> >>>>>> >>>>> And how actually debug such statements ? >>>>> //In this example, run() method do nothing, so look on slightly >>>>> complex >>>>> primer: >>>>> >>>>> class X >>>>> { >>>>> String x; >>>>> >>>>> public void setString(byte[] inBytes) >>>>> ignores UnsupportedEncodingException >>>>> { >>>>> x = new String(inBytes, "UUTF-8"); >>>>> } >>>>> >>>>> public void setAndPrintString(byte[] inBytes) >>>>> { >>>>> setString(inBytes); >>>>> System.out.println("received:"+x); >>>>> } >>>>> >>>>> >>>>> } >>>>> >>>>> Assume, that programmer wrote (by error) "UUTF-8" instead "UTF-8" >>>>> >>>>> Output of programm will be "received:null". >>>>> Reasons for null x in complex programs can be millions. Debugging with >>>>> ignoring exception will be extremally hard. >>>>> >>>>> I. e. wrapping checked exception to runtime is more or less normal; >>>>> ignoring will become a very big paint-point. >>>>> >>>>> Alternative to ignore can be call default thread exception handler. >>>>> (handle keyword ?) >>>>> >>>>> This sounds like blowing up the entire point of checked exceptions, >>>>> >>>>>> but with java moving towards more interoperation with other JVM based >>>>>> languages, which almost always throw checked exceptions without >>>>>> actually declaring them (Jython, JRuby, Scala -- I can't think of a >>>>>> single one other than java itself that has the notion of checked >>>>>> exceptions in the first place). If the whole 'java is like the >>>>>> assembler of the JVM' story is going to hold water, something like >>>>>> this is needed. >>>>>> >>>>>> >>>>>> >>>>> Yes, this is interesting problem. >>>>> In theory we have UndeclaredThowableException, but .. wrapping each >>>>> invocation of foreign language into it is ineffecient. >>>>> >>>>> But InvokeDynamic can throws any throwable in declaration, so this >>>>> problem >>>>> can be solved (on other level) >>>>> >>>>> For some further support: I doubt anyone seriously holds the position >>>>> >>>>>> that java's checked exception experiment was an unmitigated success. >>>>>> There are pain points, here and there. The above example in fact >>>>>> includes two of them: The fact that runnable throws no checked >>>>>> exceptions is clearly a mistake in regards to threading, because >>>>>> Thread objects clearly should handle ANY exception falling out of its >>>>>> run() method (and it in fact does, via the unchecked exception >>>>>> handler >>>>>> mechanism), and there's a general mismatch between main(), which MAY >>>>>> throw exceptions, and run(), which may not, even though they are both >>>>>> 'thread start points'. Another mistake is >>>>>> >>>>>> >>>>> Adding throw exception to signature of Runnable.run does not broke >>>>> anything in existent code, so this can be nice library change. >>>>> >>>>> UnsupportedEncodingExceptions, a checked exception, resulting from a >>>>> >>>>>> call to converting byte arrays to strings using an encoding that is >>>>>> guaranteed by the JVM using a string literal, such as "UTF-8". The >>>>>> appropriate exception would be UnsupportedEncodingError("This JVM is >>>>>> broken. Charset UTF-8 missing. Reinstall it") - which is unchecked. >>>>>> >>>>>> >>>>>> >>>>> Or porgrammer can write UUTF-8 instead UTF-8. It's happens ;) >>>>> >>>>> In other words, while I'm not ready to write off checked exceptions >>>>> >>>>>> as >>>>>> a whole, I am more than ready to acknowledge that the programmer more >>>>>> often knows better than the compiler, compared to how often the >>>>>> programmer, in laziness or inexperience, abuses this freedom. >>>>>> Especially considering that, on the JVM, you really DONT get checked >>>>>> exceptions guarantees; any class compiled by anything other than >>>>>> javac >>>>>> is free to throw checked exceptions without declaring them, and even >>>>>> in javac you can technically do this using 'sneaky throw' libraries, >>>>>> which use various workarounds, one of which will NEVER go away*. >>>>>> We're >>>>>> not losing much here, in other words. In fact, the way javac works, >>>>>> inexperienced java programmers may erroneously assume that checked >>>>>> exceptions couldn't possibly happen unless the checked exception is >>>>>> declared. This is not the case. >>>>>> >>>>>> *) The one that will never go away is java.lang.Class.newInstance(), >>>>>> which is functionally defined to sneakily throw on any exceptions >>>>>> thrown by the constructor, checked or not, and does NOT wrap them up >>>>>> into a wrapper the way java.lang.reflect.Method.invoke() does. This >>>>>> >>>>>> >>>>> Its wrapped to java.lang.ExceptionInInitializerError >>>>> >>>>> >>>>> cannot change without breaking backwards compatibility. Another one >>>>> >>>>>> that will never go away is constructing a class on the fly that >>>>>> sneaky >>>>>> throws, loading it with ClassLoader's load from bytes mechanism, and >>>>>> executing it. >>>>>> >>>>>> >>>>>> >>>>> And what is JVM behaviour in such case ? >>>>> >>>>> >>>>> >>>>>> Attempting to solve this issue with a library requires rather a lot >>>>>> of >>>>>> ugly boilerplate: >>>>>> >>>>>> import static Utils.sneakyThrow; >>>>>> >>>>>> Runnable r = new Runnable() { >>>>>> public void run() { >>>>>> String x; >>>>>> try { >>>>>> x = new String(inBytes, "UTF-8"); >>>>>> } catch ( UnsupportedEncodingException e ) { >>>>>> sneakyThrow(e); >>>>>> } >>>>>> } >>>>>> }; >>>>>> >>>>>> >>>>>> NB: For sanity purposes, the restriction on javac that the try block >>>>>> MUST contain at least 1 statement that could throw a checked >>>>>> exception >>>>>> type that is listed on one of the accompanying catch blocks (other >>>>>> than Exception, which you can always catch), should go away; this has >>>>>> already been proposed before, and in fact is a backwards >>>>>> compatibility >>>>>> painpoint for the coin proposal that allows you to rethrow a final >>>>>> Exception as if its type is the intersection of all checked types >>>>>> thrown by the statements in the try body. >>>>>> >>>>>> --Reinier Zwitserloot >>>>>> Like it? Tip it! >>>>>> http://tipit.to >>>>>> >>>>>> >>>>>> >>>>>> On May 20, 2009, at 02:22, Mark Mahieu wrote: >>>>>> >>>>>> Yeah, I suppose I did make it rather more complicated than it needed >>>>>> >>>>>>> to be. >>>>>>> >>>>>>> Thanks for the feedback. >>>>>>> >>>>>>> Mark >>>>>>> >>>>>>> >>>>>>> On 19 May 2009, at 23:59, Joe Darcy wrote: >>>>>>> >>>>>>> Hello. >>>>>>> >>>>>>>> Hmm; this strikes me as a bit involved for the potential benefits >>>>>>>> of the feature. >>>>>>>> >>>>>>>> -Joe >>>>>>>> >>>>>>>> On 03/30/09 05:04 PM, Mark Mahieu wrote: >>>>>>>> >>>>>>>> >>>>>>>>> Forgot my JLS references in the first one... >>>>>>>>> >>>>>>>>> >>>>>>>>> >>>>>>>>> HTML version + prototype available at: >>>>>>>>> >>>>>>>>> http://slm888.com >>>>>>>>> >>>>>>>>> >>>>>>>>> >>>>>>>>> >>>>>>>>> Rethrows Clause >>>>>>>>> v0.1.1 >>>>>>>>> >>>>>>>>> >>>>>>>>> AUTHOR(S): >>>>>>>>> >>>>>>>>> Mark Mahieu >>>>>>>>> >>>>>>>>> >>>>>>>>> OVERVIEW >>>>>>>>> >>>>>>>>> FEATURE SUMMARY: Should be suitable as a summary in a language >>>>>>>>> tutorial. >>>>>>>>> >>>>>>>>> A new clause on method declarations which allows exception >>>>>>>>> translations (wrapping and rethrowing as a different type) to be >>>>>>>>> cleanly defined separately from the body of the method. In many >>>>>>>>> cases, checked exception type names do not then need to be >>>>>>>>> repeated in a method's throws clause and in a throw statement in >>>>>>>>> the method body. >>>>>>>>> >>>>>>>>> >>>>>>>>> MAJOR ADVANTAGE: What makes the proposal a favorable change? >>>>>>>>> >>>>>>>>> The proposal adds direct support for a common idiom in daily use >>>>>>>>> by Java programmers worldwide, allowing them to express their >>>>>>>>> intentions with greater clarity and ease. In comparison with >>>>>>>>> some proposals, this is an attempt to make dealing with checked >>>>>>>>> exceptions easier by increasing the expressiveness of exception >>>>>>>>> handling code in general, rather than by attempting to deprecate >>>>>>>>> checked exceptions in favour of unchecked exceptions. >>>>>>>>> >>>>>>>>> >>>>>>>>> MAJOR BENEFIT: Why is the platform better if the proposal is >>>>>>>>> adopted? >>>>>>>>> >>>>>>>>> There is a reduction in the amount of boilerplate Java >>>>>>>>> programmers have to read and write for code dealing with checked >>>>>>>>> exceptions. Declarations specifying both thrown and rethrown >>>>>>>>> (wrapped) exceptions are kept together, aiding comprehension of >>>>>>>>> the code. >>>>>>>>> >>>>>>>>> >>>>>>>>> MAJOR DISADVANTAGE: There is always a cost. >>>>>>>>> >>>>>>>>> As with any syntax sugar which enables an alternative way of >>>>>>>>> expressing an existing idiom, programmers may be tempted to use >>>>>>>>> it even when the existing idiom would be more appropriate. >>>>>>>>> >>>>>>>>> >>>>>>>>> ALTERNATIVES: Can the benefits and advantages be had some way >>>>>>>>> without a language change? >>>>>>>>> >>>>>>>>> No. >>>>>>>>> >>>>>>>>> >>>>>>>>> EXAMPLES >>>>>>>>> >>>>>>>>> SIMPLE EXAMPLE: Show the simplest possible program utilizing the >>>>>>>>> new feature. >>>>>>>>> >>>>>>>>> >>>>>>>>> Before: >>>>>>>>> >>>>>>>>> void before() throws ConfigException { >>>>>>>>> try { >>>>>>>>> Class.forName("where.is.the.Code"); >>>>>>>>> } >>>>>>>>> catch (ClassNotFoundException e) { >>>>>>>>> throw new ConfigException(e); >>>>>>>>> } >>>>>>>>> } >>>>>>>>> >>>>>>>>> After: >>>>>>>>> >>>>>>>>> void after() >>>>>>>>> catch ClassNotFoundException throw ConfigException { >>>>>>>>> >>>>>>>>> Class.forName("here.is.the.Code"); >>>>>>>>> } >>>>>>>>> >>>>>>>>> >>>>>>>>> ADVANCED EXAMPLE: Show advanced usage(s) of the feature. >>>>>>>>> >>>>>>>>> Before: >>>>>>>>> >>>>>>>>> void suspendAccount() >>>>>>>>> throws AuthorizationException, >>>>>>>>> PersistenceException { >>>>>>>>> try { >>>>>>>>> checkMyAuthoritah(); >>>>>>>>> db.update(/*...*/); >>>>>>>>> log.recordInfo(/*...*/); >>>>>>>>> } >>>>>>>>> catch (InfernalDBException e) { >>>>>>>>> throw new PersistenceException(e); >>>>>>>>> } >>>>>>>>> catch (InfernalLogException e) { >>>>>>>>> throw new RuntimeException(e); >>>>>>>>> } >>>>>>>>> } >>>>>>>>> >>>>>>>>> After: >>>>>>>>> >>>>>>>>> void suspendAccount() >>>>>>>>> throws AuthorizationException >>>>>>>>> catch InfernalDBException throw PersistenceException, >>>>>>>>> InfernalLogException throw RuntimeException { >>>>>>>>> >>>>>>>>> checkMyAuthoritah(); >>>>>>>>> db.update(/*...*/); >>>>>>>>> log.recordInfo(/*...*/); >>>>>>>>> } >>>>>>>>> >>>>>>>>> >>>>>>>>> DETAILS >>>>>>>>> >>>>>>>>> SPECIFICATION: Describe how the proposal affects the grammar, >>>>>>>>> type system, and meaning of expressions and statements in the >>>>>>>>> Java Programming Language as well as any other known impacts. >>>>>>>>> >>>>>>>>> The syntactic grammar is modified to allow an optional rethrows >>>>>>>>> clause immediately prior to a MethodBody: >>>>>>>>> >>>>>>>>> MethodDeclaratorRest: >>>>>>>>> FormalParameters {[]} [throws >>>>>>>>> QualifiedIdentifierList] ( ( [catch ExceptionTranslationList] >>>>>>>>> MethodBody ) | ; ) >>>>>>>>> >>>>>>>>> ExceptionTranslationList: >>>>>>>>> QualifiedIdentifier throw QualifiedIdentifier >>>>>>>>> { , ExceptionTranslationList } >>>>>>>>> >>>>>>>>> >>>>>>>>> >>>>>>>>> JLSv3 ?8.4.6 : A rethrows clause lists one or more exception >>>>>>>>> translations, each translation consisting of a caught type C and >>>>>>>>> a translated type T for which all of the following must hold: >>>>>>>>> * C <: java.lang.Exception >>>>>>>>> * T < java.lang.Throwable >>>>>>>>> * Neither C nor T is a type variable. >>>>>>>>> * T has an accessible constructor suitable for rethrowing a >>>>>>>>> value of type C (see below). >>>>>>>>> * T is not the same type as C. >>>>>>>>> >>>>>>>>> Any exceptions thrown by the method body which are a subtype of a >>>>>>>>> caught exception type in the rethrows clause, are rethrown as the >>>>>>>>> corresponding translated exception type. >>>>>>>>> >>>>>>>>> For a given translated type T with corresponding caught type C, if >>>>>>>>> T has an accessible constructor accepting a value of type C, then >>>>>>>>> the translation is equivalent to the following: >>>>>>>>> >>>>>>>>> catch (C e) { >>>>>>>>> throw new T(e); >>>>>>>>> } >>>>>>>>> >>>>>>>>> Otherwise it must have an accessible no argument constructor, and >>>>>>>>> the translation is equivalent to: >>>>>>>>> >>>>>>>>> catch (C e) { >>>>>>>>> throw new T().initCause(e); >>>>>>>>> } >>>>>>>>> >>>>>>>>> >>>>>>>>> A rethrows clause does not restrict which types may appear in a >>>>>>>>> throws clause for the same method. In particular, for a given >>>>>>>>> caught type C in the rethrows clause, it is permitted for some >>>>>>>>> type C1 :> C to also be listed in the throws clause. >>>>>>>>> >>>>>>>>> >>>>>>>>> JLSv3 ?8.2 : The set of exception types declared to be thrown by >>>>>>>>> a method is the union of: >>>>>>>>> * the types in the throws clause >>>>>>>>> * the translated types in the rethrow clause >>>>>>>>> * the types thrown by the translated types' selected >>>>>>>>> constructors >>>>>>>>> >>>>>>>>> JLSv3 ?11.2.2 : For the purposes of exception analysis, the set >>>>>>>>> of checked exception types which may be thrown by the method's >>>>>>>>> body is the union of: >>>>>>>>> * the types in the throws clause >>>>>>>>> * the caught types in the rethrows clause >>>>>>>>> >>>>>>>>> JLSv3 ?11.2.3 : It is a compile-time error if a rethrows clause >>>>>>>>> contains a translation from a checked exception type C but there >>>>>>>>> exists no checked exception type E such that all of the following >>>>>>>>> hold: >>>>>>>>> * E <: C >>>>>>>>> * The method body can throw E >>>>>>>>> * No preceding translation in the rethrow clause catches E or >>>>>>>>> a supertype of E >>>>>>>>> unless C is the class java.lang.Exception. >>>>>>>>> >>>>>>>>> JLSv3 ?13.4.21 : Changes to the rethrows clause of methods or >>>>>>>>> constructors do not break compatibility with existing binaries; >>>>>>>>> these clauses are checked only at compile time. >>>>>>>>> >>>>>>>>> >>>>>>>>> >>>>>>>>> COMPILATION: How would the feature be compiled to class files? >>>>>>>>> Show how the simple and advanced examples would be compiled. >>>>>>>>> Compilation can be expressed as at least one of a desugaring to >>>>>>>>> existing source constructs and a translation down to bytecode. If >>>>>>>>> a new bytecode is used or the semantics of an existing bytecode >>>>>>>>> are changed, describe those changes, including how they impact >>>>>>>>> verification. Also discuss any new class file attributes that are >>>>>>>>> introduced. Note that there are many downstream tools that >>>>>>>>> consume class files and that they may to be updated to support >>>>>>>>> the proposal! >>>>>>>>> >>>>>>>>> A simple desugaring could consist of enclosing the method body's >>>>>>>>> statements in a try statement, with catch clauses for each >>>>>>>>> translated exception type. For example, the following method: >>>>>>>>> >>>>>>>>> Method findMethod() >>>>>>>>> catch ClassNotFoundException throw ConfigException, >>>>>>>>> NoSuchMethodException throw ConfigException { >>>>>>>>> >>>>>>>>> Class c = Class.forName("some.Thing"); >>>>>>>>> return c.getDeclaredMethod("execute", null); >>>>>>>>> } >>>>>>>>> >>>>>>>>> would be desugared to: >>>>>>>>> >>>>>>>>> Method findMethod() >>>>>>>>> throws ConfigException { >>>>>>>>> try { >>>>>>>>> Class c = Class.forName("some.Thing"); >>>>>>>>> return c.getDeclaredMethod("execute", null); >>>>>>>>> } >>>>>>>>> catch (ClassNotFoundException e) { >>>>>>>>> throw new ConfigException(e); >>>>>>>>> } >>>>>>>>> catch (MethodNotFoundException e) { >>>>>>>>> throw new ConfigException(e); >>>>>>>>> } >>>>>>>>> } >>>>>>>>> >>>>>>>>> No changes to the classfile format are required. >>>>>>>>> >>>>>>>>> >>>>>>>>> TESTING: How can the feature be tested? >>>>>>>>> >>>>>>>>> An initial set of jtreg tests is included in the prototype. >>>>>>>>> >>>>>>>>> >>>>>>>>> LIBRARY SUPPORT: Are any supporting libraries needed for the >>>>>>>>> feature? >>>>>>>>> >>>>>>>>> No >>>>>>>>> >>>>>>>>> >>>>>>>>> REFLECTIVE APIS: Do any of the various and sundry reflection APIs >>>>>>>>> need to be updated? This list of reflective APIs includes but is >>>>>>>>> not limited to core reflection (java.lang.Class and >>>>>>>>> java.lang.reflect.*), javax.lang.model.*, the doclet API, and >>>>>>>>> JPDA. >>>>>>>>> >>>>>>>>> com.sun.source.tree.MethodTree would require updates to access >>>>>>>>> the rethrows clause's caught and translated types. >>>>>>>>> >>>>>>>>> >>>>>>>>> OTHER CHANGES: Do any other parts of the platform need be updated >>>>>>>>> too? Possibilities include but are not limited to JNI, >>>>>>>>> serialization, and output of the javadoc tool. >>>>>>>>> >>>>>>>>> No >>>>>>>>> >>>>>>>>> >>>>>>>>> MIGRATION: Sketch how a code base could be converted, manually or >>>>>>>>> automatically, to use the new feature. >>>>>>>>> >>>>>>>>> Catch clauses which simply wrap and rethrow an exception as >>>>>>>>> another exception type not caught in an enclosing scope, can be >>>>>>>>> trivially replaced with a rethrows clause, either manually or >>>>>>>>> automatically. >>>>>>>>> >>>>>>>>> It should be possible for tools to offer bidirectional >>>>>>>>> conversions such that an exception translation may be moved back >>>>>>>>> into the method body if it is subsequently decided that >>>>>>>>> additional logic is required. >>>>>>>>> >>>>>>>>> >>>>>>>>> COMPATIBILITY >>>>>>>>> >>>>>>>>> BREAKING CHANGES: Are any previously valid programs now invalid? >>>>>>>>> If so, list one. >>>>>>>>> >>>>>>>>> No >>>>>>>>> >>>>>>>>> >>>>>>>>> EXISTING PROGRAMS: How do source and class files of earlier >>>>>>>>> platform versions interact with the feature? Can any new >>>>>>>>> overloadings occur? Can any new overriding occur? >>>>>>>>> >>>>>>>>> The semantics of existing class files and legal source files are >>>>>>>>> unchanged by this feature. >>>>>>>>> >>>>>>>>> >>>>>>>>> REFERENCES >>>>>>>>> >>>>>>>>> EXISTING BUGS: Please include a list of any existing Sun bug ids >>>>>>>>> related to this proposal. >>>>>>>>> >>>>>>>>> http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6534270 >>>>>>>>> (similar, but emphasizes unchecked exceptions) >>>>>>>>> >>>>>>>>> >>>>>>>>> URL FOR PROTOTYPE (optional): >>>>>>>>> >>>>>>>>> http://slm888.com/javac >>>>>>>>> >>>>>>>>> >>>>>>>>> >>>>>>>>> >>>>>>>>> >>>>>>> >>>>>> >>>>>> >>>>> >>>> >>>> > > From neal at gafter.com Wed May 20 11:17:54 2009 From: neal at gafter.com (Neal Gafter) Date: Wed, 20 May 2009 11:17:54 -0700 Subject: Checked Exceptions do not exist on the JVM. In-Reply-To: <4A1445B2.3070304@sun.com> References: <39084932-B2CC-4B91-97EA-006FE21301F0@googlemail.com> <4A1339ED.8090309@sun.com> <68BF955A-9796-44F7-9E97-94BBB43ADCC5@zwitserloot.com> <988330f1d03fc629490d5dffa3fc2d25.squirrel@wmail.gradsoft.ua> <4A1445B2.3070304@sun.com> Message-ID: <15e8b9d20905201117l1fd86697u84beeaedc345e06e@mail.gmail.com> On Wed, May 20, 2009 at 11:02 AM, Joseph D. Darcy wrote: > Additionally, on the point of interfacing with other language in Java, > the possibility of having what are in Java checked exceptions thrown by > the caller argue for Dynamic call sites to be regarded as being able to > throw Exception so that the existing Java semantics and checking can be > preserved. Agreed, though I think you mean that they throw java.lang.Throwable, which is the root of the language's exception hierarchy. From rssh at gradsoft.com.ua Wed May 20 08:53:50 2009 From: rssh at gradsoft.com.ua (Ruslan Shevchenko) Date: Wed, 20 May 2009 18:53:50 +0300 (EEST) Subject: Checked Exceptions do not exist on the JVM. In-Reply-To: <4A1445B2.3070304@sun.com> References: <39084932-B2CC-4B91-97EA-006FE21301F0@googlemail.com> <4A1339ED.8090309@sun.com> <68BF955A-9796-44F7-9E97-94BBB43ADCC5@zwitserloot.com> <988330f1d03fc629490d5dffa3fc2d25.squirrel@wmail.gradsoft.ua> <4A1445B2.3070304@sun.com> Message-ID: <47282447c5b27188fba7711e5cc659a8.squirrel@wmail.gradsoft.ua> > > Tom Ball wrote: >> I don't consider "Ruslan, you've got it all wrong" an example of opening >> a >> "perfectly civil email", it sounds like bullying. This isn't slashdot, >> it's >> a forum for discussions on possible small improvements to the Java >> language. So I shouldn't have responded with the same tone as your >> message, >> and for that I apologize to the wider group. But I really 'got it all wrong' (fooling by ignore keyword and luck of time to read) I think until we able speak 'in essence' about technical side of things, level of expression is ok ;) >> >> The purpose of throws clauses is to better describe the contract a >> method >> offers for its callers: it only accepts parameters of a certain type, >> it >> returns an instance of a specific type, and under certain (hopefully >> documented) conditions it may throw specific exceptions. Checked >> exceptions >> are intended to call out specific exceptions that the library writer >> believes the caller should be able to recover from, and therefore should >> handle or forward. If a library writer subverts the contract of his own >> method, well, that's a shame but doesn't necessarily call for changes to >> the >> language. If a non-Java language has libraries which throw what are in >> Java >> checked exceptions, then write Java code which does more checking at >> runtime >> since that's apparently what the other language requires (or don't use >> those >> libraries). >> >> This isn't a problem, and so there is nothing about it that needs fixing >> in >> Java 7. >> Exactly. Except case of Class.newInstance(), which must be or deprecated, or marked as thrown Throwable. From forax at univ-mlv.fr Wed May 20 11:56:15 2009 From: forax at univ-mlv.fr (=?ISO-8859-1?Q?R=E9mi_Forax?=) Date: Wed, 20 May 2009 20:56:15 +0200 Subject: Checked Exceptions do not exist on the JVM. In-Reply-To: <15e8b9d20905201117l1fd86697u84beeaedc345e06e@mail.gmail.com> References: <39084932-B2CC-4B91-97EA-006FE21301F0@googlemail.com> <4A1339ED.8090309@sun.com> <68BF955A-9796-44F7-9E97-94BBB43ADCC5@zwitserloot.com> <988330f1d03fc629490d5dffa3fc2d25.squirrel@wmail.gradsoft.ua> <4A1445B2.3070304@sun.com> <15e8b9d20905201117l1fd86697u84beeaedc345e06e@mail.gmail.com> Message-ID: <4A14524F.3080407@univ-mlv.fr> Neal Gafter a ?crit : > On Wed, May 20, 2009 at 11:02 AM, Joseph D. Darcy wrote: > > >> Additionally, on the point of interfacing with other language in Java, >> the possibility of having what are in Java checked exceptions thrown by >> the caller argue for Dynamic call sites to be regarded as being able to >> throw Exception so that the existing Java semantics and checking can be >> preserved. >> > > > Agreed, though I think you mean that they throw java.lang.Throwable, which > is the root of the language's exception hierarchy. > > Neal, why do you want Throwable and not Exception ? It the second time you mention it and I don't understand why. R?mi From Joe.Darcy at Sun.COM Wed May 20 11:56:56 2009 From: Joe.Darcy at Sun.COM (Joseph D. Darcy) Date: Wed, 20 May 2009 11:56:56 -0700 Subject: Checked Exceptions do not exist on the JVM. In-Reply-To: <15e8b9d20905201117l1fd86697u84beeaedc345e06e@mail.gmail.com> References: <39084932-B2CC-4B91-97EA-006FE21301F0@googlemail.com> <4A1339ED.8090309@sun.com> <68BF955A-9796-44F7-9E97-94BBB43ADCC5@zwitserloot.com> <988330f1d03fc629490d5dffa3fc2d25.squirrel@wmail.gradsoft.ua> <4A1445B2.3070304@sun.com> <15e8b9d20905201117l1fd86697u84beeaedc345e06e@mail.gmail.com> Message-ID: <4A145278.8020500@sun.com> Neal Gafter wrote: > On Wed, May 20, 2009 at 11:02 AM, Joseph D. Darcy wrote: > > >> Additionally, on the point of interfacing with other language in Java, >> the possibility of having what are in Java checked exceptions thrown by >> the caller argue for Dynamic call sites to be regarded as being able to >> throw Exception so that the existing Java semantics and checking can be >> preserved. >> > > > Agreed, though I think you mean that they throw java.lang.Throwable, which > is the root of the language's exception hierarchy. No, I mean Exception :-) Any Java code throw Throwable or RuntimeException of course since those are not tracked by a Java compiler, but the right semantics for a Dynamic call site come about if the compiler treats them as if the method included "throws Exception" in its declaration. -Joe From neal at gafter.com Wed May 20 13:02:15 2009 From: neal at gafter.com (Neal Gafter) Date: Wed, 20 May 2009 13:02:15 -0700 Subject: Checked Exceptions do not exist on the JVM. In-Reply-To: <4A145278.8020500@sun.com> References: <39084932-B2CC-4B91-97EA-006FE21301F0@googlemail.com> <68BF955A-9796-44F7-9E97-94BBB43ADCC5@zwitserloot.com> <988330f1d03fc629490d5dffa3fc2d25.squirrel@wmail.gradsoft.ua> <4A1445B2.3070304@sun.com> <15e8b9d20905201117l1fd86697u84beeaedc345e06e@mail.gmail.com> <4A145278.8020500@sun.com> Message-ID: <15e8b9d20905201302p637d888embf9549cd3cc6c138@mail.gmail.com> On Wed, May 20, 2009 at 11:56 AM, Joseph D. Darcy wrote: > Neal Gafter wrote: > >> On Wed, May 20, 2009 at 11:02 AM, Joseph D. Darcy >> wrote: >> >> >> >>> Additionally, on the point of interfacing with other language in Java, >>> the possibility of having what are in Java checked exceptions thrown by >>> the caller argue for Dynamic call sites to be regarded as being able to >>> throw Exception so that the existing Java semantics and checking can be >>> preserved. >>> >>> >> >> >> Agreed, though I think you mean that they throw java.lang.Throwable, which >> is the root of the language's exception hierarchy. >> > > No, I mean Exception :-) Any Java code throw Throwable or RuntimeException > of course since those are not tracked by a Java compiler, but the right > semantics for a Dynamic call site come about if the compiler treats them as > if the method included "throws Exception" in its declaration. I think you misread the JLS. The exception hierarchy is rooted at Throwable. Subtypes of RuntimeException and Error are unchecked. There is nothing special about the class Exception with respect to exception checking. From neal at gafter.com Wed May 20 13:02:39 2009 From: neal at gafter.com (Neal Gafter) Date: Wed, 20 May 2009 13:02:39 -0700 Subject: Checked Exceptions do not exist on the JVM. In-Reply-To: <4A14524F.3080407@univ-mlv.fr> References: <39084932-B2CC-4B91-97EA-006FE21301F0@googlemail.com> <68BF955A-9796-44F7-9E97-94BBB43ADCC5@zwitserloot.com> <988330f1d03fc629490d5dffa3fc2d25.squirrel@wmail.gradsoft.ua> <4A1445B2.3070304@sun.com> <15e8b9d20905201117l1fd86697u84beeaedc345e06e@mail.gmail.com> <4A14524F.3080407@univ-mlv.fr> Message-ID: <15e8b9d20905201302r153f0a5dmcfc81feee8bfb8b1@mail.gmail.com> On Wed, May 20, 2009 at 11:56 AM, R?mi Forax wrote: > Neal Gafter a ?crit : > > On Wed, May 20, 2009 at 11:02 AM, Joseph D. Darcy >> wrote: >> >> >> >>> Additionally, on the point of interfacing with other language in Java, >>> the possibility of having what are in Java checked exceptions thrown by >>> the caller argue for Dynamic call sites to be regarded as being able to >>> throw Exception so that the existing Java semantics and checking can be >>> preserved. >>> >>> >> >> >> Agreed, though I think you mean that they throw java.lang.Throwable, which >> is the root of the language's exception hierarchy. >> >> >> > Neal, why do you want Throwable and not Exception ? > It the second time you mention it and I don't understand why. Because a type such as *class Foo extends Throwable {} * is a checked exception type from the point of view of the Java Programming Language. The class Exception isn't special in any way. See JLS3 sections 11.2 and 11.5. Cheers, Neal From mthornton at optrak.co.uk Wed May 20 13:10:18 2009 From: mthornton at optrak.co.uk (Mark Thornton) Date: Wed, 20 May 2009 21:10:18 +0100 Subject: Checked Exceptions do not exist on the JVM. In-Reply-To: <15e8b9d20905201302p637d888embf9549cd3cc6c138@mail.gmail.com> References: <39084932-B2CC-4B91-97EA-006FE21301F0@googlemail.com> <68BF955A-9796-44F7-9E97-94BBB43ADCC5@zwitserloot.com> <988330f1d03fc629490d5dffa3fc2d25.squirrel@wmail.gradsoft.ua> <4A1445B2.3070304@sun.com> <15e8b9d20905201117l1fd86697u84beeaedc345e06e@mail.gmail.com> <4A145278.8020500@sun.com> <15e8b9d20905201302p637d888embf9549cd3cc6c138@mail.gmail.com> Message-ID: <4A1463AA.8080102@optrak.co.uk> >> No, I mean Exception :-) Any Java code throw Throwable or RuntimeException >> of course since those are not tracked by a Java compiler, but the right >> semantics for a Dynamic call site come about if the compiler treats them as >> if the method included "throws Exception" in its declaration. >> > > > I think you misread the JLS. The exception hierarchy is rooted at > Throwable. Subtypes of RuntimeException and Error are unchecked. There is > nothing special about the class Exception with respect to exception > checking. > > Or perhaps something aweful ought to happen to someone who uses or subclasses Throwable directly! ;-) Mark From markmahieu at googlemail.com Wed May 20 14:33:13 2009 From: markmahieu at googlemail.com (Mark Mahieu) Date: Wed, 20 May 2009 22:33:13 +0100 Subject: Checked Exceptions do not exist on the JVM. In-Reply-To: <4A1463AA.8080102@optrak.co.uk> References: <39084932-B2CC-4B91-97EA-006FE21301F0@googlemail.com> <68BF955A-9796-44F7-9E97-94BBB43ADCC5@zwitserloot.com> <988330f1d03fc629490d5dffa3fc2d25.squirrel@wmail.gradsoft.ua> <4A1445B2.3070304@sun.com> <15e8b9d20905201117l1fd86697u84beeaedc345e06e@mail.gmail.com> <4A145278.8020500@sun.com> <15e8b9d20905201302p637d888embf9549cd3cc6c138@mail.gmail.com> <4A1463AA.8080102@optrak.co.uk> Message-ID: <3AA6DEB8-FE68-48D0-B9F9-9D04F09474EC@googlemail.com> On 20 May 2009, at 21:10, Mark Thornton wrote: > Or perhaps something aweful ought to happen to someone who uses or > subclasses Throwable directly! ;-) > > Mark I think Google Code Search must have a sense of humour - the first result returned when I search for "throw\ new\ Throwable" is currently this, from javac's test suite (test/tools/javac/ DefiniteAssignment.java): public void throwCheckedException () throws Throwable { throw new Throwable(); } Mark From tball at google.com Wed May 20 14:42:19 2009 From: tball at google.com (Tom Ball) Date: Wed, 20 May 2009 14:42:19 -0700 Subject: Checked Exceptions do not exist on the JVM. In-Reply-To: <3AA6DEB8-FE68-48D0-B9F9-9D04F09474EC@googlemail.com> References: <39084932-B2CC-4B91-97EA-006FE21301F0@googlemail.com> <4A1445B2.3070304@sun.com> <15e8b9d20905201117l1fd86697u84beeaedc345e06e@mail.gmail.com> <4A145278.8020500@sun.com> <15e8b9d20905201302p637d888embf9549cd3cc6c138@mail.gmail.com> <4A1463AA.8080102@optrak.co.uk> <3AA6DEB8-FE68-48D0-B9F9-9D04F09474EC@googlemail.com> Message-ID: I don't understand your point -- this is a test that is supposed to fail, and it does (now). Here is its comment, which also runs the jtreg test runner: /* * @test * @bug 4053998 * @summary Compiler used to not notice the uncaught checked exception. * @author turnidge * * @compile/fail UncaughtException.java */ Tom On Wed, May 20, 2009 at 2:33 PM, Mark Mahieu wrote: > > On 20 May 2009, at 21:10, Mark Thornton wrote: > > Or perhaps something aweful ought to happen to someone who uses or > > subclasses Throwable directly! ;-) > > > > Mark > > I think Google Code Search must have a sense of humour - the first > result returned when I search for "throw\ new\ Throwable" is > currently this, from javac's test suite (test/tools/javac/ > DefiniteAssignment.java): > > public void throwCheckedException () throws Throwable { > throw new Throwable(); > } > > > Mark > > From markmahieu at googlemail.com Wed May 20 14:52:29 2009 From: markmahieu at googlemail.com (Mark Mahieu) Date: Wed, 20 May 2009 22:52:29 +0100 Subject: Checked Exceptions do not exist on the JVM. In-Reply-To: References: <39084932-B2CC-4B91-97EA-006FE21301F0@googlemail.com> <4A1445B2.3070304@sun.com> <15e8b9d20905201117l1fd86697u84beeaedc345e06e@mail.gmail.com> <4A145278.8020500@sun.com> <15e8b9d20905201302p637d888embf9549cd3cc6c138@mail.gmail.com> <4A1463AA.8080102@optrak.co.uk> <3AA6DEB8-FE68-48D0-B9F9-9D04F09474EC@googlemail.com> Message-ID: Tom, Sorry, there wasn't really a point in that sense; I just found it mildly amusing in an 'all roads lead back to javac' kind of way. Probably just my sense of humour though. Mark On 20 May 2009, at 22:42, Tom Ball wrote: > I don't understand your point -- this is a test that is supposed to > fail, and it does (now). Here is its comment, which also runs the > jtreg test runner: > > /* > * @test > > > * @bug 4053998 > * @summary Compiler used to not notice the uncaught checked > exception. > * @author turnidge > * > * @compile/fail UncaughtException.java > > > */ > Tom > > On Wed, May 20, 2009 at 2:33 PM, Mark Mahieu > wrote: > > On 20 May 2009, at 21:10, Mark Thornton wrote: > > Or perhaps something aweful ought to happen to someone who uses or > > subclasses Throwable directly! ;-) > > > > Mark > > I think Google Code Search must have a sense of humour - the first > result returned when I search for "throw\ new\ Throwable" is > currently this, from javac's test suite (test/tools/javac/ > DefiniteAssignment.java): > > public void throwCheckedException () throws Throwable { > throw new Throwable(); > } > > > Mark > > From vapor1 at teleport.com Wed May 20 20:12:19 2009 From: vapor1 at teleport.com (Derek Foster) Date: Wed, 20 May 2009 23:12:19 -0400 (EDT) Subject: PROPOSAL: Abstract enums (version 2) Message-ID: <23749174.1242875539733.JavaMail.root@mswamui-chipeau.atl.sa.earthlink.net> Hi, folks. I think Howard's counterproposal might be interesting, if it were fully fleshed out to the degree that my proposal is by now. I might even prefer his to mine, if that were the case. However, it's hard to evaluate in its current form. A lot of potential implementation problems are currently being handwaved past -- a real proposal would have to grapple with these and find specific answers to all of them: Binary compatibility, serialization, how to handle Enum's static methods, how to identify and what to do about inherited or overridden methods that conflict with the current Enum's, how to reduce code bloat in subtypes due to duplicate methods, etc. My "abstract enums" proposal is an attempt to add abstract supertypes to enums while changing as little as possible about how enums currently work, so as to not disturb any existing code (serialization, IDEs, etc.) that might depend on the current semantics and implementation strategy. I went to quite some trouble to minimize the scope of the changes to try to make the proposal small enough for Project Coin and to minimize any disruption to the compiler or libraries. Howard's suggested counterproposal attempts to achieve a little bit more (the ability for an enum and a non-enum to share a supertype) by totally changing how enums are implemented. In particular, under Howard's proposal, Enum becomes an interface, not an abstract superclass, and its methods become duplicated in each leaf subclass rather than inherited. Plus some changes would have to be made to the compiler to hack in a way to still do things like "Enum.valueOf(Foo.class, "bar")" (I don't buy Howard's argument that we can just abandon backwards compatibility and encourage people to migrate away from these static methods, although I think that this "abstract class->interface" migration is a good argument for the "static methods in interfaces" proposal that was put forth on the list a while ago and (IIRC) already shot down. Possibly we could just hack the compiler to treat "Enum.valueOf" as a special case and map the method invocation to a different static method on another class in java.lang, though.) Still, overall, what Howard proposes is a pretty major change to how enums of all kinds (not just abstract ones!) work. I'm not necessarily opposed to it -- David raises some good points about its applicability, and I can recall some times where I might have been inclined to extend an enum from a non-enum abstract class for the purpose of creating a singleton or a fixed-size set of them, if the option had been available. Howard's approach would meet my abstract enum needs as well as mine does, and has some other minor pluses, so in that sense, I don't really care about which approach is taken... if there aren't hidden "gotcha's" as far as implementation goes, which is hard to tell at this level of detail. If Howard wants to try 'fork'ing my proposal and modifying it to add a parallel version of it implemented along the lines he suggests, I won't mind (although Joe might, if he considers it a new (late) proposal instead of a modification of an existing one). Ideally, the two co-proposals would be considered in parallel. However, I'm not currently planning to abandon my proposal's current implementation approach in favor of Howard's unless I am convinced that Howard's has a better chance of actually being selected by Sun -- which would imply at the very least that it has been described in exacting detail and that all implementation challenges have been identified and that specific solutions for them are proposed, and have been vetted by the Project Coin listmembers. (Is there still time to do this? Questionable...) This would have been a lot easier if a proposal along the lines of what Howard is suggesting had been put forth before the cutoff deadline for proposal submissions... Derek -----Original Message----- >From: David Walend >Sent: May 17, 2009 7:45 PM >To: coin-dev at openjdk.java.net >Subject: Re: PROPOSAL: Abstract enums (version 2) > > >On May 13, 2009, at 2:53 AM, coin-dev-request at openjdk.java.net wrote: >> Date: Wed, 13 May 2009 10:35:17 +1000 >> From: Howard Lovatt >> Subject: Re: PROPOSAL: Abstract enums (version 2) >> >> On a pragmatic point, I doubt if the proposal will go anywhere since >> no one is supporting it except me :( The point you make about wanting >> to change from a singleton to a number of instances in the future >> might be valid, but I haven't personally had this problem in using >> Scala and I haven't heard of others having problems in Scala. >> >> The main enhancement I would find useful is to be able to extend an >> arbitrary abstract class when making an enum. The present proposal of >> a special abstract enum wouldn't help my use cases much. Therefore I >> don't thing the Singleton variation is that important. > > >Howard, > >I'll speak for enumerations extending abstract classes. It comes up >every forth project or so for me; machine-readable JMX notifications >come to mind. A lot of general purpose abstract classes should only be >used certain ways within a particular context. Sometimes those ways >fit an enum well. With the current limitation, I have to extend the >abstract class, then create an enum full of pass-through methods. It's >uninteresting boilerplate, and labor to maintain. I'd use enums this >way occasionally if it were part of JDK7. > >Dave > From vapor1 at teleport.com Wed May 20 20:23:28 2009 From: vapor1 at teleport.com (Derek Foster) Date: Wed, 20 May 2009 23:23:28 -0400 (EDT) Subject: PROPOSAL: Byte and Short Integer Literal Suffixes Message-ID: <4309233.1242876209034.JavaMail.root@mswamui-chipeau.atl.sa.earthlink.net> -----Original Message----- >From: Joe Darcy >Sent: May 19, 2009 9:05 PM >To: Bruce Chapman >Cc: "coin-dev at openjdk.java.net" >Subject: Re: PROPOSAL: Byte and Short Integer Literal Suffixes > >Hi Bruce. > >Between your two proposals "Byte and Short Integer Literal Suffixes" and >"Auto Typing Hexadecimal and Binary Integer Literals," the suffixes are >more in keeping with the existing flavor of Java literals. I'm more >inclined for support to be added for narrow (or auto) literals for bytes >rather than shorts since my impression is short is rarely used and those >annoying casts of values 0xF1 to byte are much more common. Hi, Joe. How often shorts are used depends a bit on the domain -- I am currently working on modifications for Eclipse to debug programs running on a 16-bit processor, and shorts are used quite a bit since that is the word size of the processor. If a suffix is added for byte, I'd like to see one added for short as well. Derek > >-Joe > > >On 03/25/09 01:59 AM, Bruce Chapman wrote: >> TITLE: Byte and Short Integer Literal Suffixes >> >> latest html version at >> http://docs.google.com/Doc?docid=dcvp3mkv_0fvz5gx7b&hl >> >> AUTHOR(S): Bruce Chapman >> >> OVERVIEW >> >> Problems occur when trying to create literal byte values for known bit >> patterns because byte is signed therefore 0x80 thru 0xFF are not valid >> byte values. >> >> Working with bytes (binary files, network communications) can be >> simplified by allowing byte size integer literals (and short for >> consistency). Specifically allow hexadecimal byte literals, others for >> completeness. >> >> >> >> FEATURE SUMMARY: >> >> Allow byte and short integer literals by introducing 4 new integer type >> suffixes 'y' & 'Y' for bytes, 's' & 'S' for shorts. >> >> >> MAJOR ADVANTAGE: >> >> Somewhat reduces the pain resulting from byte being a signed type, >> removes the need to downcast integer literals to byte or short. >> >> >> MAJOR BENEFIT: Why is the platform better if the proposal is adopted? >> >> cruddy code like >> >> byte[] stuff = { 0x00, 0x7F, (byte)0x80, (byte)0xFF}; >> >> can be recoded as >> >> >> >> byte[] ufum7 = { 0x00y, 0x7Fy, 0x80y, 0xFFy }; >> >> MAJOR DISADVANTAGE: >> >> Some familiarisation curve required before the syntax stops looking >> slightly odd. >> >> Would prefer to but cannot use 'B' as Integral type suffix because it is >> a hexadecimal digit, 'Y' can be used but is slightly esoteric, but >> probably no more so than 'X' for hexadecimal prefix. >> >> >> ALTERNATIVES: >> >> An alternative language change would be to have hexadecimal integer >> literals that are typed according to the number of digits. >> >> EXAMPLES >> Show us the code! >> SIMPLE EXAMPLE: >> >> >> byte[] utf8bom7 = { 0xEFy, 0xBBy, 0xBFy }; >> >> >> ADVANCED EXAMPLE: >> >> >> byte[] buffer = ...; >> >> if(buffer[i] == 0xBBy) { // never equal with 0xBB >> >> ... >> >> } >> >> DETAILS >> SPECIFICATION: >> >> >> "3.10.1 Integer literals" is amended as follows - additions in bold. >> >> >> IntegerTypeSuffix: one of >> l L y Y s S >> >> >> An integer literal is of type long if it is suffixed with an ASCII >> letter L or l (ell), of type short if it is suffixed with an ASCII >> letter S or s and of type byte if it is suffixed with an ASCII letter Y >> or y; otherwise it is of type int (?4.2.1). For long literals the >> suffix L is preferred, because the letter l (ell) is often hard to >> distinguish from the digit 1 (one). >> >> >> >> and at the end of 3.10.1 add >> >> A compile-time error occurs if a decimal literal of type short is >> larger than 32767 (215), or if the literal 32767 appears anywhere other >> than as the operand of the unary - operator, or if a hexadecimal or >> octal short literal does not fit in 16 bits. >> >> A compile-time error occurs if a decimal literal of type byte is >> larger than 128 (27), or if the literal 128 appears anywhere other than >> as the operand of the unary - operator, or if a hexadecimal or octal >> byte literal does not fit in 8 bits. >> >> >> COMPILATION: How would the feature be compiled to class files? Show how >> the simple and advanced examples would be compiled. Compilation can be >> expressed as at least one of a desugaring to existing source constructs >> and a translation down to bytecode. If a new bytecode is used or the >> semantics of an existing bytecode are changed, describe those changes, >> including how they impact verification. Also discuss any new class file >> attributes that are introduced. Note that there are many downstream >> tools that consume class files and that they may to be updated to >> support the proposal! >> >> TESTING: How can the feature be tested? >> >> LIBRARY SUPPORT: >> >> No library support required. >> >> REFLECTIVE APIS: Do any of the various and sundry reflection APIs need >> to be updated? This list of reflective APIs includes but is not limited >> to core reflection (java.lang.Class and java.lang.reflect.*), >> javax.lang.model.*, the doclet API, and JPDA. >> >> OTHER CHANGES: Do any other parts of the platform need be updated too? >> Possibilities include but are not limited to JNI, serialization, and >> output of the javadoc tool. >> >> MIGRATION: Sketch how a code base could be converted, manually or >> automatically, to use the new feature. >> >> COMPATIBILITY >> BREAKING CHANGES: Are any previously valid programs now invalid? If so, >> list one. >> >> EXISTING PROGRAMS: How do source and class files of earlier platform >> versions interact with the feature? Can any new overloadings occur? Can >> any new overriding occur? >> >> REFERENCES >> EXISTING BUGS: Please include a list of any existing Sun bug ids related >> to this proposal. >> >> URL FOR PROTOTYPE (optional): >> >> >> > > From vapor1 at teleport.com Wed May 20 21:00:14 2009 From: vapor1 at teleport.com (Derek Foster) Date: Thu, 21 May 2009 00:00:14 -0400 (EDT) Subject: PROPOSAL: Equivalence operators (formerly titled Message-ID: <18680561.1242878414855.JavaMail.root@mswamui-chipeau.atl.sa.earthlink.net> Replies inline. -----Original Message----- >From: Mark Thornton >Sent: May 9, 2009 4:33 AM >To: Derek Foster >Cc: Project Coin >Subject: Re: PROPOSAL: Equivalence operators (formerly titled > >Derek Foster wrote: >> Hi, Mark. >> >> Thanks for your comments. >> >> The proposal already does what you suggest, although I agree it is not clear from the section you quoted (which was only intended to be a brief feature summary). If you look in the specification section, you will find that in a case like "a < b" where a is Float and b is float, that since both types are convertible to a primitive type, that this conversion will be done before the operation is attempted (possibly triggering a NullPointerException on unboxing), yielding the same results as would occur in Java now. >> >> In some ways, I think it would be nice to have the ># and <# operators return true if both of their operands are null, even if both operands are typed as boxed primitives. This would be more similar to how ## and !# work and would be consistent for all operators if you assume that null "is equivalent to" null. I am considering changing the proposal to allow this. (Currently this operation would provoke a NullPointerException during unboxing, according to proposal version 3 and before). < and > would not be affected by this, of course. Comments? >> >> Derek >> >My first thought was that managing null with ># and <# was attractive >and nicely consistent with ## and #!, but then <, > don't just return >false but throw a NullPointerException. That's fine, since by their definitions, < and > don't care about either equivalence or equality: they just care about ordering. As such, they ALWAYS need to inspect the contents of the objects, and if they can't (due to a null reference) a NullPointerException is necessary. This is different from the case where <# and ># can determine that two null references are equivalent and that therefore the "greater than or equivalent" or "less than or equivalent" condition would be true, since "X or true" is true regardless of X. Thus, two null references can be determined to be "greater than or equivalent" or "less than or equivalent" without ever needing to evaluate the "greater than" or "less than" part of those clauses -- This is basically a form of short-circuit evaluation. Of course, if the first object was null and the second object wasn't, then a NullPointerException could still be thrown even from ># and <#. In that case, the "null is equivalent to null" short-circuit evaluation couldn't be used and the full expression needs to be evaluated, possibly resulting in an NPE if the left operand is null. >Why can't we overload >= and <= instead in the same way as < and > (i.e. >only apply to Comparable types which are NOT convertable to primitives). >Then >##, #! handle null, based on equals() ><=, >=, <, > For primitives or primitive wrappers behave as now and >throw NullPointerException with null wrapper values ><=, >=, <, > For Comparable types other than primitive wrappers, based >on compareTo, throw NullPointerException The problem here is that if you do that, the meaning of "=" in ">=" then becomes different from the meaning of "=" in "==". That is in large part the problem that my proposal was trying to solve by introducing a new character with a meaning of "is equivalent to" instead of "is the same object as". Thus, if "#" means "is equivalent to" (defined as either "A==null ? B==null : A.equals(B)" or "A==null ? B==null : a.compareTo(B)==0" depending on whether it's used in an equality test or an ordering test) then the definitions of the operators fall out naturally by comparison with the existing >=, <=, ==, and != operators: So for instance since the ># operator means "greater than or equivalent", and since greater than means "A.compareTo(B) >= 0" and equivalent means "A==null ? B==null : a.compareTo(B)==0" then if we evaluate equivalence first (for short circuiting purposes), the result must be "(A==null ? B==null : a.compareTo(B)==0) || (A.compareTo(B) >= 0)" or using a bit of algebraic simplification, we get "(A==null && B==null) || a.compareTo(B)>=0))". Derek From vapor1 at teleport.com Wed May 20 21:06:03 2009 From: vapor1 at teleport.com (Derek Foster) Date: Thu, 21 May 2009 00:06:03 -0400 (EDT) Subject: PROPOSAL: Underscores in Numbers (Version 2) Message-ID: <11588396.1242878763855.JavaMail.root@mswamui-chipeau.atl.sa.earthlink.net> Replies inline. -----Original Message----- >From: Joe Darcy >Sent: May 7, 2009 9:59 PM >To: Derek Foster >Cc: coin-dev at openjdk.java.net >Subject: Re: PROPOSAL: Underscores in Numbers (Version 2) > >Hello. > >A few comments. > >This is well-localized change and judicious use of the feature would >improve the readability of some numerical constants. > >However, I generally agree with Bruce's earlier comments that phone >numbers, credit card numbers, social security numbers, etc. are not a >good motivating example since they are really strings whose digits are >(mostly) constrained to be numeric as opposed to actual integral or >real-valued data. (Using floating-point types to store dollars and >cents is also ill-advised because fractions like 0.12 generally cannot >be stored exactly as binary fractions.) Hi, Joe. I agree with this comment -- my major intended use of the feature would be for separating digits in large hex and/or binary (I hope) numbers, and secondarily for making large decimal numbers more readable by introducing order-of-magnitude marks. (Every three digits, for Americans). I mostly included the credit card numbers, etc. just to illustrate that the feature could potentially be used for numbers in other regular formats, if desired. >For more substantive feedback, I believe the grammar changes still need >some work. I'll take another look at the proposal and revise the grammar to handle your concerns. Thanks for pointing out these issues. Derek > First, my reading of the grammar is that it is ambiguous >regarding underscores, there are multiple ways for "0__1" to be parsed >and the grammar as written does not ban "5_" (NonZeroDigit followed by >Undersccores_opt). How about treating underscore as an extra digit in >some cases, something like: > >Decimal Numeral > 0 > NonZeroDigit DigitsAndUnderscores_opt > >DigitsAndUnderscores > DigitOrUnderscore_opt Digit > >DigitOrUnderscore > 0 ... 9 _ > >This grammar: > >* forces a nonzero leading digit >* forces a non-underscore final character >* allows any number of intermixed digits and underscores in between > >-Joe > >On 04/30/09 09:01 PM, Derek Foster wrote: >> Per feedback on the Project Coin mailing list, the following proposal has been revised to disallow placing underscores at the beginning or end of a sequence of digits within a number. I have also revised the value used for the "alsoMaxLong" example (as it was previously illegal), as well as the other examples showing where underscores can/cannot be placed. >> >> AUTHOR(S): Derek Foster >> >> OVERVIEW >> >> In Java, currently, numbers of various types currently are expressed in their pure form, as a long string of digits possibly interspersed with other punctuation (periods, an exponent specifier, etc.) needed to separate distinct sections of the number. While this is easy for a compiler to process, it is often difficult for a human being to visually parse. >> >> The ability of a human to visually separate separate items tops out somewhere near "seven plus or minus two" items. Research done by telephone companies suggests that for many practical purposes, the longest string of numbers an average human can successfully hold in memory at a time is around three or four. Also, it is difficult for the human eye to find common positions in numbers that have no break in their visual structure. >> >> As a result, most numbers that humans deal with in day-to-day life have separators included in them to break the long sequence of digits into manageable chunks that are easy to deal with as separate entities. This includes items such as (apologies to non-USA readers...): >> >> Phone numbers: 555-555-1212 >> Credit card numbers: 1234-5678-9012-3456 >> Social security numbers: 999-99-9999 >> Monetary amounts: $12,345,132.12 >> >> and a wide variety of other types of numbers. >> >> However, Java provides no way to add these kinds of visual separators into a number. Java expects the number to be essentially an unbroken string of digits. >> >> This proposal suggests that Java follow the lead of the Ruby programming language in allowing the underscore character to be inserted into numbers in most positions, for readability purposes. >> >> >> FEATURE SUMMARY: >> >> Java numeric literals will allow underscores to be placed in (nearly) arbitrary positions within the number, at the programmer's discretion, for readability purposes. These underscores shall be ignored by the compiler for the purposes of code generation. >> >> >> MAJOR ADVANTAGE: >> >> Programmers won't have to visually parse long strings of digits (a task humans are quite poor at). The internal digit-oriented structure of many numbers can be made more clear. >> >> >> MAJOR BENEFIT: >> >> Increased readability of code. >> >> >> MAJOR DISADVANTAGE: >> >> The number parsers in the Java compiler would have to be adjusted to parse and ignore the underscores. This is a small amount of effort, but nonzero. There might also be some small performance impact. >> >> If someone were to use this feature inappropriately, it could result in difficult to read code. >> >> >> ALTERNATIVES: >> >> Do without separators in numbers, or use some other character for them. >> >> >> EXAMPLES >> >> >> SIMPLE EXAMPLE: Show the simplest possible program utilizing the new feature. >> >> int phoneNumber = 555_555_1212; >> >> >> ADVANCED EXAMPLE: >> >> long creditCardNumber = 1234_5678_9012_3456L; >> long socialSecurityNumbers = 999_99_9999L; >> float monetaryAmount = 12_345_132.12; >> long hexBytes = 0xFF_EC_DE_5E; >> long hexWords = 0xFFEC_DE5E; >> long maxLong = 0x7fff_ffff_ffff_ffffL; >> long alsoMaxLong = 9_223_372_036_854_775_807L; >> double whyWouldYouEverDoThis = 0x1_.ffff_ffff_ffff_fp10_23; >> >> (Additionally, if binary literals are ever added to the Java language, the following might also be possible... >> byte nybbles = 0b0010_0101; >> long bytes = 0b11010010_01101001_10010100_10010010; >> int weirdBitfields = 0b000_10_101; >> ) >> >> Note that according to this proposal, underscores can only be placed between digits. They cannot be placed by themselves in positions where a string of digits would normally be expected: >> >> int x1 = _52; // This is an identifier, not a numeric literal. >> int x2 = 5_2; // OK. (Decimal literal) >> int x2 = 52_; // Illegal. (Underscores must always be between digits) >> int x3 = 5_______2; // OK. (Decimal literal.) >> >> int x4 = 0_x52; // Illegal. Can't put underscores in the "0x" radix prefix. >> int x5 = 0x_52; // Illegal. (Underscores must always be between digits) >> int x6 = 0x5_2; // OK. (Hexadecimal literal) >> int x6 = 0x52_; // Illegal. (Underscores must always be between digits) >> int x6 = 0x_; // Illegal. (Not valid with the underscore removed) >> >> int x7 = 0_52; // OK. (Octal literal) >> int x7 = 05_2; // OK. (Octal literal) >> int x8 = 052_; // Illegal. (Underscores must always be between digits) >> >> >> DETAILS >> >> SPECIFICATION: >> >> DECIMALS: >> >> Section 3.10.1 ("Integer Literals") of the Java Language Specification 3rd edition shall be modified like so: >> >> Underscores: >> _ >> _ Underscores >> >> DecimalNumeral: >> 0 >> NonZeroDigit Underscores_opt DigitsAndUnderscores_opt >> >> DigitsAndUnderscores: >> Digit >> DigitsAndUnderscores Underscores_opt Digit >> >> Digit: >> 0 >> NonZeroDigit >> >> NonZeroDigit: one of >> 1 2 3 4 5 6 7 8 9 >> >> HexNumeral: >> 0 x HexDigitsAndUnderscores >> 0 X HexDigitsAndUnderscores >> >> HexDigitsAndUnderscores: >> HexDigit >> HexDigit Underscores_opt HexDigitsAndUnderscores >> >> HexDigit: one of >> 0 1 2 3 4 5 6 7 8 9 a b c d e f A B C D E F >> >> OctalNumeral: >> 0 OctalDigitsAndUnderscores >> >> OctalDigitsAndUnderscores: >> OctalDigit >> OctalDigit Underscores_opt OctalDigitsAndUnderscores >> >> OctalDigit: one of >> 0 1 2 3 4 5 6 7 >> >> Section 3.10.2 ("Floating-Point Literals") would be modified as follows: >> >> >> FloatingPointLiteral: >> DecimalFloatingPointLiteral >> HexadecimalFloatingPointLiteral >> >> DecimalFloatingPointLiteral: >> DigitsAndUnderscores_opt . DigitsAndUnderscores_opt ExponentPart_opt FloatTypeSuffix_opt >> . DigitsAndUnderscores ExponentPartopt FloatTypeSuffix_opt >> DigitsAndUnderscores_opt ExponentPart FloatTypeSuffix_opt >> DigitsAndUnderscores_opt ExponentPart_opt FloatTypeSuffix >> >> ExponentPart: >> ExponentIndicator SignedInteger >> >> ExponentIndicator: one of >> e E >> >> SignedInteger: >> Sign_opt DigitsAndUnderscores >> >> Sign: one of >> + - >> >> FloatTypeSuffix: one of >> f F d D >> >> HexadecimalFloatingPointLiteral: >> HexSignificand BinaryExponent FloatTypeSuffix_opt >> >> HexSignificand: >> HexNumeral >> HexNumeral . >> 0x HexDigitsAndUnderscores_opt . HexDigitsAndUnderscores >> 0X HexDigitsAndUnderscores_opt . HexDigitsAndUnderscores >> >> BinaryExponent: >> BinaryExponentIndicator SignedInteger >> >> BinaryExponentIndicator:one of >> p P >> >> >> COMPILATION: >> >> Numbers containing underscores are to be parsed and evaluated by the compiler exactly as if the underscores were not present. The above grammar ensures that removing underscores will not result in an unparseable number. >> >> A simple strategy for achieving this is that once a number has been parsed by the compiler lexer and determined to be syntactically valid according to the above grammar, then if the number contains any underscores, then all underscores in it may be removed (by something as simple as numberAsString.replaceAll("_","")) before passing the number on to the code that would normally have parsed the number prior to this proposal. >> >> More performant approaches are certainly possible. >> >> >> TESTING: How can the feature be tested? >> >> A variety of literals may be generated, of the cross product of each of the following radicies: >> >> hex, decimal, octal >> >> with each of the following types: >> >> byte, char, short, int, long, float, double >> >> such that for each possible numeric field in the result, that one or more underscores are inserted at the beginning, in the middle, and at the end of the digits. >> >> Note that the above grammar is specifically designed to disallow any underscores from appearing which are not either preceded by or followed by a digit. >> >> >> LIBRARY SUPPORT: >> >> Methods such as Integer.decode(String) and Long.decode(String) should probably be updated to ignore underscores in their inputs, since these methods attempt to parse according to Java conventions. >> >> I suggest that methods such as Integer.parseInt(), Float.parseFloat(), etc. should probably NOT be updated to ignore underscores, since these methods deal with numbers in their pure form, and are more focused and much more widely used. To alter them to ignore underscores would introduce ambiguity in (and have a performance impact on) various parsing code that uses them. >> >> >> REFLECTIVE APIS: >> >> No changes to reflective APIs are needed. >> >> >> OTHER CHANGES: >> >> No other changes are needed. >> >> >> MIGRATION: >> >> Underscores can be inserted into numbers within an existing code base as desired for readability. >> >> >> COMPATIBILITY >> >> BREAKING CHANGES: >> >> Since use of underscores within numbers was previously a syntax error, this should not break any existing programs. >> >> >> EXISTING PROGRAMS: >> >> This feature does not affect the format of class files. It is purely a notational convenience. Hence, interaction with existing class files would not be affected. >> >> >> REFERENCES >> >> EXISTING BUGS: >> >> A search of the Bug Database did not find any bug ID's related to this proposal. >> >> URL FOR PROTOTYPE (optional): >> >> None. >> >> >> >> > From howard.lovatt at iee.org Wed May 20 22:21:57 2009 From: howard.lovatt at iee.org (Howard Lovatt) Date: Thu, 21 May 2009 15:21:57 +1000 Subject: PROPOSAL: Abstract enums (version 2) Message-ID: <3dd3f56a0905202221ib77c5a0rc52c7020439fb050@mail.gmail.com> Joe, Is it too late to submit a second abstract enum proposal, see Derek's email below? The idea is that the expert group would evaluate both proposals in parallel. -- Howard. Derek Foster writes: Hi, folks. I think Howard's counterproposal might be interesting, if it were fully fleshed out to the degree that my proposal is by now. I might even prefer his to mine, if that were the case. However, it's hard to evaluate in its current form. A lot of potential implementation problems are currently being handwaved past -- a real proposal would have to grapple with these and find specific answers to all of them: Binary compatibility, serialization, how to handle Enum's static methods, how to identify and what to do about inherited or overridden methods that conflict with the current Enum's, how to reduce code bloat in subtypes due to duplicate methods, etc. My "abstract enums" proposal is an attempt to add abstract supertypes to enums while changing as little as possible about how enums currently work, so as to not disturb any existing code (serialization, IDEs, etc.) that might depend on the current semantics and implementation strategy. I went to quite some trouble to minimize the scope of the changes to try to make the proposal small enough for Project Coin and to minimize any disruption to the compiler or libraries. Howard's suggested counterproposal attempts to achieve a little bit more (the ability for an enum and a non-enum to share a supertype) by totally changing how enums are implemented. In particular, under Howard's proposal, Enum becomes an interface, not an abstract superclass, and its methods become duplicated in each leaf subclass rather than inherited. Plus some changes would have to be made to the compiler to hack in a way to still do things like "Enum.valueOf(Foo.class, "bar")" (I don't buy Howard's argument that we can just abandon backwards compatibility and encourage people to migrate away from these static methods, although I think that this "abstract class->interface" migration is a good argument for the "static methods in interfaces" proposal that was put forth on the list a while ago and (IIRC) already shot down. Possibly we could just hack the compiler to treat "Enum.valueOf" as a special case and map the method invocation to a different static method on another class in java.lang, though.) Still, overall, what Howard proposes is a pretty major change to how enums of all kinds (not just abstract ones!) work. I'm not necessarily opposed to it -- David raises some good points about its applicability, and I can recall some times where I might have been inclined to extend an enum from a non-enum abstract class for the purpose of creating a singleton or a fixed-size set of them, if the option had been available. Howard's approach would meet my abstract enum needs as well as mine does, and has some other minor pluses, so in that sense, I don't really care about which approach is taken... if there aren't hidden "gotcha's" as far as implementation goes, which is hard to tell at this level of detail. If Howard wants to try 'fork'ing my proposal and modifying it to add a parallel version of it implemented along the lines he suggests, I won't mind (although Joe might, if he considers it a new (late) proposal instead of a modification of an existing one). Ideally, the two co-proposals would be considered in parallel. However, I'm not currently planning to abandon my proposal's current implementation approach in favor of Howard's unless I am convinced that Howard's has a better chance of actually being selected by Sun -- which would imply at the very least that it has been described in exacting detail and that all implementation challenges have been identified and that specific solutions for them are proposed, and have been vetted by the Project Coin listmembers. (Is there still time to do this? Questionable...) This would have been a lot easier if a proposal along the lines of what Howard is suggesting had been put forth before the cutoff deadline for proposal submissions... Derek From peter.levart at gmail.com Wed May 20 23:54:15 2009 From: peter.levart at gmail.com (Peter Levart) Date: Thu, 21 May 2009 08:54:15 +0200 Subject: Notes on implementing concise calls to constructors with type parameters In-Reply-To: <3dd3f56a0905180113l1b7dab5fge695caba96fdcf72@mail.gmail.com> References: <3dd3f56a0905132041r67710789if86d4e942987a039@mail.gmail.com> <15e8b9d20905132115r58bfe6a7naa6952e5f94c1392@mail.gmail.com> <3dd3f56a0905140543v63603bd4qed2a149fc06cb0ce@mail.gmail.com> <15e8b9d20905140932g33fbcd7atd6c6e28f95211cb4@mail.gmail.com> <3dd3f56a0905150026ta489f58lece1b35ee17df44d@mail.gmail.com> <15e8b9d20905150633n5f3cbb92q79a37a4e736b93b9@mail.gmail.com> <3dd3f56a0905180113l1b7dab5fge695caba96fdcf72@mail.gmail.com> Message-ID: Hello Howard, What Neal and others are trying to point out is that your "textual substitution algorithm" is not defined. The name "textual" implies that it should be simple. But the right thing to do is not simple at all. Have you looked at the 3rd JLS section 15.12.2.7 ? To just scratch the surface, take the following example: public interface IntA { ... } public class ClsA implements IntA { ... } public class ClsB implements IntA { ... } ... public void doIt(IntA param) { ... } ... // what should "textual substitution" do in the following 2 cases: anInstance.doIt(new ClsA()); // vs. anInstance.doIt(new ClsB()); Peter. On Mon, May 18, 2009 at 10:13 AM, Howard Lovatt wrote: > Hi Neal, > > Yes I should have spelled this out, it is one of those things obvious > to the author but not to the reader. I would propose that given more > than one method of the same name, method in example below, with the > general declaration for each following the syntax: > > ... method ( typeLHS [] name , ... ) { ... } > > and given the call: > > ... method ( new [typeRHS] [] ( ... ) , ... ); > > Then a three step procedure would be used: > > 1. If typeRHS is absent assume for step 2 type Void, where Void is the > bottom type (in Java 7 this may be called Null but I chose Void to be > consistent with the InvokeDynamic proposal) > > 2. Resolve method as normal and hence find typeLHS and if specified > genericParametersLHS also > > 3. Apply textual substitution algorithm, i.e. If typeRHS is absent > substitute typeLHS and if genericParametersRHS is absent and > genericParametersLHS is present then substitute genericParametersLHS > > For example, given two methods: > > void method( Object notUsed ) { out.println( "Object" ); } > void method( String notUsed ) { out.println( "String" ); } > > The call: > > method( new() ); > > would print String because it would be translated by the textual > substitution algorithm into method( new String() ), i.e. the same > behaviour as method( null ) because null has type Void (bottom). > > Does that add sufficient clarity? I would be really interested if you > can see a problem with the technique? > > If not the method maybe a good solution as it has many desirable > characteristics (as listed in previous posts in this thread). I also > note that many people would like a var or auto style declaration and > maybe this proposal of text substitution can satisfy more people than > other proposals, since it retains LHS types but saves re-specification > of type, generic type, and doesn't require a diamond operator on the > RHS. > > -- Howard. > > > From reinier at zwitserloot.com Thu May 21 01:21:25 2009 From: reinier at zwitserloot.com (Reinier Zwitserloot) Date: Thu, 21 May 2009 10:21:25 +0200 Subject: Checked Exceptions do not exist on the JVM. In-Reply-To: References: <39084932-B2CC-4B91-97EA-006FE21301F0@googlemail.com> <4A1339ED.8090309@sun.com> <68BF955A-9796-44F7-9E97-94BBB43ADCC5@zwitserloot.com> <988330f1d03fc629490d5dffa3fc2d25.squirrel@wmail.gradsoft.ua> Message-ID: <03A0D853-0216-4983-B17C-799D8A9A8103@zwitserloot.com> Ruslan: Why do you keep mentioning LinkageError? I'll try to explain the 'not- care' keyword one more time: int f() not-care MyException { throw MyException(); } does the *exact* same thing as: int f() throws MyException { throw MyException(); } The only difference is for javac: In the second case, with the throws statement, the caller must either wrap their call to f() in a try/ catch block nd catch MyException, -or-, the caller must add a 'throws MyException' to their method. However, in the not-care case, a caller does NOT have to do these things. That's all. Also, we can't add 'throws Throwable' to Class.newInstance - it would break backwards compatibility. It's also not the only problem - you can't close the 'construct a class file' hole, and you certainly can't close the 'there are other languages that run on the JVM' hole. Java does not break backwards compatibility. I'll let Joe give the final word, but the odds that java will add 'throws Throwable' to Class.newInstance, or adds 'throws Exception' to java.lang.Runnable, are somewhere between pigs flying and hell freezing over. It just won't happen. I'm specifically NOT proposing to destroy the building - that would be 'Let's get rid of checked exceptions' altogether. --Reinier Zwitserloot On May 20, 2009, at 15:47, Ruslan Shevchenko wrote: >> Ruslan, you've got it all wrong. Though, you've just proved to this >> list that java programmers don't really get this concept, which is >> one >> of the reasons why I want to introduce it: Make it obvious to java >> programmers that the JVM does *NOT* guarantee that checked exceptions >> are declared. >> >> Checked exceptions do not exist. >> >> That's right. They don't. There's no such thing. It's all a figment >> of >> javac. The JVM does not have checked exceptions. All it knows about >> is >> 'throws clauses', which are part of a method's signature and have >> ZERO >> impact on how a JVM runs a class file. As far as the JVM is >> concerned, >> throws clauses are just a comment. Utterly ignored by javac. You can >> strip every single one out of every class file and run an app, and >> the >> execution of it would be 100% the same. The only change would be in >> java.lang.reflect's getExceptionTypes() method. >> > > What means 'really' ? > Can we say, that ... for examples, 'for' construct does not exists, > because it emulated by 'if-s' on JVM level ? > >> >> In other words: There is *NO* guarantee whatsoever in the JVM that >> checked exceptions can only occur in situations where they are >> explicitly declared. If your code relies on it, then your code is >> buggy. >> > > Java (as language) give me some isolation level. Of course not 100%, > (Class.newInstance() is a hole. > //I misread documentation, because I was not able to imagine that such > //hole exists (!). > But you propose to destroy building because exists one hole, > instead fixing building ? Better fix - is declare > Class.newInstance() to > throw Throwable. > > Can I ask community: > anybody know, why such situation exists and reason not to fix > Class.newInstance() ? > > >> >> Thirdly, you misunderstand what my ignoreslist proposal does: It does >> not silently swallow the exception, that'd be a very stupid way of >> handling exceptions that you don't -think- can occur. An ignoreslist > > Yes, (I wrote this in my next letter). > // word 'ignore' fooled me and will fool others. > Let's speak 'not-care' instead 'ignore' > > So > int f() not-care MyException > { > > } > > will throw MyException, which will be not handled for JVM, for > programmer > this mean, that this code: > > 1. will throw LinkageError, when f is not called inside some try > blocks, > where MyException is not catched. > 2. will throw MyException, when f is called inside some try blocks, > where > MyException (or generic Exception or Throwable) is cathed. > > >> >> You're also mistaken in retrofitting Runnable with 'throws >> Exception': >> That'll break many thousands of classes out there in real life. You >> forget that people don't just make Runnables and hand them off to >> java.lang.Thread; there's plenty of code out there that *receives* >> Runnables, and that code presumes that its run() method does not >> throw >> any checked exceptions. It would be backwards compatible (because, as >> I said, the JVM doesn't know about these things), but it wouldn't be > > // Hmm, looks like my next letter was not in list. (in which I > correct self > //in this points) > //I guess 1.6 -> 1.7 transition can break API compatibility: it's > major > //revision change. > > Java (as language) support *both* checked and unchecked exception. > More realistic approach for transition 'all exceptions unchecked' is > change API to throw unchecked exception. (Which we see on practice in > layered software system, and where rethrow proposal good for). > > > > From reinier at zwitserloot.com Thu May 21 01:33:21 2009 From: reinier at zwitserloot.com (Reinier Zwitserloot) Date: Thu, 21 May 2009 10:33:21 +0200 Subject: Checked Exceptions do not exist on the JVM. In-Reply-To: <4A1445B2.3070304@sun.com> References: <39084932-B2CC-4B91-97EA-006FE21301F0@googlemail.com> <4A1339ED.8090309@sun.com> <68BF955A-9796-44F7-9E97-94BBB43ADCC5@zwitserloot.com> <988330f1d03fc629490d5dffa3fc2d25.squirrel@wmail.gradsoft.ua> <4A1445B2.3070304@sun.com> Message-ID: <30086D82-D94C-48EC-9B6D-C4F14F9AB935@zwitserloot.com> Joe, perhaps you missed it in all the hullabaloo about the Class.newInstance() and class construction holes, which aren't the interesting reasons to add dont-care. These are: 1. Java actively wants to integrate better with other languages. We should extend this principle to exception handling. 2. The exception hierarchy has many flaws in it. As far as I can tell, this is undisputed, and I've already sent a very long email listing many examples. The problem with this, is that its causing average java programmers to strongly dislike the exception system, and as a result, to write bad code. I've also explained the how and why of this in depth. Adding a dont-care option would give programmers an easy way out when, either through a flawed hierarchy or an unexpected situation, they are forced into dealing with an exception they know either can't happen or can safely be thrown onwards but e.g. an interface restricts their throws lists. 3. In situations where that does happen (such as IOExceptions falling out of resources loaded via ClassLoader.getResourceAsStream, or UnsupportedEncodingExceptions falling out of new String(bytes, "UTF-8"), or throwing a checked exception out of a Runnable.run() method passed to a thread), java programmers are currently forced into writing boilerplate that actually makes their code worse as well! - such exceptions get either wrapped, which is bad, because trying to find the signal in the noise of an exception with 20 causes (it happens, all the time, in frameworks) can already be a formidable problem, and wrapping an exception just for the sake of retrofitting it to an unchecked form ALWAYS adds 1 level of noise to the chain. The alternative is that they get swallowed or printed to the console, which is even worse, for obvious reasons. So, it's that, -and- the boilerplate, -and- the alienation of the average java programmer to the exception system. All bad things, and it happens quite often (that is; situations where you are forced by javac to deal with a checked exception where javac is essentially wrong, and you really should not be forced into dealing with it). 4. I offered a less contentious alternative: Add Throwable.sneakyThrow(Throwable t) to java.lang.Throwable, and lobby IDEA, Eclipse, and the NetBeans team to change the way the 'quickfix' feature works when trying to quickFix the 'uncaught checked exception' compiler error, by wrapping in a try/catch block and sneaky throwing the exception, which is superior. (clearly, to me, and I haven't heard anybody give me a reason or alternative why I'm wrong) --Reinier Zwitserloot On May 20, 2009, at 20:02, Joseph D. Darcy wrote: > Well said Tom. > > Additionally, on the point of interfacing with other language in > Java, the possibility of having what are in Java checked exceptions > thrown by the caller argue for Dynamic call sites to be regarded as > being able to throw Exception so that the existing Java semantics > and checking can be preserved. > > -Joe > > Tom Ball wrote: >> I don't consider "Ruslan, you've got it all wrong" an example of >> opening a >> "perfectly civil email", it sounds like bullying. This isn't >> slashdot, it's >> a forum for discussions on possible small improvements to the Java >> language. So I shouldn't have responded with the same tone as your >> message, >> and for that I apologize to the wider group. >> >> An "it's possible to write bad code" argument doesn't refute other >> people's >> valid arguments. Developers are always capable of writing bad >> code, and >> anyone who designs a language or runtime where it's impossible will >> have >> trouble finding adoption because it's too restrictive. Who cares >> if sneaky >> throw works? If a library abuses that hack, don't use it. >> >> The purpose of throws clauses is to better describe the contract a >> method >> offers for its callers: it only accepts parameters of a certain >> type, it >> returns an instance of a specific type, and under certain (hopefully >> documented) conditions it may throw specific exceptions. Checked >> exceptions >> are intended to call out specific exceptions that the library writer >> believes the caller should be able to recover from, and therefore >> should >> handle or forward. If a library writer subverts the contract of >> his own >> method, well, that's a shame but doesn't necessarily call for >> changes to the >> language. If a non-Java language has libraries which throw what >> are in Java >> checked exceptions, then write Java code which does more checking >> at runtime >> since that's apparently what the other language requires (or don't >> use those >> libraries). >> >> This isn't a problem, and so there is nothing about it that needs >> fixing in >> Java 7. >> >> Tom >> >> On Wed, May 20, 2009 at 9:39 AM, Reinier Zwitserloot < >> reinier at zwitserloot.com> wrote: >> >> >>> Tom, here are two class files: >>> >>> Foo.class >>> Bar.class >>> >>> which one adheres to the JLS checked exception model, and which >>> one has >>> methods that leak checked exceptions without declaring them? >>> >>> I can't tell. Can you? >>> >>> You can quote me JLS specs all day long, mis-interpret my words >>> and write >>> in a denigrating fashion, but none of that changes the plain fact: >>> >>> You CAN NOT RELY ON THROWS CLAUSES. Checked exceptions can fall >>> out of >>> *any* method *anywhere*. Period. I thought when I mentioned "checked >>> exceptions in situations where you didn't expect them", it was >>> obvious from >>> context that I meant: checked exceptions falling out of methods >>> that don't >>> declare them, but apparently I need to spell this out for you. >>> >>> You also conveniently forgot that, even if you're only using >>> javac, you can >>> still get sneakyThrow: You can expicitly sneakyThrow via class file >>> construction or using the .newInstance() trick, or get accidental >>> sneakyThrow when compiling against v1 of a class, but running with >>> v2 (which >>> added a bunch of checked exceptions). Point me to the entry in the >>> JLS that >>> makes this impossible, please. It doesn't exist, so, take your >>> pedantic >>> whinging about "JLS spec", print it out, and eat it*. >>> >>> >>> *) I get annoyed when people write 'WTF' and 'I give up' in >>> response to a >>> perfectly civil email. >>> >>> >>> Example: >>> >>> public class Foo { >>> public static void foo() {} >>> } >>> >>> as Foo.class >>> >>> and this: >>> >>> public class Bar { >>> public static void main(String[] args) { >>> Foo.foo(); >>> } >>> } >>> >>> as Bar.class. >>> >>> Then edit Foo.java to this and recompile (but don't recompile >>> Bar.java!), >>> then rerun Bar: >>> >>> public class Foo { >>> public static void foo() throws java.io.IOException { >>> throw new java.io.IOException("Apparently this will make Tom >>> Ball's >>> head explode. Whoops!"); >>> } >>> } >>> >>> ... and behold! Tom Ball's head explodes. >>> >>> --Reinier Zwitserloot >>> >>> >>> >>> >>> On May 20, 2009, at 18:11, Tom Ball wrote: >>> >>> On Wed, May 20, 2009 at 6:35 AM, Reinier Zwitserloot < >>> >>>> reinier at zwitserloot.com> wrote: >>>> >>>> Checked exceptions do not exist. >>>> Sure they do, but they are a Java language concept, not a >>>> JVM one. The >>>> same >>>> is true for lots of other Java language features. >>>> >>>> That's right. They don't. There's no such thing. It's all a >>>> figment of >>>> >>>> >>>>> javac. >>>>> >>>>> >>>> You must mean that checked exceptions are defined by the Java >>>> Language >>>> Specification. javac is just a compiler that adheres to the JLS, >>>> like >>>> many >>>> other Java compilers. >>>> >>>> >>>> The JVM does not have checked exceptions. All it knows about is >>>> >>>>> 'throws clauses', which are part of a method's signature and >>>>> have ZERO >>>>> impact on how a JVM runs a class file. As far as the JVM is >>>>> concerned, >>>>> throws clauses are just a comment. Utterly ignored by javac. >>>>> >>>>> >>>> No compiler can ignore the throws part of a method signature and >>>> be a >>>> valid >>>> Java language compiler. Having worked on javac, I know for a >>>> fact that >>>> whether a class symbol is read from a source or class file, its >>>> methods >>>> include all defined throws clauses and enforces their use as the >>>> JLS >>>> dictates. The javac source is publicly available -- check out >>>> the Symbol >>>> and ClassReader classes. >>>> >>>> >>>> You can >>>> >>>>> strip every single one out of every class file and run an app, >>>>> and the >>>>> execution of it would be 100% the same. The only change would be >>>>> in >>>>> java.lang.reflect's getExceptionTypes() method. >>>>> >>>>> I repeat: The JVM *DOES* *NOT* know about checked exceptions. >>>>> The JVM >>>>> assumes all exceptions are unchecked, and assumes that javac >>>>> sorted it >>>>> all out. This is flawed, obviously, because javac isn't the only >>>>> tool >>>>> out there that can make class files. >>>>> >>>>> >>>> Flawed? The Java Language and the JVM have different >>>> specifications; the >>>> JLS defines checked exceptions, and the JVMS doesn't. The JVM >>>> support >>>> many >>>> different languages besides Java, most of whom don't define checked >>>> exceptions. That's not a flaw, but support for language >>>> independence. >>>> The >>>> reason the JVM considers all exceptions as runtime exceptions is >>>> because >>>> it's the runtime. >>>> >>>> >>>> This is similar to generics in >>>> >>>>> objects, which is also a figment of javac's imagination: On the >>>>> JVM >>>>> level, erasure occurs - that info just isn't there. If you want, >>>>> you >>>>> can name this 'checked exception erasure'. The notion that >>>>> exceptions >>>>> are checked is erased during compilation. >>>>> >>>>> >>>> Not true. Yes, the JVM doesn't support generics, but classfiles >>>> contain >>>> all >>>> information needed to correctly compile classes which use them. >>>> The same >>>> is >>>> true for exceptions, as the JLS requires. >>>> >>>> >>>> The only application in existence that cares about this 'throws >>>> >>>>> clauses' comment in class files is the application called 'javac'. >>>>> >>>>> >>>> You are going to make engineers support other Java compilers >>>> upset with >>>> this >>>> incorrect assumption. They all have to support checked >>>> exceptions, or >>>> they >>>> aren't Java compilers. >>>> >>>> It gets worse: JRuby, groovy, Jython, and scala, they ALL feature >>>> >>>> >>>>> *ZERO* checked exception clauses on methods. They just generate >>>>> class >>>>> bytecode with throw statements without caring about the throws >>>>> clause >>>>> on methods. >>>>> >>>>> >>>> Worse? Different languages make different trade-offs between >>>> compile and >>>> runtime checking, and it's a matter of personal preference what >>>> trade-offs >>>> you want. There is no "better" or "worse", which is why the JVM >>>> doesn't >>>> require one or the other. >>>> >>>> >>>> This is why, in java, anytime you interop with code not >>>> >>>>> compiled by javac, you can get checked exceptions in situations >>>>> where >>>>> you didn't expect them. >>>>> >>>>> >>>> WTF? If you are calling libraries written in other languages, >>>> those >>>> libraries throw exceptions as defined by their language >>>> specifications. >>>> If >>>> you don't like the contracts of those libraries, don't use them. >>>> >>>> I give up, >>>> Tom >>>> >>>> >>>> Millions of classes generated by those >>>> >>>>> compilers are out there right now throwing checked exceptions that >>>>> escape from methods that do NOT have a 'throws X' clause on them. >>>>> >>>>> In other words: There is *NO* guarantee whatsoever in the JVM that >>>>> checked exceptions can only occur in situations where they are >>>>> explicitly declared. If your code relies on it, then your code >>>>> is buggy. >>>>> >>>>> >>>>> Secondly, you mentioned that java wraps exceptions that occur in >>>>> the >>>>> constructor with Class.newInstance() into an >>>>> ExceptionInInitializerError. That's not what happens at all; That >>>>> exception (ExceptionInInitializerError) is for static >>>>> initializers and >>>>> object initializers, not constructors. A practical example will >>>>> make >>>>> this clear. Take the following code, save it in Foo.java, >>>>> compile it, >>>>> and run it: >>>>> >>>>> import java.io.IOException; >>>>> >>>>> public class Foo { >>>>> public static class Test { >>>>> public Test() throws IOException { >>>>> throw new IOException(); >>>>> } >>>>> } >>>>> >>>>> //Note how I didn't add 'throws IOException' in the next line! >>>>> public static void main(String[] args) throws >>>>> InstantiationException, IllegalAccessException { >>>>> Test x = Test.class.newInstance(); >>>>> } >>>>> } >>>>> >>>>> >>>>> The result is an IOException. Not a ObjectInstantionException >>>>> with an >>>>> IOException as cause; no - an IOException. You can doublecheck >>>>> this >>>>> by wrapping the newInstance in a try/catch (Throwable t) block >>>>> and >>>>> printing the class name of the resulting t. >>>>> >>>>> Thirdly, you misunderstand what my ignoreslist proposal does: It >>>>> does >>>>> not silently swallow the exception, that'd be a very stupid way of >>>>> handling exceptions that you don't -think- can occur. An >>>>> ignoreslist >>>>> has zero effect on the execution of a method body. The only >>>>> difference >>>>> is that, unlike a throws clause, you don't burden any of the >>>>> methods >>>>> that call you to handle the listed exception. It's a signal to >>>>> javac >>>>> to disable its rigid checking of making sure any checked exception >>>>> thrown in the body is also present in that method's 'throws' >>>>> clause. >>>>> It's exactly analogous to adding the 'throws' clause, compiling >>>>> the >>>>> code, then using a hex editor to remove the throws clause. >>>>> >>>>> >>>>> You're also mistaken in retrofitting Runnable with 'throws >>>>> Exception': >>>>> That'll break many thousands of classes out there in real life. >>>>> You >>>>> forget that people don't just make Runnables and hand them off to >>>>> java.lang.Thread; there's plenty of code out there that *receives* >>>>> Runnables, and that code presumes that its run() method does not >>>>> throw >>>>> any checked exceptions. It would be backwards compatible >>>>> (because, as >>>>> I said, the JVM doesn't know about these things), but it >>>>> wouldn't be >>>>> source compatible; recompiling your code would all of a sudden >>>>> produce >>>>> errors. e.g: >>>>> >>>>> public void myMethod(Runnable r) { >>>>> r.run(); >>>>> } >>>>> >>>>> would no longer compile, because all of a sudden 'r.run();' can >>>>> throw >>>>> Exception, which I need to catch, or declare as thrown (or, if >>>>> this >>>>> proposal is accepted, declare as sneakyThrown/ignore). >>>>> >>>>> >>>>> --Reinier Zwitserloot >>>>> >>>>> >>>>> >>>>> On May 20, 2009, at 07:01, Ruslan Shevchenko wrote: >>>>> >>>>> Here's a trivially simple change to implement, though it has >>>>> some far >>>>> >>>>>>> reaching repercussions for java as a whole: >>>>>>> >>>>>>> change the 'rethrows' clause to an ignores clause: Any checked >>>>>>> exception in the ignores list may be thrown from the method >>>>>>> body, but >>>>>>> is NOT part of the method's checked exception list. It is >>>>>>> hence also >>>>>>> not part of the signature, just like sticking a 'synchronized' >>>>>>> keyword >>>>>>> on a method isn't part of its signature, but an implementation >>>>>>> detail. >>>>>>> >>>>>>> >>>>>>> example: >>>>>>> >>>>>>> Runnable r = new Runnable() { >>>>>>> public void run() ignores UnsupportedEncodingException { >>>>>>> String x = new String(inBytes, "UTF-8"); >>>>>>> } >>>>>>> }; >>>>>>> >>>>>>> >>>>>>> >>>>>> And how actually debug such statements ? >>>>>> //In this example, run() method do nothing, so look on slightly >>>>>> complex >>>>>> primer: >>>>>> >>>>>> class X >>>>>> { >>>>>> String x; >>>>>> >>>>>> public void setString(byte[] inBytes) >>>>>> ignores >>>>>> UnsupportedEncodingException >>>>>> { >>>>>> x = new String(inBytes, "UUTF-8"); >>>>>> } >>>>>> >>>>>> public void setAndPrintString(byte[] inBytes) >>>>>> { >>>>>> setString(inBytes); >>>>>> System.out.println("received:"+x); >>>>>> } >>>>>> >>>>>> >>>>>> } >>>>>> >>>>>> Assume, that programmer wrote (by error) "UUTF-8" instead "UTF-8" >>>>>> >>>>>> Output of programm will be "received:null". >>>>>> Reasons for null x in complex programs can be millions. >>>>>> Debugging with >>>>>> ignoring exception will be extremally hard. >>>>>> >>>>>> I. e. wrapping checked exception to runtime is more or less >>>>>> normal; >>>>>> ignoring will become a very big paint-point. >>>>>> >>>>>> Alternative to ignore can be call default thread exception >>>>>> handler. >>>>>> (handle keyword ?) >>>>>> >>>>>> This sounds like blowing up the entire point of checked >>>>>> exceptions, >>>>>> >>>>>>> but with java moving towards more interoperation with other >>>>>>> JVM based >>>>>>> languages, which almost always throw checked exceptions without >>>>>>> actually declaring them (Jython, JRuby, Scala -- I can't think >>>>>>> of a >>>>>>> single one other than java itself that has the notion of checked >>>>>>> exceptions in the first place). If the whole 'java is like the >>>>>>> assembler of the JVM' story is going to hold water, something >>>>>>> like >>>>>>> this is needed. >>>>>>> >>>>>>> >>>>>>> >>>>>> Yes, this is interesting problem. >>>>>> In theory we have UndeclaredThowableException, but .. wrapping >>>>>> each >>>>>> invocation of foreign language into it is ineffecient. >>>>>> >>>>>> But InvokeDynamic can throws any throwable in declaration, so >>>>>> this >>>>>> problem >>>>>> can be solved (on other level) >>>>>> >>>>>> For some further support: I doubt anyone seriously holds the >>>>>> position >>>>>> >>>>>>> that java's checked exception experiment was an unmitigated >>>>>>> success. >>>>>>> There are pain points, here and there. The above example in fact >>>>>>> includes two of them: The fact that runnable throws no checked >>>>>>> exceptions is clearly a mistake in regards to threading, because >>>>>>> Thread objects clearly should handle ANY exception falling out >>>>>>> of its >>>>>>> run() method (and it in fact does, via the unchecked exception >>>>>>> handler >>>>>>> mechanism), and there's a general mismatch between main(), >>>>>>> which MAY >>>>>>> throw exceptions, and run(), which may not, even though they >>>>>>> are both >>>>>>> 'thread start points'. Another mistake is >>>>>>> >>>>>>> >>>>>> Adding throw exception to signature of Runnable.run does not >>>>>> broke >>>>>> anything in existent code, so this can be nice library change. >>>>>> >>>>>> UnsupportedEncodingExceptions, a checked exception, resulting >>>>>> from a >>>>>> >>>>>>> call to converting byte arrays to strings using an encoding >>>>>>> that is >>>>>>> guaranteed by the JVM using a string literal, such as "UTF-8". >>>>>>> The >>>>>>> appropriate exception would be UnsupportedEncodingError("This >>>>>>> JVM is >>>>>>> broken. Charset UTF-8 missing. Reinstall it") - which is >>>>>>> unchecked. >>>>>>> >>>>>>> >>>>>>> >>>>>> Or porgrammer can write UUTF-8 instead UTF-8. It's happens ;) >>>>>> >>>>>> In other words, while I'm not ready to write off checked >>>>>> exceptions >>>>>> >>>>>>> as >>>>>>> a whole, I am more than ready to acknowledge that the >>>>>>> programmer more >>>>>>> often knows better than the compiler, compared to how often the >>>>>>> programmer, in laziness or inexperience, abuses this freedom. >>>>>>> Especially considering that, on the JVM, you really DONT get >>>>>>> checked >>>>>>> exceptions guarantees; any class compiled by anything other than >>>>>>> javac >>>>>>> is free to throw checked exceptions without declaring them, >>>>>>> and even >>>>>>> in javac you can technically do this using 'sneaky throw' >>>>>>> libraries, >>>>>>> which use various workarounds, one of which will NEVER go away*. >>>>>>> We're >>>>>>> not losing much here, in other words. In fact, the way javac >>>>>>> works, >>>>>>> inexperienced java programmers may erroneously assume that >>>>>>> checked >>>>>>> exceptions couldn't possibly happen unless the checked >>>>>>> exception is >>>>>>> declared. This is not the case. >>>>>>> >>>>>>> *) The one that will never go away is >>>>>>> java.lang.Class.newInstance(), >>>>>>> which is functionally defined to sneakily throw on any >>>>>>> exceptions >>>>>>> thrown by the constructor, checked or not, and does NOT wrap >>>>>>> them up >>>>>>> into a wrapper the way java.lang.reflect.Method.invoke() does. >>>>>>> This >>>>>>> >>>>>>> >>>>>> Its wrapped to java.lang.ExceptionInInitializerError >>>>>> >>>>>> >>>>>> cannot change without breaking backwards compatibility. Another >>>>>> one >>>>>> >>>>>>> that will never go away is constructing a class on the fly that >>>>>>> sneaky >>>>>>> throws, loading it with ClassLoader's load from bytes >>>>>>> mechanism, and >>>>>>> executing it. >>>>>>> >>>>>>> >>>>>>> >>>>>> And what is JVM behaviour in such case ? >>>>>> >>>>>> >>>>>> >>>>>>> Attempting to solve this issue with a library requires rather >>>>>>> a lot >>>>>>> of >>>>>>> ugly boilerplate: >>>>>>> >>>>>>> import static Utils.sneakyThrow; >>>>>>> >>>>>>> Runnable r = new Runnable() { >>>>>>> public void run() { >>>>>>> String x; >>>>>>> try { >>>>>>> x = new String(inBytes, "UTF-8"); >>>>>>> } catch ( UnsupportedEncodingException e ) { >>>>>>> sneakyThrow(e); >>>>>>> } >>>>>>> } >>>>>>> }; >>>>>>> >>>>>>> >>>>>>> NB: For sanity purposes, the restriction on javac that the try >>>>>>> block >>>>>>> MUST contain at least 1 statement that could throw a checked >>>>>>> exception >>>>>>> type that is listed on one of the accompanying catch blocks >>>>>>> (other >>>>>>> than Exception, which you can always catch), should go away; >>>>>>> this has >>>>>>> already been proposed before, and in fact is a backwards >>>>>>> compatibility >>>>>>> painpoint for the coin proposal that allows you to rethrow a >>>>>>> final >>>>>>> Exception as if its type is the intersection of all checked >>>>>>> types >>>>>>> thrown by the statements in the try body. >>>>>>> >>>>>>> --Reinier Zwitserloot >>>>>>> Like it? Tip it! >>>>>>> http://tipit.to >>>>>>> >>>>>>> >>>>>>> >>>>>>> On May 20, 2009, at 02:22, Mark Mahieu wrote: >>>>>>> >>>>>>> Yeah, I suppose I did make it rather more complicated than it >>>>>>> needed >>>>>>> >>>>>>>> to be. >>>>>>>> >>>>>>>> Thanks for the feedback. >>>>>>>> >>>>>>>> Mark >>>>>>>> >>>>>>>> >>>>>>>> On 19 May 2009, at 23:59, Joe Darcy wrote: >>>>>>>> >>>>>>>> Hello. >>>>>>>> >>>>>>>>> Hmm; this strikes me as a bit involved for the potential >>>>>>>>> benefits >>>>>>>>> of the feature. >>>>>>>>> >>>>>>>>> -Joe >>>>>>>>> >>>>>>>>> On 03/30/09 05:04 PM, Mark Mahieu wrote: >>>>>>>>> >>>>>>>>> >>>>>>>>>> Forgot my JLS references in the first one... >>>>>>>>>> >>>>>>>>>> >>>>>>>>>> >>>>>>>>>> HTML version + prototype available at: >>>>>>>>>> >>>>>>>>>> http://slm888.com >>>>>>>>>> >>>>>>>>>> >>>>>>>>>> >>>>>>>>>> >>>>>>>>>> Rethrows Clause >>>>>>>>>> v0.1.1 >>>>>>>>>> >>>>>>>>>> >>>>>>>>>> AUTHOR(S): >>>>>>>>>> >>>>>>>>>> Mark Mahieu >>>>>>>>>> >>>>>>>>>> >>>>>>>>>> OVERVIEW >>>>>>>>>> >>>>>>>>>> FEATURE SUMMARY: Should be suitable as a summary in a >>>>>>>>>> language >>>>>>>>>> tutorial. >>>>>>>>>> >>>>>>>>>> A new clause on method declarations which allows exception >>>>>>>>>> translations (wrapping and rethrowing as a different type) >>>>>>>>>> to be >>>>>>>>>> cleanly defined separately from the body of the method. In >>>>>>>>>> many >>>>>>>>>> cases, checked exception type names do not then need to be >>>>>>>>>> repeated in a method's throws clause and in a throw >>>>>>>>>> statement in >>>>>>>>>> the method body. >>>>>>>>>> >>>>>>>>>> >>>>>>>>>> MAJOR ADVANTAGE: What makes the proposal a favorable change? >>>>>>>>>> >>>>>>>>>> The proposal adds direct support for a common idiom in >>>>>>>>>> daily use >>>>>>>>>> by Java programmers worldwide, allowing them to express >>>>>>>>>> their >>>>>>>>>> intentions with greater clarity and ease. In comparison >>>>>>>>>> with >>>>>>>>>> some proposals, this is an attempt to make dealing with >>>>>>>>>> checked >>>>>>>>>> exceptions easier by increasing the expressiveness of >>>>>>>>>> exception >>>>>>>>>> handling code in general, rather than by attempting to >>>>>>>>>> deprecate >>>>>>>>>> checked exceptions in favour of unchecked exceptions. >>>>>>>>>> >>>>>>>>>> >>>>>>>>>> MAJOR BENEFIT: Why is the platform better if the proposal is >>>>>>>>>> adopted? >>>>>>>>>> >>>>>>>>>> There is a reduction in the amount of boilerplate Java >>>>>>>>>> programmers have to read and write for code dealing with >>>>>>>>>> checked >>>>>>>>>> exceptions. Declarations specifying both thrown and >>>>>>>>>> rethrown >>>>>>>>>> (wrapped) exceptions are kept together, aiding >>>>>>>>>> comprehension of >>>>>>>>>> the code. >>>>>>>>>> >>>>>>>>>> >>>>>>>>>> MAJOR DISADVANTAGE: There is always a cost. >>>>>>>>>> >>>>>>>>>> As with any syntax sugar which enables an alternative way of >>>>>>>>>> expressing an existing idiom, programmers may be tempted to >>>>>>>>>> use >>>>>>>>>> it even when the existing idiom would be more appropriate. >>>>>>>>>> >>>>>>>>>> >>>>>>>>>> ALTERNATIVES: Can the benefits and advantages be had some way >>>>>>>>>> without a language change? >>>>>>>>>> >>>>>>>>>> No. >>>>>>>>>> >>>>>>>>>> >>>>>>>>>> EXAMPLES >>>>>>>>>> >>>>>>>>>> SIMPLE EXAMPLE: Show the simplest possible program >>>>>>>>>> utilizing the >>>>>>>>>> new feature. >>>>>>>>>> >>>>>>>>>> >>>>>>>>>> Before: >>>>>>>>>> >>>>>>>>>> void before() throws ConfigException { >>>>>>>>>> try { >>>>>>>>>> Class.forName("where.is.the.Code"); >>>>>>>>>> } >>>>>>>>>> catch (ClassNotFoundException e) { >>>>>>>>>> throw new ConfigException(e); >>>>>>>>>> } >>>>>>>>>> } >>>>>>>>>> >>>>>>>>>> After: >>>>>>>>>> >>>>>>>>>> void after() >>>>>>>>>> catch ClassNotFoundException throw ConfigException { >>>>>>>>>> >>>>>>>>>> Class.forName("here.is.the.Code"); >>>>>>>>>> } >>>>>>>>>> >>>>>>>>>> >>>>>>>>>> ADVANCED EXAMPLE: Show advanced usage(s) of the feature. >>>>>>>>>> >>>>>>>>>> Before: >>>>>>>>>> >>>>>>>>>> void suspendAccount() >>>>>>>>>> throws AuthorizationException, >>>>>>>>>> PersistenceException { >>>>>>>>>> try { >>>>>>>>>> checkMyAuthoritah(); >>>>>>>>>> db.update(/*...*/); >>>>>>>>>> log.recordInfo(/*...*/); >>>>>>>>>> } >>>>>>>>>> catch (InfernalDBException e) { >>>>>>>>>> throw new PersistenceException(e); >>>>>>>>>> } >>>>>>>>>> catch (InfernalLogException e) { >>>>>>>>>> throw new RuntimeException(e); >>>>>>>>>> } >>>>>>>>>> } >>>>>>>>>> >>>>>>>>>> After: >>>>>>>>>> >>>>>>>>>> void suspendAccount() >>>>>>>>>> throws AuthorizationException >>>>>>>>>> catch InfernalDBException throw PersistenceException, >>>>>>>>>> InfernalLogException throw RuntimeException { >>>>>>>>>> >>>>>>>>>> checkMyAuthoritah(); >>>>>>>>>> db.update(/*...*/); >>>>>>>>>> log.recordInfo(/*...*/); >>>>>>>>>> } >>>>>>>>>> >>>>>>>>>> >>>>>>>>>> DETAILS >>>>>>>>>> >>>>>>>>>> SPECIFICATION: Describe how the proposal affects the grammar, >>>>>>>>>> type system, and meaning of expressions and statements in >>>>>>>>>> the >>>>>>>>>> Java Programming Language as well as any other known >>>>>>>>>> impacts. >>>>>>>>>> >>>>>>>>>> The syntactic grammar is modified to allow an optional >>>>>>>>>> rethrows >>>>>>>>>> clause immediately prior to a MethodBody: >>>>>>>>>> >>>>>>>>>> MethodDeclaratorRest: >>>>>>>>>> FormalParameters {[]} [throws >>>>>>>>>> QualifiedIdentifierList] ( ( [catch ExceptionTranslationList] >>>>>>>>>> MethodBody ) | ; ) >>>>>>>>>> >>>>>>>>>> ExceptionTranslationList: >>>>>>>>>> QualifiedIdentifier throw QualifiedIdentifier >>>>>>>>>> { , ExceptionTranslationList } >>>>>>>>>> >>>>>>>>>> >>>>>>>>>> >>>>>>>>>> JLSv3 ?8.4.6 : A rethrows clause lists one or more exception >>>>>>>>>> translations, each translation consisting of a caught type >>>>>>>>>> C and >>>>>>>>>> a translated type T for which all of the following must >>>>>>>>>> hold: >>>>>>>>>> * C <: java.lang.Exception >>>>>>>>>> * T < java.lang.Throwable >>>>>>>>>> * Neither C nor T is a type variable. >>>>>>>>>> * T has an accessible constructor suitable for rethrowing a >>>>>>>>>> value of type C (see below). >>>>>>>>>> * T is not the same type as C. >>>>>>>>>> >>>>>>>>>> Any exceptions thrown by the method body which are a >>>>>>>>>> subtype of a >>>>>>>>>> caught exception type in the rethrows clause, are rethrown >>>>>>>>>> as the >>>>>>>>>> corresponding translated exception type. >>>>>>>>>> >>>>>>>>>> For a given translated type T with corresponding caught >>>>>>>>>> type C, if >>>>>>>>>> T has an accessible constructor accepting a value of type >>>>>>>>>> C, then >>>>>>>>>> the translation is equivalent to the following: >>>>>>>>>> >>>>>>>>>> catch (C e) { >>>>>>>>>> throw new T(e); >>>>>>>>>> } >>>>>>>>>> >>>>>>>>>> Otherwise it must have an accessible no argument >>>>>>>>>> constructor, and >>>>>>>>>> the translation is equivalent to: >>>>>>>>>> >>>>>>>>>> catch (C e) { >>>>>>>>>> throw new T().initCause(e); >>>>>>>>>> } >>>>>>>>>> >>>>>>>>>> >>>>>>>>>> A rethrows clause does not restrict which types may appear >>>>>>>>>> in a >>>>>>>>>> throws clause for the same method. In particular, for a >>>>>>>>>> given >>>>>>>>>> caught type C in the rethrows clause, it is permitted for >>>>>>>>>> some >>>>>>>>>> type C1 :> C to also be listed in the throws clause. >>>>>>>>>> >>>>>>>>>> >>>>>>>>>> JLSv3 ?8.2 : The set of exception types declared to be >>>>>>>>>> thrown by >>>>>>>>>> a method is the union of: >>>>>>>>>> * the types in the throws clause >>>>>>>>>> * the translated types in the rethrow clause >>>>>>>>>> * the types thrown by the translated types' selected >>>>>>>>>> constructors >>>>>>>>>> >>>>>>>>>> JLSv3 ?11.2.2 : For the purposes of exception analysis, the >>>>>>>>>> set >>>>>>>>>> of checked exception types which may be thrown by the >>>>>>>>>> method's >>>>>>>>>> body is the union of: >>>>>>>>>> * the types in the throws clause >>>>>>>>>> * the caught types in the rethrows clause >>>>>>>>>> >>>>>>>>>> JLSv3 ?11.2.3 : It is a compile-time error if a rethrows >>>>>>>>>> clause >>>>>>>>>> contains a translation from a checked exception type C but >>>>>>>>>> there >>>>>>>>>> exists no checked exception type E such that all of the >>>>>>>>>> following >>>>>>>>>> hold: >>>>>>>>>> * E <: C >>>>>>>>>> * The method body can throw E >>>>>>>>>> * No preceding translation in the rethrow clause catches E or >>>>>>>>>> a supertype of E >>>>>>>>>> unless C is the class java.lang.Exception. >>>>>>>>>> >>>>>>>>>> JLSv3 ?13.4.21 : Changes to the rethrows clause of methods >>>>>>>>>> or >>>>>>>>>> constructors do not break compatibility with existing >>>>>>>>>> binaries; >>>>>>>>>> these clauses are checked only at compile time. >>>>>>>>>> >>>>>>>>>> >>>>>>>>>> >>>>>>>>>> COMPILATION: How would the feature be compiled to class >>>>>>>>>> files? >>>>>>>>>> Show how the simple and advanced examples would be compiled. >>>>>>>>>> Compilation can be expressed as at least one of a >>>>>>>>>> desugaring to >>>>>>>>>> existing source constructs and a translation down to >>>>>>>>>> bytecode. If >>>>>>>>>> a new bytecode is used or the semantics of an existing >>>>>>>>>> bytecode >>>>>>>>>> are changed, describe those changes, including how they >>>>>>>>>> impact >>>>>>>>>> verification. Also discuss any new class file attributes >>>>>>>>>> that are >>>>>>>>>> introduced. Note that there are many downstream tools that >>>>>>>>>> consume class files and that they may to be updated to >>>>>>>>>> support >>>>>>>>>> the proposal! >>>>>>>>>> >>>>>>>>>> A simple desugaring could consist of enclosing the method >>>>>>>>>> body's >>>>>>>>>> statements in a try statement, with catch clauses for each >>>>>>>>>> translated exception type. For example, the following >>>>>>>>>> method: >>>>>>>>>> >>>>>>>>>> Method findMethod() >>>>>>>>>> catch ClassNotFoundException throw ConfigException, >>>>>>>>>> NoSuchMethodException throw ConfigException { >>>>>>>>>> >>>>>>>>>> Class c = Class.forName("some.Thing"); >>>>>>>>>> return c.getDeclaredMethod("execute", null); >>>>>>>>>> } >>>>>>>>>> >>>>>>>>>> would be desugared to: >>>>>>>>>> >>>>>>>>>> Method findMethod() >>>>>>>>>> throws ConfigException { >>>>>>>>>> try { >>>>>>>>>> Class c = Class.forName("some.Thing"); >>>>>>>>>> return c.getDeclaredMethod("execute", null); >>>>>>>>>> } >>>>>>>>>> catch (ClassNotFoundException e) { >>>>>>>>>> throw new ConfigException(e); >>>>>>>>>> } >>>>>>>>>> catch (MethodNotFoundException e) { >>>>>>>>>> throw new ConfigException(e); >>>>>>>>>> } >>>>>>>>>> } >>>>>>>>>> >>>>>>>>>> No changes to the classfile format are required. >>>>>>>>>> >>>>>>>>>> >>>>>>>>>> TESTING: How can the feature be tested? >>>>>>>>>> >>>>>>>>>> An initial set of jtreg tests is included in the prototype. >>>>>>>>>> >>>>>>>>>> >>>>>>>>>> LIBRARY SUPPORT: Are any supporting libraries needed for the >>>>>>>>>> feature? >>>>>>>>>> >>>>>>>>>> No >>>>>>>>>> >>>>>>>>>> >>>>>>>>>> REFLECTIVE APIS: Do any of the various and sundry >>>>>>>>>> reflection APIs >>>>>>>>>> need to be updated? This list of reflective APIs includes >>>>>>>>>> but is >>>>>>>>>> not limited to core reflection (java.lang.Class and >>>>>>>>>> java.lang.reflect.*), javax.lang.model.*, the doclet API, >>>>>>>>>> and >>>>>>>>>> JPDA. >>>>>>>>>> >>>>>>>>>> com.sun.source.tree.MethodTree would require updates to >>>>>>>>>> access >>>>>>>>>> the rethrows clause's caught and translated types. >>>>>>>>>> >>>>>>>>>> >>>>>>>>>> OTHER CHANGES: Do any other parts of the platform need be >>>>>>>>>> updated >>>>>>>>>> too? Possibilities include but are not limited to JNI, >>>>>>>>>> serialization, and output of the javadoc tool. >>>>>>>>>> >>>>>>>>>> No >>>>>>>>>> >>>>>>>>>> >>>>>>>>>> MIGRATION: Sketch how a code base could be converted, >>>>>>>>>> manually or >>>>>>>>>> automatically, to use the new feature. >>>>>>>>>> >>>>>>>>>> Catch clauses which simply wrap and rethrow an exception as >>>>>>>>>> another exception type not caught in an enclosing scope, >>>>>>>>>> can be >>>>>>>>>> trivially replaced with a rethrows clause, either manually >>>>>>>>>> or >>>>>>>>>> automatically. >>>>>>>>>> >>>>>>>>>> It should be possible for tools to offer bidirectional >>>>>>>>>> conversions such that an exception translation may be >>>>>>>>>> moved back >>>>>>>>>> into the method body if it is subsequently decided that >>>>>>>>>> additional logic is required. >>>>>>>>>> >>>>>>>>>> >>>>>>>>>> COMPATIBILITY >>>>>>>>>> >>>>>>>>>> BREAKING CHANGES: Are any previously valid programs now >>>>>>>>>> invalid? >>>>>>>>>> If so, list one. >>>>>>>>>> >>>>>>>>>> No >>>>>>>>>> >>>>>>>>>> >>>>>>>>>> EXISTING PROGRAMS: How do source and class files of earlier >>>>>>>>>> platform versions interact with the feature? Can any new >>>>>>>>>> overloadings occur? Can any new overriding occur? >>>>>>>>>> >>>>>>>>>> The semantics of existing class files and legal source >>>>>>>>>> files are >>>>>>>>>> unchanged by this feature. >>>>>>>>>> >>>>>>>>>> >>>>>>>>>> REFERENCES >>>>>>>>>> >>>>>>>>>> EXISTING BUGS: Please include a list of any existing Sun >>>>>>>>>> bug ids >>>>>>>>>> related to this proposal. >>>>>>>>>> >>>>>>>>>> http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6534270 >>>>>>>>>> (similar, but emphasizes unchecked exceptions) >>>>>>>>>> >>>>>>>>>> >>>>>>>>>> URL FOR PROTOTYPE (optional): >>>>>>>>>> >>>>>>>>>> http://slm888.com/javac >>>>>>>>>> >>>>>>>>>> >>>>>>>>>> >>>>>>>>>> >>>>>>>>>> >>>>>>>> >>>>>>> >>>>>>> >>>>>> >>>>> >>>>> >> >> > From brucechapman at paradise.net.nz Thu May 21 01:37:49 2009 From: brucechapman at paradise.net.nz (Bruce Chapman) Date: Thu, 21 May 2009 20:37:49 +1200 Subject: Helping to find the usefulness of a proposal In-Reply-To: <49D5BBCE.2030102@optrak.co.uk> References: <4b4f45e00904020439q28caaeacrc6f53fa1cae50187@mail.gmail.com> <1238711752.49d53dc8e0a4c@www.paradise.net.nz> <49D56FAB.8090405@sun.com> <1238731172.49d589a4a3575@www.paradise.net.nz> <49D5BBCE.2030102@optrak.co.uk> Message-ID: <4A1512DD.8050705@paradise.net.nz> Hi all, I was handed a copy of the qualitas corpus on 2 DVDs at the JUG meeting last night. I'll see if I can find time to run Ruslan's work across it for a broader set of results, though it may not add much to the existing figures. Bruce Mark Thornton wrote: > brucechapman at paradise.net.nz wrote: >> OK, >> >> I was aware of that one because the last JUG meeting here was about >> visualising >> code and was working with that corpus. >> >> The problem then is that the corpus is HUGE. Even the 20090202r >> version which >> only has the latest release of each system (and is probably the >> appopriate one >> for coin use) is 1.2Gb (my monthly broadband limit is 1Gb - I'd probably >> sneakernet it from someone locally). > Ouch, however I'm sure there are quite a few of us with substantially > more generous download allowances. > > Mark Thornton > From rssh at gradsoft.com.ua Wed May 20 23:06:11 2009 From: rssh at gradsoft.com.ua (Ruslan Shevchenko) Date: Thu, 21 May 2009 09:06:11 +0300 (EEST) Subject: Checked Exceptions do not exist on the JVM. In-Reply-To: <03A0D853-0216-4983-B17C-799D8A9A8103@zwitserloot.com> References: <39084932-B2CC-4B91-97EA-006FE21301F0@googlemail.com> <4A1339ED.8090309@sun.com> <68BF955A-9796-44F7-9E97-94BBB43ADCC5@zwitserloot.com> <988330f1d03fc629490d5dffa3fc2d25.squirrel@wmail.gradsoft.ua> <03A0D853-0216-4983-B17C-799D8A9A8103@zwitserloot.com> Message-ID: <54e2814fa4f0f25828037a38ac5dd463.squirrel@wmail.gradsoft.ua> > Ruslan: > > Why do you keep mentioning LinkageError? I'll try to explain the 'not- > care' keyword one more time: > > int f() not-care MyException { > throw MyException(); > } > > does the *exact* same thing as: > > int f() throws MyException { > throw MyException(); > } > > The only difference is for javac: In the second case, with the throws > statement, the caller must either wrap their call to f() in a try/ > catch block nd catch MyException, -or-, the caller must add a 'throws > MyException' to their method. However, in the not-care case, a caller > does NOT have to do these things. That's all. > I understand what you mean. But after 'that's all' JVM must do something with exception, which was not handled ... hmm, in theory it can be translated to LinkageError in process barrier. Oops, it was not for plain JVM ;) Plain JVM just do printStackTrace() on exception. (I wrote small text to see this). package x; public class X { public X() throws Exception { throw new Exception("hi!"); } public static void main(String[] args) { try { X x = X.class.newInstance(); } catch (InstantiationException ex) { System.err.println("instantiation exception"); ex.printStackTrace(); } catch (IllegalAccessException ex) { System.err.println("illegal access exception"); ex.printStackTrace(); } } } But I guess this is implementation-specifics property of JVM. I. e. nothing prevent JVM-implementors to handle unhandled checked exceptions and throw LinkageErrors on some barriers (function or process). And I can imagine optimizations, where such change is necessory. > > Also, we can't add 'throws Throwable' to Class.newInstance - it would > break backwards compatibility. It's also not the only problem - you > can't close the 'construct a class file' hole, and you certainly can't > close the 'there are other languages that run on the JVM' hole. Java > does not break backwards compatibility. I'll let Joe give the final > word, but the odds that java will add 'throws Throwable' to > Class.newInstance, or adds 'throws Exception' to java.lang.Runnable, > are somewhere between pigs flying and hell freezing over. It just > won't happen. > Some evolutions exists (i. e. all methods of Date deprecated, ThreadLocal interdace changed a lot). May be changes to Runnable or Threads to radical; but with Class.newInstantce() ... Ok, let's wait for process of library changes. (As I understand, it will be after coin) From rssh at gradsoft.com.ua Wed May 20 23:15:37 2009 From: rssh at gradsoft.com.ua (Ruslan Shevchenko) Date: Thu, 21 May 2009 09:15:37 +0300 (EEST) Subject: rethrow proposal and not-care construct In-Reply-To: <54e2814fa4f0f25828037a38ac5dd463.squirrel@wmail.gradsoft.ua> References: <39084932-B2CC-4B91-97EA-006FE21301F0@googlemail.com> <4A1339ED.8090309@sun.com> <68BF955A-9796-44F7-9E97-94BBB43ADCC5@zwitserloot.com> <988330f1d03fc629490d5dffa3fc2d25.squirrel@wmail.gradsoft.ua> <03A0D853-0216-4983-B17C-799D8A9A8103@zwitserloot.com> <54e2814fa4f0f25828037a38ac5dd463.squirrel@wmail.gradsoft.ua> Message-ID: <3bb6c60426030808bcc8792386a01bde.squirrel@wmail.gradsoft.ua> Actually same as non-care without new keyword, can be emulated (logically, not technikally) by rethrow extension as: catch Exception throw MyRuntimeWrapperException It would be good to have some standard convention about exceptions, which we belive impossible. It can be UndeclaredThrowableException, or, may be create new standard exception. From reinier at zwitserloot.com Thu May 21 02:15:11 2009 From: reinier at zwitserloot.com (Reinier Zwitserloot) Date: Thu, 21 May 2009 11:15:11 +0200 Subject: Checked Exceptions do not exist on the JVM. In-Reply-To: <54e2814fa4f0f25828037a38ac5dd463.squirrel@wmail.gradsoft.ua> References: <39084932-B2CC-4B91-97EA-006FE21301F0@googlemail.com> <4A1339ED.8090309@sun.com> <68BF955A-9796-44F7-9E97-94BBB43ADCC5@zwitserloot.com> <988330f1d03fc629490d5dffa3fc2d25.squirrel@wmail.gradsoft.ua> <03A0D853-0216-4983-B17C-799D8A9A8103@zwitserloot.com> <54e2814fa4f0f25828037a38ac5dd463.squirrel@wmail.gradsoft.ua> Message-ID: <7BE63AF8-0E70-48F7-A6DD-D848F9A91C57@zwitserloot.com> No, Ruslan, the JVM doesn't do anything special to the exception. It remains a MyException - it isn't changed, wrapped, swallowed, converted, or anything else. Again: At the JVM level, you can throw a checked MyException even if your method does not specifcally say "throws MyException". The JVM ignores 'throws' clauses on method signatures. So, either the exception is handled somewhere up the stack by a catch block, or if it isn't, then it eventually arrives at the thread unhandled exception code, which you can configure on a per-thread basis. By default, a thread will dump a stack trace to the console. --Reinier Zwitserloot On May 21, 2009, at 08:06, Ruslan Shevchenko wrote: >> Ruslan: >> >> Why do you keep mentioning LinkageError? I'll try to explain the >> 'not- >> care' keyword one more time: >> >> int f() not-care MyException { >> throw MyException(); >> } >> >> does the *exact* same thing as: >> >> int f() throws MyException { >> throw MyException(); >> } >> >> The only difference is for javac: In the second case, with the throws >> statement, the caller must either wrap their call to f() in a try/ >> catch block nd catch MyException, -or-, the caller must add a 'throws >> MyException' to their method. However, in the not-care case, a caller >> does NOT have to do these things. That's all. >> > > I understand what you mean. But after 'that's all' JVM must do > something > with exception, which was not handled ... hmm, in theory it can be > translated to LinkageError in process barrier. > > Oops, it was not for plain JVM ;) Plain JVM just do printStackTrace() > on exception. (I wrote small text to see this). > > package x; > > public class X > { > > public X() throws Exception > { > throw new Exception("hi!"); > } > > public static void main(String[] args) { > try { > X x = X.class.newInstance(); > } catch (InstantiationException ex) { > System.err.println("instantiation exception"); > ex.printStackTrace(); > } catch (IllegalAccessException ex) { > System.err.println("illegal access exception"); > ex.printStackTrace(); > } > } > > } > > But I guess this is implementation-specifics property of JVM. I. e. > nothing prevent JVM-implementors to handle unhandled checked > exceptions > and throw LinkageErrors on some barriers (function or process). > And I can imagine optimizations, where such change is necessory. >> >> Also, we can't add 'throws Throwable' to Class.newInstance - it would >> break backwards compatibility. It's also not the only problem - you >> can't close the 'construct a class file' hole, and you certainly >> can't >> close the 'there are other languages that run on the JVM' hole. Java >> does not break backwards compatibility. I'll let Joe give the final >> word, but the odds that java will add 'throws Throwable' to >> Class.newInstance, or adds 'throws Exception' to java.lang.Runnable, >> are somewhere between pigs flying and hell freezing over. It just >> won't happen. >> > > Some evolutions exists (i. e. all methods of Date deprecated, > ThreadLocal > interdace changed a lot). May be changes to Runnable or Threads to > radical; but with Class.newInstantce() ... > > Ok, let's wait for process of library changes. (As I understand, it > will > be after coin) > > > > From rssh at gradsoft.com.ua Wed May 20 23:29:44 2009 From: rssh at gradsoft.com.ua (Ruslan Shevchenko) Date: Thu, 21 May 2009 09:29:44 +0300 (EEST) Subject: Checked Exceptions do not exist on the JVM. In-Reply-To: <7BE63AF8-0E70-48F7-A6DD-D848F9A91C57@zwitserloot.com> References: <39084932-B2CC-4B91-97EA-006FE21301F0@googlemail.com> <4A1339ED.8090309@sun.com> <68BF955A-9796-44F7-9E97-94BBB43ADCC5@zwitserloot.com> <988330f1d03fc629490d5dffa3fc2d25.squirrel@wmail.gradsoft.ua> <03A0D853-0216-4983-B17C-799D8A9A8103@zwitserloot.com> <54e2814fa4f0f25828037a38ac5dd463.squirrel@wmail.gradsoft.ua> <7BE63AF8-0E70-48F7-A6DD-D848F9A91C57@zwitserloot.com> Message-ID: > No, Ruslan, the JVM doesn't do anything special to the exception. It > remains a MyException - it isn't changed, wrapped, swallowed, > converted, or anything else. > > Again: At the JVM level, you can throw a checked MyException even if > your method does not specifcally say "throws MyException". The JVM > ignores 'throws' clauses on method signatures. > It means, they can't do set of optimizations to exception handling, based on facts that some functions are exception-free. > So, either the exception is handled somewhere up the stack by a catch > block, or if it isn't, then it eventually arrives at the thread > unhandled exception code, which you can configure on a per-thread > basis. By default, a thread will dump a stack trace to the console. > > --Reinier Zwitserloot > > > > On May 21, 2009, at 08:06, Ruslan Shevchenko wrote: > >>> Ruslan: >>> >>> Why do you keep mentioning LinkageError? I'll try to explain the >>> 'not- >>> care' keyword one more time: >>> >>> int f() not-care MyException { >>> throw MyException(); >>> } >>> >>> does the *exact* same thing as: >>> >>> int f() throws MyException { >>> throw MyException(); >>> } >>> >>> The only difference is for javac: In the second case, with the throws >>> statement, the caller must either wrap their call to f() in a try/ >>> catch block nd catch MyException, -or-, the caller must add a 'throws >>> MyException' to their method. However, in the not-care case, a caller >>> does NOT have to do these things. That's all. >>> >> >> I understand what you mean. But after 'that's all' JVM must do >> something >> with exception, which was not handled ... hmm, in theory it can be >> translated to LinkageError in process barrier. >> >> Oops, it was not for plain JVM ;) Plain JVM just do printStackTrace() >> on exception. (I wrote small text to see this). >> >> package x; >> >> public class X >> { >> >> public X() throws Exception >> { >> throw new Exception("hi!"); >> } >> >> public static void main(String[] args) { >> try { >> X x = X.class.newInstance(); >> } catch (InstantiationException ex) { >> System.err.println("instantiation exception"); >> ex.printStackTrace(); >> } catch (IllegalAccessException ex) { >> System.err.println("illegal access exception"); >> ex.printStackTrace(); >> } >> } >> >> } >> >> But I guess this is implementation-specifics property of JVM. I. e. >> nothing prevent JVM-implementors to handle unhandled checked >> exceptions >> and throw LinkageErrors on some barriers (function or process). >> And I can imagine optimizations, where such change is necessory. >>> >>> Also, we can't add 'throws Throwable' to Class.newInstance - it would >>> break backwards compatibility. It's also not the only problem - you >>> can't close the 'construct a class file' hole, and you certainly >>> can't >>> close the 'there are other languages that run on the JVM' hole. Java >>> does not break backwards compatibility. I'll let Joe give the final >>> word, but the odds that java will add 'throws Throwable' to >>> Class.newInstance, or adds 'throws Exception' to java.lang.Runnable, >>> are somewhere between pigs flying and hell freezing over. It just >>> won't happen. >>> >> >> Some evolutions exists (i. e. all methods of Date deprecated, >> ThreadLocal >> interdace changed a lot). May be changes to Runnable or Threads to >> radical; but with Class.newInstantce() ... >> >> Ok, let's wait for process of library changes. (As I understand, it >> will >> be after coin) >> >> >> >> > > From howard.lovatt at iee.org Thu May 21 05:18:07 2009 From: howard.lovatt at iee.org (Howard Lovatt) Date: Thu, 21 May 2009 22:18:07 +1000 Subject: Notes on implementing concise calls to constructors with type parameters In-Reply-To: References: <3dd3f56a0905132041r67710789if86d4e942987a039@mail.gmail.com> <15e8b9d20905132115r58bfe6a7naa6952e5f94c1392@mail.gmail.com> <3dd3f56a0905140543v63603bd4qed2a149fc06cb0ce@mail.gmail.com> <15e8b9d20905140932g33fbcd7atd6c6e28f95211cb4@mail.gmail.com> <3dd3f56a0905150026ta489f58lece1b35ee17df44d@mail.gmail.com> <15e8b9d20905150633n5f3cbb92q79a37a4e736b93b9@mail.gmail.com> <3dd3f56a0905180113l1b7dab5fge695caba96fdcf72@mail.gmail.com> Message-ID: <3dd3f56a0905210518l45a27361jb5861afd44b82224@mail.gmail.com> Hi Peter, 2009/5/21 Peter Levart : > Hello Howard, > > What Neal and others are trying to point out is that your "textual > substitution algorithm" is not defined. The name "textual" implies that it > should be simple. But the right thing to do is not simple at all. I suspect that we have more of a philosophical difference rather than a technical one. I think it is a mistake to choose complicated systems that few understand; you have to keep it simple. Much of Java is a simplification of C++ and this simplification is the reason for the success of Java. An example of a feature of Java that has received much negative comment is variance, to me this is an example of a system that though powerful is too complicated. The reason for people wanting to have type declarations on the left rather than the var (auto) type construct is for this very reason of simplicity, so it makes no sense to me to use a complicated system when the aim is simplicity. In summary the number one goal for me is simplicity, rather than ultimate power. It doesn't matter how hard you try with type inference it would seem that some part of it will fail. The following example from Peter Ahe blog demonstrates this: static void merge( List l1, List l2 ) {} static void test(List list) { merge(list, list); } Fails with an obscure error message: merge(java.util.List,java.util.List) in listtypesafety.Main cannot be applied to (java.util.List,java.util.List) Yet to a human reader it is obvious that it is type sound. Now unfortunately you have a failure for no apparent reason and a system that is so complicated you cannot work out why and therefore can't work out how to fix the problem. (I do know why it fails, but you have to admit it is not obvious.) > Have you > looked at the 3rd JLS section 15.12.2.7 ? Yes > To just scratch the surface, take > the following example: > > public interface IntA { ... } > > public class ClsA implements IntA { ... } > > public class ClsB implements IntA { ... } > > ... > public void doIt(IntA param) { ... } > ... > // what should "textual substitution" do in the following 2 cases: > anInstance.doIt(new ClsA()); > // vs. > anInstance.doIt(new ClsB()); For an example like this I would use raw types, to remain compatible with existing code. This is the same answer I gave for multiply constrained types. Also note the following slight variation currently fails: static class ClsA implements IntA { static ClsA instance() { return new ClsA(); } } static class ClsB implements IntA { static ClsB instance() { return new ClsB(); } } static void inferenceTest() { doIt( ClsA.instance() ); doIt( ClsB.instance() ); } Which shows what a difficult example this is. Back on my philosophical point, I don't mind the inference resulting in a raw type (no inference) for an example like this. The chance of something like this occurring in real code is slim and if you are really worried about the types then you can specify them. For me it is much more important that examples like: // Translation // Original Ex e___ = new Ex(); // Ex e___ = new(); Ex e__s = new Ex(); // Ex e__s = new(); Ex e_e_ = new Ex(); // Ex e_e_ = new Ex(); Ex e_es = new Ex(); // Ex e_es = new Ex(); Ex es__ = new Ex(); // Ex es__ = new(); Ex es_s = new Ex(); // Ex es_s = new(); Ex ese_ = new Ex(); // Ex ese_ = new Ex(); Ex eses = new Ex(); // Ex eses = new Ex(); Work well and are easily understood. Cheers, -- Howard. > > Peter. > > > On Mon, May 18, 2009 at 10:13 AM, Howard Lovatt > wrote: >> >> Hi Neal, >> >> Yes I should have spelled this out, it is one of those things obvious >> to the author but not to the reader. I would propose that given more >> than one method of the same name, method in example below, with the >> general declaration for each following the syntax: >> >> ... method ( typeLHS [] name , ... ) { ... } >> >> and given the call: >> >> ... method ( new [typeRHS] [] ( ... ) , ... ); >> >> Then a three step procedure would be used: >> >> 1. If typeRHS is absent assume for step 2 type Void, where Void is the >> bottom type (in Java 7 this may be called Null but I chose Void to be >> consistent with the InvokeDynamic proposal) >> >> 2. Resolve method as normal and hence find typeLHS and if specified >> genericParametersLHS also >> >> 3. Apply textual substitution algorithm, i.e. If typeRHS is absent >> substitute typeLHS and if genericParametersRHS is absent and >> genericParametersLHS is present then substitute genericParametersLHS >> >> For example, given two methods: >> >> void method( Object notUsed ) { out.println( "Object" ); ?} >> void method( String notUsed ) { out.println( "String" ); ?} >> >> The call: >> >> method( new() ); >> >> would print String because it would be translated by the textual >> substitution algorithm into method( new String() ), i.e. the same >> behaviour as method( null ) because null has type Void (bottom). >> >> Does that add sufficient clarity? I would be really interested if you >> can see a problem with the technique? >> >> If not the method maybe a good solution as it has many desirable >> characteristics (as listed in previous posts in this thread). I also >> note that many people would like a var or auto style declaration and >> maybe this proposal of text substitution can satisfy more people than >> other proposals, since it retains LHS types but saves re-specification >> of type, generic type, and doesn't require a diamond operator on the >> RHS. >> >> ?-- Howard. >> >> > > > ______________________________________________________________________ > This email has been scanned by the MessageLabs Email Security System. > For more information please visit http://www.messagelabs.com/email > ______________________________________________________________________ > -- -- Howard. From reinier at zwitserloot.com Thu May 21 05:27:53 2009 From: reinier at zwitserloot.com (Reinier Zwitserloot) Date: Thu, 21 May 2009 14:27:53 +0200 Subject: Checked Exceptions do not exist on the JVM. In-Reply-To: References: <39084932-B2CC-4B91-97EA-006FE21301F0@googlemail.com> <4A1339ED.8090309@sun.com> <68BF955A-9796-44F7-9E97-94BBB43ADCC5@zwitserloot.com> <988330f1d03fc629490d5dffa3fc2d25.squirrel@wmail.gradsoft.ua> <03A0D853-0216-4983-B17C-799D8A9A8103@zwitserloot.com> <54e2814fa4f0f25828037a38ac5dd463.squirrel@wmail.gradsoft.ua> <7BE63AF8-0E70-48F7-A6DD-D848F9A91C57@zwitserloot.com> Message-ID: The JVM cannot make optimizations in regards to exceptions now, either. How often do I need to repeat this: You can make class files that throw checked exceptions out of a method that does not declare it in the throws clause --Reinier Zwitserloot On May 21, 2009, at 08:29, Ruslan Shevchenko wrote: >> No, Ruslan, the JVM doesn't do anything special to the exception. It >> remains a MyException - it isn't changed, wrapped, swallowed, >> converted, or anything else. >> >> Again: At the JVM level, you can throw a checked MyException even if >> your method does not specifcally say "throws MyException". The JVM >> ignores 'throws' clauses on method signatures. >> > > It means, they can't do set of optimizations to exception handling, > based > on facts that some functions are exception-free. > > >> So, either the exception is handled somewhere up the stack by a catch >> block, or if it isn't, then it eventually arrives at the thread >> unhandled exception code, which you can configure on a per-thread >> basis. By default, a thread will dump a stack trace to the console. >> >> --Reinier Zwitserloot >> >> >> >> On May 21, 2009, at 08:06, Ruslan Shevchenko wrote: >> >>>> Ruslan: >>>> >>>> Why do you keep mentioning LinkageError? I'll try to explain the >>>> 'not- >>>> care' keyword one more time: >>>> >>>> int f() not-care MyException { >>>> throw MyException(); >>>> } >>>> >>>> does the *exact* same thing as: >>>> >>>> int f() throws MyException { >>>> throw MyException(); >>>> } >>>> >>>> The only difference is for javac: In the second case, with the >>>> throws >>>> statement, the caller must either wrap their call to f() in a try/ >>>> catch block nd catch MyException, -or-, the caller must add a >>>> 'throws >>>> MyException' to their method. However, in the not-care case, a >>>> caller >>>> does NOT have to do these things. That's all. >>>> >>> >>> I understand what you mean. But after 'that's all' JVM must do >>> something >>> with exception, which was not handled ... hmm, in theory it can be >>> translated to LinkageError in process barrier. >>> >>> Oops, it was not for plain JVM ;) Plain JVM just do >>> printStackTrace() >>> on exception. (I wrote small text to see this). >>> >>> package x; >>> >>> public class X >>> { >>> >>> public X() throws Exception >>> { >>> throw new Exception("hi!"); >>> } >>> >>> public static void main(String[] args) { >>> try { >>> X x = X.class.newInstance(); >>> } catch (InstantiationException ex) { >>> System.err.println("instantiation exception"); >>> ex.printStackTrace(); >>> } catch (IllegalAccessException ex) { >>> System.err.println("illegal access exception"); >>> ex.printStackTrace(); >>> } >>> } >>> >>> } >>> >>> But I guess this is implementation-specifics property of JVM. I. >>> e. >>> nothing prevent JVM-implementors to handle unhandled checked >>> exceptions >>> and throw LinkageErrors on some barriers (function or process). >>> And I can imagine optimizations, where such change is necessory. >>>> >>>> Also, we can't add 'throws Throwable' to Class.newInstance - it >>>> would >>>> break backwards compatibility. It's also not the only problem - you >>>> can't close the 'construct a class file' hole, and you certainly >>>> can't >>>> close the 'there are other languages that run on the JVM' hole. >>>> Java >>>> does not break backwards compatibility. I'll let Joe give the final >>>> word, but the odds that java will add 'throws Throwable' to >>>> Class.newInstance, or adds 'throws Exception' to >>>> java.lang.Runnable, >>>> are somewhere between pigs flying and hell freezing over. It just >>>> won't happen. >>>> >>> >>> Some evolutions exists (i. e. all methods of Date deprecated, >>> ThreadLocal >>> interdace changed a lot). May be changes to Runnable or Threads to >>> radical; but with Class.newInstantce() ... >>> >>> Ok, let's wait for process of library changes. (As I understand, it >>> will >>> be after coin) >>> >>> >>> >>> >> >> > > From rssh at gradsoft.com.ua Thu May 21 04:48:41 2009 From: rssh at gradsoft.com.ua (Ruslan Shevchenko) Date: Thu, 21 May 2009 14:48:41 +0300 (EEST) Subject: Helping to find the usefulness of a proposal In-Reply-To: <4A1512DD.8050705@paradise.net.nz> References: <4b4f45e00904020439q28caaeacrc6f53fa1cae50187@mail.gmail.com> <1238711752.49d53dc8e0a4c@www.paradise.net.nz> <49D56FAB.8090405@sun.com> <1238731172.49d589a4a3575@www.paradise.net.nz> <49D5BBCE.2030102@optrak.co.uk> <4A1512DD.8050705@paradise.net.nz> Message-ID: <8e849d37ff5f4fc8986e8fa950dfd6a7.squirrel@wmail.gradsoft.ua> > Hi all, > > I was handed a copy of the qualitas corpus on 2 DVDs at the JUG meeting > last night. I'll see if I can find time to run Ruslan's work across it > for a broader set of results, though it may not add much to the existing > figures. > Great! I will prepare next version on check-set on week-end. Also, timing issues: On our compile server, with CPU0: Intel(R) Xeon(R) 2.13GHz and 4Gb RAM openjdk-jdk fully processed during 65 minutes. So, may be have sense take some part of corpus. > Bruce > > > Mark Thornton wrote: >> brucechapman at paradise.net.nz wrote: >>> OK, >>> >>> I was aware of that one because the last JUG meeting here was about >>> visualising >>> code and was working with that corpus. >>> >>> The problem then is that the corpus is HUGE. Even the 20090202r >>> version which >>> only has the latest release of each system (and is probably the >>> appopriate one >>> for coin use) is 1.2Gb (my monthly broadband limit is 1Gb - I'd >>> probably >>> sneakernet it from someone locally). >> Ouch, however I'm sure there are quite a few of us with substantially >> more generous download allowances. >> >> Mark Thornton >> > > > From peter.levart at gmail.com Thu May 21 08:22:10 2009 From: peter.levart at gmail.com (Peter Levart) Date: Thu, 21 May 2009 17:22:10 +0200 Subject: Notes on implementing concise calls to constructors with type parameters In-Reply-To: <3dd3f56a0905210518l45a27361jb5861afd44b82224@mail.gmail.com> References: <3dd3f56a0905132041r67710789if86d4e942987a039@mail.gmail.com> <15e8b9d20905132115r58bfe6a7naa6952e5f94c1392@mail.gmail.com> <3dd3f56a0905140543v63603bd4qed2a149fc06cb0ce@mail.gmail.com> <15e8b9d20905140932g33fbcd7atd6c6e28f95211cb4@mail.gmail.com> <3dd3f56a0905150026ta489f58lece1b35ee17df44d@mail.gmail.com> <15e8b9d20905150633n5f3cbb92q79a37a4e736b93b9@mail.gmail.com> <3dd3f56a0905180113l1b7dab5fge695caba96fdcf72@mail.gmail.com> <3dd3f56a0905210518l45a27361jb5861afd44b82224@mail.gmail.com> Message-ID: Answers following in-line... On Thu, May 21, 2009 at 2:18 PM, Howard Lovatt wrote: > Hi Peter, > > 2009/5/21 Peter Levart : > > Hello Howard, > > > > What Neal and others are trying to point out is that your "textual > > substitution algorithm" is not defined. The name "textual" implies that > it > > should be simple. But the right thing to do is not simple at all. > > I suspect that we have more of a philosophical difference rather than > a technical one. I think it is a mistake to choose complicated systems > that few understand; you have to keep it simple. Much of Java is a > simplification of C++ and this simplification is the reason for the > success of Java. An example of a feature of Java that has received > much negative comment is variance, to me this is an example of a > system that though powerful is too complicated. The reason for people > wanting to have type declarations on the left rather than the var > (auto) type construct is for this very reason of simplicity, so it > makes no sense to me to use a complicated system when the aim is > simplicity. In summary the number one goal for me is simplicity, > rather than ultimate power. ... and you forgot "consistency". That means features should be orthogonal. If it works that way in one context it should work the same way in all contexts. Consistency increases simplicity. What you propose is something that would work differently for constructors than for example inference works in generic methods. This would not achieve your ultimate goal. > > It doesn't matter how hard you try with type inference it would seem > that some part of it will fail. The following example from Peter Ahe > blog demonstrates this: > > static void merge( List l1, List l2 ) {} > > static void test(List list) { merge(list, list); } > > Fails with an obscure error message: > > merge(java.util.List,java.util.List) in listtypesafety.Main > cannot be applied to (java.util.List java.lang.Object>,java.util.List java.lang.Object>) > > Yet to a human reader it is obvious that it is type sound. Now > unfortunately you have a failure for no apparent reason and a system > that is so complicated you cannot work out why and therefore can't > work out how to fix the problem. (I do know why it fails, but you have > to admit it is not obvious.) Not obvious is only to someone that assumes the problem domain is not complicated. In order to understand the failure of the above compilation, you have to consider the whole problem domain. The compiler has to consider the whole problem domain because it must NEVER produce wrong result. Would it allow the above call, then it would also allow for example this: public class Test { void merge(List l1, List l2) { // ... } static final List STRINGS = Arrays.asList("xx", "yy"); static final List INTEGERS = Arrays.asList(1, 2, 3); volatile List list = STRINGS; void test() { new Thread() { public void run() { list = INTEGERS; } }.start(); merge(list, list); // it can happen that we merge STRINGS with INTEGERS !!! } } In order for the compiler to allow Peter Ahe's example and not allow the exploit above, it would have to even further "complicate" the algorithm and include special cases for local or final variables. This might be an idea for a project COIN proposal if it bothered many people. But no such proposal was seen on this list, so we could assume it doesn't bother to many people. What we have now is "simplified" handling that does not consider valid special cases but throws them together with invalid cases. Type inference algorithm is in this respect to simple, not to complicated. I agree that diagnostic message could be better though. > > > Have you > > looked at the 3rd JLS section 15.12.2.7 ? > > Yes > > > To just scratch the surface, take > > the following example: > > > > public interface IntA { ... } > > > > public class ClsA implements IntA { ... } > > > > public class ClsB implements IntA { ... } > > > > ... > > public void doIt(IntA param) { ... } > > ... > > // what should "textual substitution" do in the following 2 cases: > > anInstance.doIt(new ClsA()); > > // vs. > > anInstance.doIt(new ClsB()); > > For an example like this I would use raw types, to remain compatible > with existing code. This is the same answer I gave for multiply > constrained types. > > Also note the following slight variation currently fails: > > static class ClsA implements IntA { > static ClsA instance() { return new ClsA(); } > } > > static class ClsB implements IntA { > static ClsB instance() { return new ClsB(); } > } > > static void inferenceTest() { > doIt( ClsA.instance() ); > doIt( ClsB.instance() ); > } > > Which shows what a difficult example this is. > Yes, but the following works: IntA a = ClsA.instance(); IntA b = ClsB.instance(); ... it's just a matter of further "complicating" the inference algorithm in combination with overloaded methods. I read on this list that today the theory can do it. > Back on my philosophical point, I don't mind the inference resulting > in a raw type (no inference) for an example like this. The chance of > something like this occurring in real code is slim and if you are > really worried about the types then you can specify them. For me it is > much more important that examples like: > > // Translation // Original > Ex e___ = new Ex(); // Ex > e___ = new(); > Ex e__s = new Ex(); // Ex e__s > = new(); > Ex e_e_ = new Ex(); // Ex > e_e_ = new Ex(); > Ex e_es = new Ex(); // Ex e_es > = new Ex(); > Ex es__ = new Ex(); // Ex es__ = new(); > Ex es_s = new Ex(); // Ex es_s = new(); > Ex ese_ = new Ex(); // Ex ese_ = new Ex(); > Ex eses = new Ex(); // Ex eses = new > Ex(); > > Work well and are easily understood. > It might work well for straightforward cases but will be unusable for many others. And It might bring a lot of surprises. For example: public class InferenceTest { interface IntA { } static class ClsA implements IntA // note the reversal of X & Y { } static void inferenceTest() { IntA a = new ClsA(); // inferred as new ClsA(); IntA b = new ClsA(); // inferred as new ClsA< Integer, Integer>(); IntA c = new ClsA(); // produces raw type new ClsA(); ??? } } I think the "textual substitution and fall back to raw type if it doesn't compile" is not a serious algorithm for any compiler or language. It is simply not consistent. I think we can do better. Java should only get the best. Regards, Peter > Cheers, > > -- Howard. > > > > > Peter. > > > > > > On Mon, May 18, 2009 at 10:13 AM, Howard Lovatt > > wrote: > >> > >> Hi Neal, > >> > >> Yes I should have spelled this out, it is one of those things obvious > >> to the author but not to the reader. I would propose that given more > >> than one method of the same name, method in example below, with the > >> general declaration for each following the syntax: > >> > >> ... method ( typeLHS [] name , ... ) { ... } > >> > >> and given the call: > >> > >> ... method ( new [typeRHS] [] ( ... ) , ... ); > >> > >> Then a three step procedure would be used: > >> > >> 1. If typeRHS is absent assume for step 2 type Void, where Void is the > >> bottom type (in Java 7 this may be called Null but I chose Void to be > >> consistent with the InvokeDynamic proposal) > >> > >> 2. Resolve method as normal and hence find typeLHS and if specified > >> genericParametersLHS also > >> > >> 3. Apply textual substitution algorithm, i.e. If typeRHS is absent > >> substitute typeLHS and if genericParametersRHS is absent and > >> genericParametersLHS is present then substitute genericParametersLHS > >> > >> For example, given two methods: > >> > >> void method( Object notUsed ) { out.println( "Object" ); } > >> void method( String notUsed ) { out.println( "String" ); } > >> > >> The call: > >> > >> method( new() ); > >> > >> would print String because it would be translated by the textual > >> substitution algorithm into method( new String() ), i.e. the same > >> behaviour as method( null ) because null has type Void (bottom). > >> > >> Does that add sufficient clarity? I would be really interested if you > >> can see a problem with the technique? > >> > >> If not the method maybe a good solution as it has many desirable > >> characteristics (as listed in previous posts in this thread). I also > >> note that many people would like a var or auto style declaration and > >> maybe this proposal of text substitution can satisfy more people than > >> other proposals, since it retains LHS types but saves re-specification > >> of type, generic type, and doesn't require a diamond operator on the > >> RHS. > >> > >> -- Howard. > >> > >> > > > > > > ______________________________________________________________________ > > This email has been scanned by the MessageLabs Email Security System. > > For more information please visit http://www.messagelabs.com/email > > ______________________________________________________________________ > > > > > > -- > -- Howard. > From Joe.Darcy at Sun.COM Thu May 21 08:49:57 2009 From: Joe.Darcy at Sun.COM (Joseph D. Darcy) Date: Thu, 21 May 2009 08:49:57 -0700 Subject: Notes on implementing concise calls to constructors with type parameters In-Reply-To: <3dd3f56a0905210518l45a27361jb5861afd44b82224@mail.gmail.com> References: <3dd3f56a0905132041r67710789if86d4e942987a039@mail.gmail.com> <15e8b9d20905132115r58bfe6a7naa6952e5f94c1392@mail.gmail.com> <3dd3f56a0905140543v63603bd4qed2a149fc06cb0ce@mail.gmail.com> <15e8b9d20905140932g33fbcd7atd6c6e28f95211cb4@mail.gmail.com> <3dd3f56a0905150026ta489f58lece1b35ee17df44d@mail.gmail.com> <15e8b9d20905150633n5f3cbb92q79a37a4e736b93b9@mail.gmail.com> <3dd3f56a0905180113l1b7dab5fge695caba96fdcf72@mail.gmail.com> <3dd3f56a0905210518l45a27361jb5861afd44b82224@mail.gmail.com> Message-ID: <4A157825.7060201@sun.com> Howard Lovatt wrote: > Hi Peter, > > 2009/5/21 Peter Levart : > >> Hello Howard, >> >> What Neal and others are trying to point out is that your "textual >> substitution algorithm" is not defined. The name "textual" implies that it >> should be simple. But the right thing to do is not simple at all. >> > > I suspect that we have more of a philosophical difference rather than > a technical one. I think it is a mistake to choose complicated systems > that few understand; you have to keep it simple. Much of Java is a > simplification of C++ and this simplification is the reason for the > success of Java. An example of a feature of Java that has received > much negative comment is variance, to me this is an example of a > system that though powerful is too complicated. The reason for people > wanting to have type declarations on the left rather than the var > (auto) type construct is for this very reason of simplicity, so it > makes no sense to me to use a complicated system when the aim is > simplicity. In summary the number one goal for me is simplicity, > rather than ultimate power. > > It doesn't matter how hard you try with type inference it would seem > that some part of it will fail. The following example from Peter Ahe > blog demonstrates this: > > static void merge( List l1, List l2 ) {} > > static void test(List list) { merge(list, list); } > > Fails with an obscure error message: > > merge(java.util.List,java.util.List) in listtypesafety.Main > cannot be applied to (java.util.List java.lang.Object>,java.util.List java.lang.Object>) > > Yet to a human reader it is obvious that it is type sound. Now > Yes, and as Peter Levart has detailed, the human reader is wrong. The compiler messages are a known shortcoming which are being addressed in JDK 7; the messages from current builds are much better and another round of message improvements just hit the langtools Mercurial repository. We will not be adding a textual substitution algorithm type inferencing algorithm in JDK 7; further discussion on this matter is not necessary. -Joe From tim.lebedkov at googlemail.com Thu May 21 09:45:50 2009 From: tim.lebedkov at googlemail.com (Tim Lebedkov) Date: Thu, 21 May 2009 18:45:50 +0200 Subject: Proposal: Type inference for variable definition/initialization using the 'auto' keyword. In-Reply-To: <4A13D2C7.1010201@sun.com> References: <4A0D0066.1060701@sun.com> <4A13D2C7.1010201@sun.com> Message-ID: Hello Maurizio, (see my comments below) On Wed, May 20, 2009 at 11:52 AM, Maurizio Cimadamore wrote: > Hi Tim > let me start by saying that I've been working on a similar area on the > JavaFX compiler. As you probably know, JavaFX supports some kind of limited > variable declaration type-inference, so that, e.g. a variable declared as: > > var x = "Hello!" > > is automatically inferred to be of type String. > > Here's a bunch of problems that we found when implementing this feature in > JavaFX - note I'm not saying that for these reason the proposal is not > feasible, but I think that it should be more precise about the kind of > things that the compiler should be able to infer. Let me clarify this by > examples: > > *) inference from multiple assignments: > > often JavaFX users complain about the impossibility of writing code like: > > var x = "Hello"; > x = 1; //type-error here, Integer cannot be assigned to String In my opinion the JavaFX implementation is better: it is easier to implement and more type safe. I'll add this example to the proposal. > > which means, after the type of the variable has been inferred (usually in > the var initializer or in the first assignment to the variable) it is not > possible to 'refine' the inferred type so that it also matches other > assignments. In this case a 'complete' approach would have kept track of all > the RHS {String, Integer} and inferred x to the type glb{String, Integer}, > which happens to be Object & Comparable> >. > > *) cycles in initialization preventing inference > > In JavaFX forward references are allowed (with warning) which means that > sometimes the compiler has no clue about which type should be picked given a > sequence of statements like the following: > > var x = y; > var y = x; > > In Java we (luckily) have no such thing as forward reference - the compiler > reports errors in such circumstances. However it's still possible to have > some kind of cyclic dependency (through qualified static names): > > class A { > static int a = B.b; > } > > class B { > static int b = A.a; > } > > The above code is legal and it compiles without errors. If we use the 'auto' > keyword we could write something like: > > class A { > static auto a = B.b; > } > > class B { > static auto b = A.a; > } > > Which types is the compiler supposed to infer for both a and b? It is clear that the compiler should generate an error in this case. I'll add the example to the proposal. Regards --Tim > > I think that a proposal should deal explicitly with such 'corner' cases - > they might seem a bit 'artificial' here, but they (or similar variants) are > fairly common once users start to heavily rely on variable-type inference. > Simply trusting the compiler to 'figure out' what the right type would be in > each case is not an option :-) ?. > > Maurizio > > Joseph D. Darcy wrote: >> >> Tim Lebedkov wrote: >> >>> >>> Type inference for variable definition/initialization using the 'auto' >>> keyword. >>> >>> AUTHOR(S): Tim Lebedkov >>> >>> OVERVIEW >>> >>> Provide a two sentence or shorter description of these five aspects of >>> the feature: >>> >>> FEATURE SUMMARY: Should be suitable as a summary in a language tutorial. >>> >>> This proposal addresses the addition of type inference for >>> variable definitions to the Java programming language using the 'auto' >>> keyword instead of specific type name. >>> >>> For example, consider the following assignment statement: >>> >>> Map> anagrams = new HashMap>(); >>> >>> This is rather lengthy, so it can be replaced with this: >>> >>> auto anagrams = new HashMap>(); >>> >>> and anagrams is automatically typed as HashMap> >>> >>> MAJOR ADVANTAGE: What makes the proposal a favorable change? >>> >>> Generics have had a tremendously positive impact on type safety in the >>> Java programming language. They ?have made it possible to provide >>> static guarantees about the type of instances used by other classes, >>> preventing entire classes of runtime errors from occurring. However, >>> generics have added complexity to Java, making the code far more >>> verbose and occasionally difficult to read. Although solving this >>> problem is well outside the scope of this proposal, a limited form of >>> type inference would remove unnecessary redundancy from the language. >>> Even without generics it seems unnecessary to duplicate type names for >>> simple variable definitions/assignments like: >>> >>> Integer a = new Integer(1023); >>> >>> MAJOR BENEFIT: Why is the platform better if the proposal is adopted? >>> >>> Less code and no duplication has a positive impact on many things: >>> - faster typing/faster code changes >>> - easier code changing without IDE assistance >>> - code versioning diffs are more clear >>> >>> MAJOR DISADVANTAGE: There is always a cost. >>> >>> - it could be harder to read the code. >>> - auto will be a keyword and may break some old code >>> >>> ALTERNATIVES: Can the benefits and advantages be had some way without >>> a language change? >>> >>> no >>> >>> >> >> Catching up on proposal comments, I think the core benefits of using >> "auto" or "final" on the left hand side for variables are achieved with the >> diamond operator that allows one to elide type parameters on the right hand >> side. ?IMO, the diamond solution of specifying the variable type fully on >> the left and then specifying only the implementation type without redundant, >> repeated type parameters on the right is more in keeping with Java coding >> style. >> >> -Joe >> >> > > From per at bothner.com Thu May 21 10:00:27 2009 From: per at bothner.com (Per Bothner) Date: Thu, 21 May 2009 10:00:27 -0700 Subject: Proposal: Type inference for variable definition/initialization using the 'auto' keyword. In-Reply-To: References: <4A0D0066.1060701@sun.com> <4A13D2C7.1010201@sun.com> Message-ID: <4A1588AB.5060802@bothner.com> On 05/21/2009 09:45 AM, Tim Lebedkov wrote: > On Wed, May 20, 2009 at 11:52 AM, Maurizio Cimadamore > wrote: >> often JavaFX users complain about the impossibility of writing code like: >> >> var x = "Hello"; >> x = 1; //type-error here, Integer cannot be assigned to String > > In my opinion the JavaFX implementation is better: it is easier to implement and > more type safe. I'll add this example to the proposal. The problem is that gets into awkwardness of the "most specific type" issues. For example: var x = 0; // Inferred to be integer x = x + 0.1; // Oops What we'd like to do is infer the type to be the "union type" (or most specific shared super-type) of all the assignments to a variable. This of course requires all the assignments to be visible, which is why we made the default visibility in JavaFX "script-local" (rather than package-local as in Java). An increment as above would normally cause a cycle (because the variable is used in the RHS of the assignment), but it is possible to special-case increments (and appending), and that would seem worthwhile. (Conditional expressions also use "union types".) Unfortunately, we haven't had time to implement a better type inference algorithm. -- --Per Bothner per at bothner.com http://per.bothner.com/ From howard.lovatt at iee.org Thu May 21 18:57:28 2009 From: howard.lovatt at iee.org (Howard Lovatt) Date: Fri, 22 May 2009 11:57:28 +1000 Subject: Notes on implementing concise calls to constructors with type parameters In-Reply-To: References: <3dd3f56a0905132041r67710789if86d4e942987a039@mail.gmail.com> <15e8b9d20905132115r58bfe6a7naa6952e5f94c1392@mail.gmail.com> <3dd3f56a0905140543v63603bd4qed2a149fc06cb0ce@mail.gmail.com> <15e8b9d20905140932g33fbcd7atd6c6e28f95211cb4@mail.gmail.com> <3dd3f56a0905150026ta489f58lece1b35ee17df44d@mail.gmail.com> <15e8b9d20905150633n5f3cbb92q79a37a4e736b93b9@mail.gmail.com> <3dd3f56a0905180113l1b7dab5fge695caba96fdcf72@mail.gmail.com> <3dd3f56a0905210518l45a27361jb5861afd44b82224@mail.gmail.com> Message-ID: <3dd3f56a0905211857w703deebes94056457ae63d43d@mail.gmail.com> Peter, Comments in-line. 2009/5/22 Peter Levart : [snip] > ... and you forgot "consistency". That means features should be orthogonal. > If it works that way in one context it should work the same way in all > contexts. Consistency increases simplicity. What you propose is something > that would work differently for constructors than for example inference > works in generic methods. This would not achieve your ultimate goal. But I want to do something that is different, I want to infer both the class and the generic parameters - not just the generics. [snip] > In order for the compiler to allow Peter Ahe's example and not allow the > exploit above, it would have to even further "complicate" the algorithm and > include special cases for local or final variables. This might be an idea > for a project COIN proposal if it bothered many people. But no such proposal > was seen on this list, so we could assume it doesn't bother to many people. Your example was nicely written, but as I said in my post "I do know why it fails". [snip] > Yes, but the following works: > > ??????? IntA a = ClsA.instance(); > ??????? IntA b = ClsB.instance(); > > ... it's just a matter of further "complicating" the inference algorithm in > combination with overloaded methods. I read on this list that today the > theory can do it. The main point I was making was that a simple to understand algorthim optimised for common use cases is the optimum choice. [snip] > ?It might work well for straightforward cases but will be unusable for many > others. And It might bring a lot of surprises. For example: > > public class InferenceTest > { > ??? interface IntA > ??? { > ??? } > > ??? static class ClsA implements IntA // note the reversal of X > & Y > ??? { > ??? } > > ??? static void inferenceTest() > ??? { > ??????? IntA a = new ClsA(); ?? // inferred as new > ClsA(); > ??????? IntA b = new ClsA();? // inferred as new > ClsA(); > ??????? IntA c = new ClsA();?? // produces raw type new > ClsA(); ??? > ??? } > } The line IntA c = new ClsA() would br translated into IntA c = new ClsA(), which would fail with an error message clearly indicating the type mismatch - therefore I would say that textual substitution works extremely well on your example (it is in fact ideal). Ulf has given similar examples on the forum and shown how generating errors for these cases is highly desirable since they are most commonly caused by typos. > I think the "textual substitution and fall back to raw type if it doesn't > compile" is not a serious algorithm for any compiler or language. It is > simply not consistent. I think we can do better. Java should only get the > best. I agree with your sentiment that the best algorithm should be chosen - perhaps you can suggest one that works well, is optimised for, for the common cases, doesn't produce poor error messages, is simply understood, can be explained easily, is compatible with existing code, and can infer both type and generic parameters. As demonstrated, the current algorithms in javac can't do that. I don't mean the above challenge rhetorically or sarcastically, I am not wedded to "my" algorithm - if a better one exists lets use it. Cheers, -- Howard. > > Regards, Peter > >> >> Cheers, >> >> ?-- Howard. >> >> > >> > Peter. >> > >> > >> > On Mon, May 18, 2009 at 10:13 AM, Howard Lovatt >> > wrote: >> >> >> >> Hi Neal, >> >> >> >> Yes I should have spelled this out, it is one of those things obvious >> >> to the author but not to the reader. I would propose that given more >> >> than one method of the same name, method in example below, with the >> >> general declaration for each following the syntax: >> >> >> >> ... method ( typeLHS [] name , ... ) { ... } >> >> >> >> and given the call: >> >> >> >> ... method ( new [typeRHS] [] ( ... ) , ... ); >> >> >> >> Then a three step procedure would be used: >> >> >> >> 1. If typeRHS is absent assume for step 2 type Void, where Void is the >> >> bottom type (in Java 7 this may be called Null but I chose Void to be >> >> consistent with the InvokeDynamic proposal) >> >> >> >> 2. Resolve method as normal and hence find typeLHS and if specified >> >> genericParametersLHS also >> >> >> >> 3. Apply textual substitution algorithm, i.e. If typeRHS is absent >> >> substitute typeLHS and if genericParametersRHS is absent and >> >> genericParametersLHS is present then substitute genericParametersLHS >> >> >> >> For example, given two methods: >> >> >> >> void method( Object notUsed ) { out.println( "Object" ); ?} >> >> void method( String notUsed ) { out.println( "String" ); ?} >> >> >> >> The call: >> >> >> >> method( new() ); >> >> >> >> would print String because it would be translated by the textual >> >> substitution algorithm into method( new String() ), i.e. the same >> >> behaviour as method( null ) because null has type Void (bottom). >> >> >> >> Does that add sufficient clarity? I would be really interested if you >> >> can see a problem with the technique? >> >> >> >> If not the method maybe a good solution as it has many desirable >> >> characteristics (as listed in previous posts in this thread). I also >> >> note that many people would like a var or auto style declaration and >> >> maybe this proposal of text substitution can satisfy more people than >> >> other proposals, since it retains LHS types but saves re-specification >> >> of type, generic type, and doesn't require a diamond operator on the >> >> RHS. >> >> >> >> ?-- Howard. >> >> >> >> >> > >> > >> > ______________________________________________________________________ >> > This email has been scanned by the MessageLabs Email Security System. >> > For more information please visit http://www.messagelabs.com/email >> > ______________________________________________________________________ >> > >> >> >> >> -- >> ?-- Howard. > > > ______________________________________________________________________ > This email has been scanned by the MessageLabs Email Security System. > For more information please visit http://www.messagelabs.com/email > ______________________________________________________________________ > -- -- Howard. From howard.lovatt at iee.org Thu May 21 19:12:04 2009 From: howard.lovatt at iee.org (Howard Lovatt) Date: Fri, 22 May 2009 12:12:04 +1000 Subject: Notes on implementing concise calls to constructors with type parameters In-Reply-To: <4A157825.7060201@sun.com> References: <3dd3f56a0905132041r67710789if86d4e942987a039@mail.gmail.com> <15e8b9d20905132115r58bfe6a7naa6952e5f94c1392@mail.gmail.com> <3dd3f56a0905140543v63603bd4qed2a149fc06cb0ce@mail.gmail.com> <15e8b9d20905140932g33fbcd7atd6c6e28f95211cb4@mail.gmail.com> <3dd3f56a0905150026ta489f58lece1b35ee17df44d@mail.gmail.com> <15e8b9d20905150633n5f3cbb92q79a37a4e736b93b9@mail.gmail.com> <3dd3f56a0905180113l1b7dab5fge695caba96fdcf72@mail.gmail.com> <3dd3f56a0905210518l45a27361jb5861afd44b82224@mail.gmail.com> <4A157825.7060201@sun.com> Message-ID: <3dd3f56a0905211912qec40a9aw9064ccbb34421003@mail.gmail.com> Hi Joe, Answers in-line. 2009/5/22 Joseph D. Darcy : [snip] >> Yet to a human reader it is obvious that it is type sound. Now >> > > Yes, and as Peter Levart has detailed, the human reader is wrong. Just a pedantic point. The example I gave is type sound and therefore an ideal compiler wouldn't reject it. Peter didn't suggest the example wasn't type sound, he just explained why the compiler has difficulty with it. > The compiler ?messages are a known shortcoming which are being addressed in > JDK 7; the messages from current builds are much better and another round of > message improvements just hit the langtools Mercurial repository. Glad to hear it - it is not very sexy work but very important. > We will not be adding a textual substitution algorithm type inferencing > algorithm in JDK 7; further discussion on this matter is not necessary. I am not wedded to any particular algorithm or even to type declarations on the left, but I do hope that what every you decide on is goes further than the current diamond proposal. I an not a fan of this proposal because the diamond operator looks like it should be declaring a raw type and because it only infers the generic parameters and not the type as well. As you can see from the forum there is plenty of support for either: Ex e = new(); or auto e = new Ex(); Hopefully you will be able to accommodate one or the other. -- Howard. From Dmitry.Miltsov at Sun.COM Fri May 22 07:03:34 2009 From: Dmitry.Miltsov at Sun.COM (Dmitry Miltsov) Date: Fri, 22 May 2009 18:03:34 +0400 Subject: JCK feedback on Project Coin proposals Message-ID: <4A16B0B6.5080404@sun.com> Hello, The JCK engineers have reviewed the following proposals: "Simplified Varargs Method Invocation", "Automatic Resource Management", "Improved Type Inference for Generic Instance Creation", "Elvis and Other Null-Safe Operators". We haven't noticed any issues in the proposals. The proposal "Simplified Varargs Method Invocation" assumes the tests on compiler mandatory warnings. Note that currently JCK doesn't provide such tests due to the known javac issue. We have no other comments on testability of the proposals. Thanks, Dmitry Miltsov, JCK engineer From Ulf.Zibis at gmx.de Sun May 24 08:31:57 2009 From: Ulf.Zibis at gmx.de (Ulf Zibis) Date: Sun, 24 May 2009 17:31:57 +0200 Subject: Extend switch .. case statement for all types and simple expressions In-Reply-To: References: <49D14427.5070105@gmx.de> <49D33129.2090600@gmx.de> Message-ID: <4A19686D.4080207@gmx.de> Am 02.04.2009 11:34, Daniel Cheng schrieb: > On Wed, Apr 1, 2009 at 5:17 PM, Ulf Zibis wrote: > >> I would like to add, that the MAJOR ADVANTAGE of my proposal is, >> that the numerous grades/levels of this proposal could be implemented >> step by step, depending on the complexity of changes, which could be >> done for JDK 7. >> More sophisticated grades/levels could be seamlessly added later. >> This would be impossible, if the concurring syntax of "Strings in >> switch", which only compares for equality, comes to account. >> Also Multiple switch expressions and case ranges >> >> could seamlessly be integrated in my proposal. >> >> As I argued more detailed before, default semantic of "switch..case" >> should stay on determining the cases by IDENTITY. >> Strings, which are equal, could simply be made identical by String#intern(). >> > > Except, using some combination of gc options, intern'ed String won't be gc'ed. > > Literals are always intern'd, so the wouldn't gc'ed either. >> Example: >> switch (myStringFromElsewere.intern()) { >> case STRING1 : ...; // all constants are interned by definition >> case STRING2 : ...; // " " >> case "foo" : ...; // automatically interned >> case "bar" : ...; // " " >> ... >> } >> >> -Ulf >> > > > From Ulf.Zibis at gmx.de Sun May 24 08:37:38 2009 From: Ulf.Zibis at gmx.de (Ulf Zibis) Date: Sun, 24 May 2009 17:37:38 +0200 Subject: JCK feedback on "Strings in Switch" proposal In-Reply-To: <4A12A923.9060501@sun.com> References: <4A12A923.9060501@sun.com> Message-ID: <4A1969C2.402@gmx.de> Am 19.05.2009 14:42, Dmitry Miltsov schrieb: > Hello, > > The JCK engineers have reviewed the "Strings in switch" proposal > and found one issue to clarify. > > "14.11 The switch Statement" states: > ------------------------------------------------------------------ > ... > Otherwise, execution continues by comparing the value of the > Expression with each case constant. Then there is a choice: > * If one of the case constants is equal to the value of the > expression, then we say that the case matches ... > ------------------------------------------------------------------ > > It would be good to clarify what "equal" means in case of the > String values. It would be useful to mention that in this case > the result of comparison will be "expression.equals(constant)", > not "expression == constant" as for other types. > I think it would be better to define "expression == constant" for several reasons. (1) "switch..case" syntax historically is expected to be very fast. See discussions on: http://forums.java.net/jive/message.jspa?messageID=4146#4146 http://forums.java.net/jive/message.jspa?messageID=14216#14216 http://forums.java.net/jive/thread.jspa?threadID=504 (2) Comparison for identity would better match to legacy semantics of "switch..case" statement. (3) Don't obstruct later, more general extensions on "switch..case" statement. See: http://mail.openjdk.java.net/pipermail/coin-dev/2009-March/001182.html http://forums.java.net/jive/message.jspa?messageID=4146#4146 There are 40 votes on Bug ID: 5012262 Please note, that these votes are for "Strings AND Objects in switch", and not for just "Strings in switch". Strings, which are only equal, could simply be made identical by String#intern(). Example: switch (myStringFromElsewere.intern()) { case STRING1 : ...; // all constants are interned by definition case STRING2 : ...; // " " case "foo" : ...; // automatically interned case "bar" : ...; // " " ... } -Ulf From Ulf.Zibis at gmx.de Sun May 24 08:44:59 2009 From: Ulf.Zibis at gmx.de (Ulf Zibis) Date: Sun, 24 May 2009 17:44:59 +0200 Subject: Extend switch .. case statement for Object types and simple expressions In-Reply-To: <4A133644.40104@sun.com> References: <49D10FE6.3000404@gmx.de> <4A133644.40104@sun.com> Message-ID: <4A196B7B.8050806@gmx.de> Am 20.05.2009 00:44, Joe Darcy schrieb: > Hello. > > Catching up on comments. > > On 03/30/09 11:31 AM, Ulf Zibis wrote: >> AUTHOR(S): Ulf Zibis, Cologne, Germany >> >> OVERVIEW >> FEATURE SUMMARY: Extend switch .. case statement for Object types and >> simple expressions. >> MAJOR ADVANTAGE: >> - Increases readability of source in concurrence to if .. else if .. >> else syntax. >> - Sophisticated jumps. >> MAJOR BENEFIT: >> Stop some programmers escaping to some modern scripting language. >> MAJOR DISADVANTAGE: >> Programmers from other languages, especially C, may be confused about >> such rich syntax. >> > > I'm also a bit confused over what exactly is being proposed; it does > feel to me to be a rather aggressive change to switch. Yes, fulfilling all given examples would be a rather aggressive change to switch. But you could start from example (1), and stop, where the change seems to be too radical. Confusing examples ? Can you please be mor specific, which examples are confusing for you, and in which way. -Ulf > > -Joe > >> EXAMPLES >> SIMPLE EXAMPLE: >> (1): >> switch( myObject) { >> case CONSTANT1 : doSomething(); break; >> case CONSTANT2 : doSomethingElse(); break; >> default : doSomethingDefault(); >> } >> (2): >> switch( myString) { >> case equals("red") : stop(); break; >> case equals("green") : go(); break; >> default : openYourEyesForCrossingTraffic(); >> } >> (3): >> switch( myString) { >> case equalsIgnoreCase("RED") : sureStop(); break; >> case equalsIgnoreCase("GREEN") : sureGo(); break; >> default : beAwareOfPoliceWachtingYou(); >> } >> >> ADVANCED EXAMPLE: >> (1): >> switch( primitiveInt) { >> case == 10 : doOnlyIf10(); // alternative syntax for 'case 10:' >> case < 10 : >> case >= 20 : break; >> default : doOnlyInRange(); >> } >> (2): >> switch( primitiveInt) { >> case (>= 10 && < 20) : doOnlyInRange(); >> default : throw new Exception("Out of range"); >> } >> (3): >> switch( myString) { >> case contains("foo") : doSomething(); break; >> case regionMatches(true, 2, otherString, 4, 6) : >> doSomethingElse(); break; >> default : doSomethingDefault(); >> } >> (4): >> switch( myString.equals()) { // alternative: myString.equals(..) >> case "foo" : foo(); break; >> case "bar" : bar(); break; >> default : dontCare(); >> } >> (5): >> switch( className.startsWith("String", ..)) { // alternative: >> className.startsWith("String", ?) >> case 0 : doForSimpleName(); break; >> case 9 : doForFullName(); break; >> default : canNotDecide(); >> } >> (6): >> switch( anyObjectOrPrimitive instanceof) { // note, that casting >> is solved implicit >> case boolean, byte, ... float : break; // Don't do anything >> case double : forDouble(anyObjectOrPrimitive); >> case HashMap : >> case TreeMap : forPlattformMap(anyObjectOrPrimitive); break; >> case Map : forOtherMap(anyObjectOrPrimitive); break; >> default : forObject(anyObjectOrPrimitive); >> } >> (7): >> switch( some_lethargic_function_we_cant_call_much().equals(..) ) { >> case "this": >> case "that": this_or_that(); break; >> case "bigjump": big(); // fall >> case "jump": jump(); break; >> case "secondlastchance": >> case "lastchance": last_chance(); break; >> default: do_default(); >> } >> .. as replacement for: >> String sSomeString = some_lethargic_function_we_cant_call_much(); >> if( sSomeString.equals( "this" ) || sSomeString.equals( "that" ) ) >> this_or_that(); >> else if( sSomeString.equals( "jump" ) || sSomeString.equals( >> "bigjump" ) ) >> { >> if( sSomeString.equals( "bigjump" ) ) >> big(); >> jump(); >> } else if( sSomeString.equals( "secondlastchance" ) || >> sSomeString.equals( "lastchance" ) ) >> { >> last_chance(); >> } else do_default(); >> >> ALTERNATIVES: >> switch( myString) { // note the '.', I personally would prefer >> this alternative! >> case .equals("red") : stop(); break; >> case .equals("green") : go(); break; >> default : openYourEyesForCrossingTraffic(); >> } >> switch( primitiveInt) { // note the '.' >> case (. >= 10 && . < 20) : doOnlyInRange(); >> // case (? >= 10 && ? < 20) : doOnlyInRange(); // alternative >> default : throw new Exception("Out of range"); >> } >> >> >> DETAILS >> SPECIFICATION: >> The new syntax should be interpreted as >> switch ( leftExpressionPart ) { >> case rightExpressionPart1 : >> case rightExpressionPart2 : >> ... >> default : >> } >> The result of entire expression should be boolean type. >> There is shortcut for: >> leftExpressionPart: intVariable >> rightExpressionPart: == intLiteral >> (the '==' could be ommitted.) >> >> COMPILATION: >> Compiler could first pre-compile to appropriate if..then..else syntax. >> Bytecode would not be affected, but in special cases it could be more >> compact, if noted pre-compilation would be replaced by sophisticated >> optimization. >> TESTING: >> Compiler byte-code results for new syntax should be same than from >> equivalent hand-coded legacy if..then..else syntax >> . Exception: sophisticated optimization. >> LIBRARY SUPPORT: No supporting libraries are needed for the feature? >> REFLECTIVE APIS: There should not be any affection to reflection API. >> OTHER CHANGES: No. >> MIGRATION: >> No refactoring is needed to stay compatible. >> >> COMPATIBILITY >> BREAKING CHANGES: >> No previously valid programs are now invalid. >> ... but ATTENTION: >> If proposals from some other guys regarding "Strings in switch" would >> be taken into JDK 7, there won't be any compatible way to implement >> my more general proposal in future version of JDK !!! >> --> So switch .. case statement should compare for IDENTITY if not >> syntactically determined otherwise. >> --> compare for EQUALITY would also break semantic of existing switch >> .. case statement. >> EXISTING PROGRAMS: >> Source and class files of earlier platform versions interact with the >> feature without any notice. >> >> REFERENCES >> http://mail.openjdk.java.net/pipermail/coin-dev/2009-February/000001.html >> >> http://mail.openjdk.java.net/pipermail/coin-dev/2009-March/000213.html >> http://mail.openjdk.java.net/pipermail/coin-dev/2009-March/000855.html >> http://forums.java.net/jive/thread.jspa?messageID=27781沅 >> http://forums.java.net/jive/thread.jspa?messageID=15769㶙 >> http://forums.java.net/jive/thread.jspa?messageID=27773汽 >> http://forums.java.net/jive/thread.jspa?messageID=11393ⲁ >> EXISTING BUGS: >> http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=5012262 >> URL FOR PROTOTYPE (optional): >> >> >> >> > > From tim.lebedkov at googlemail.com Sun May 24 10:55:55 2009 From: tim.lebedkov at googlemail.com (Tim Lebedkov) Date: Sun, 24 May 2009 19:55:55 +0200 Subject: VERSION 2: Re: Proposal: Type inference for variable definition/initialization using the 'auto' keyword. Message-ID: Hello, here is an updated proposal that also deals with two cases pointed to by Maurizio Cimadamore and some cases found after more careful reading of the JLS The cases are: - union types - cyclic variable references - null type - multiple variable declarations - array declarations - declaration without initialization Regards --Tim Type inference for variable definition/initialization using the 'auto' keyword (Version 2). AUTHOR(S): Tim Lebedkov OVERVIEW Provide a two sentence or shorter description of these five aspects of the feature: FEATURE SUMMARY: Should be suitable as a summary in a language tutorial. This proposal addresses the addition of type inference for variable definitions to the Java programming language using the 'auto' keyword instead of specific type name. For example, consider the following assignment statement: Map> anagrams = new HashMap>(); This is rather lengthy, so it can be replaced with this: auto anagrams = new HashMap>(); and anagrams is automatically typed as HashMap> MAJOR ADVANTAGE: What makes the proposal a favorable change? Generics have had a tremendously positive impact on type safety in the Java programming language. They have made it possible to provide static guarantees about the type of instances used by other classes, preventing entire classes of runtime errors from occurring. However, generics have added complexity to Java, making the code far more verbose and occasionally difficult to read. Although solving this problem is well outside the scope of this proposal, a limited form of type inference would remove unnecessary redundancy from the language. Even without generics it seems unnecessary to duplicate type names for simple variable definitions/assignments like: Integer a = new Integer(1023); MAJOR BENEFIT: Why is the platform better if the proposal is adopted? Less code and no duplication has a positive impact on many things: - faster typing/faster code changes - easier code changing without IDE assistance - code versioning diffs are more clear MAJOR DISADVANTAGE: There is always a cost. - it could be harder to read the code. - auto will be a keyword and may break some old code ALTERNATIVES: Can the benefits and advantages be had some way without a language change? no EXAMPLES SIMPLE EXAMPLE: Show the simplest possible program utilizing the new feature. 1. simple assignment Map> a = new HashMap>(); becomes auto a = new HashMap>(); 2. auto in for List list = ... for (auto s: list) ... 3. auto for a final variable final ArrayList list = new ArrayList(); becomes final auto list = new ArrayList(); 4. class field definition class A { String a = ""; } becomes class A { auto a = ""; } ADVANCED EXAMPLE: Show advanced usage(s) of the feature. auto i = 5 + 3; // same as "int i = 5 + 3" auto i = 5 + 3L; // same as "long i = 5 + 3L" for (auto entry : (new HashMap>).entrySet()) { } DETAILS SPECIFICATION: Describe how the proposal affects the grammar, type system, and meaning of expressions and statements in the Java Programming Language as well as any other known impacts. Informally, the specification adds syntax to replace the type definition in variable definitions with assignments by 'auto'. The type of the variable is automatically determined. The use of the null literal for initialization is not permitted. The following code should result in an error: auto value = null; // compile-time error. The type of value cannot // be determined. A cast to a type could be used used to avoid a compile-time error: auto value = (String) null; // OK Cyclic references in initialization should also result in compiler errors: Example: class A { static auto a = B.b; // compile-time error. Cyclic reference. } class B { static auto b = A.a; // compile-time error. Cyclic reference. } The type of a variable defined using "auto" should be determined at the time of definition. Finding the right type as replacement for "auto" does not depend on subsequent statements. Example: auto a; // compile-time error. The type of "a" cannot be determined. a = 2; Example: auto a = 2; a = 2.0f; // compile-time error. The type of "a" is "int" All variables declared using the same "auto" statement are of the same type. The type is determined by the first variable in the list with an initialization expression. Example: auto a, b = 2; // OK. The type of "a" and "b" is "int". Example: auto a, b; // compile-time error. The type cannot be determined. Example: auto a = 2, b = "tree"; // compile-time error. Different types for "a" and "b". An array initialization expressions cannot be used with "auto": auto a = {2, 0, 0, 0}; // compile-time error. Java allows to place brackets for array type declaration either after the variable name or after the type name. Similar rules apply also to "auto": auto a[] = new int[] {}; // OK. "a" is of type "int[]" auto b[] = new int[2][3]; // OK. "b" is of type "int[][]" auto c[] = 5; // compile-time error. "int" is not an array type auto d[][] = new int[4]; // compile-time error. "int[]" cannot be casted to "int[][]" COMPILATION: How would the feature be compiled to class files? Show how the simple and advanced examples would be compiled. Compilation can be expressed as at least one of a desugaring to existing source constructs and a translation down to bytecode. If a new bytecode is used or the semantics of an existing bytecode are changed, describe those changes, including how they impact verification. Also discuss any new class file attributes that are introduced. Note that there are many downstream tools that consume class files and that they may to be updated to support the proposal! The resulting bytecode would be identical to bytecode generated by the same code with the types inferred. TESTING: How can the feature be tested? The proposed construct can be tested by writing a number of statements that construct instances using inferred types. These instances can then be assigned to variables and fields of specific types, and passed to methods that expect specific types. These tests should compile and run as expected: auto set = new SortedSet(); set.add("A"); set.add("B"); set.add("C"); // verify that set contains "A", "B", "C". LIBRARY SUPPORT: Are any supporting libraries needed for the feature? No library support is required, although libraries can be rewritten to take advantage of the new feature. REFLECTIVE APIS: Do any of the various and sundry reflection APIs need to be updated? This list of reflective APIs includes but is not limited to core reflection (java.lang.Class and java.lang.reflect.*), javax.lang.model.*, the doclet API, and JPDA. No reflective APIs need to be changed. OTHER CHANGES: Do any other parts of the platform need be updated too? Possibilities include but are not limited to JNI, serialization, and output of the javadoc tool. No other parts of the platform need to be updated. MIGRATION: Sketch how a code base could be converted, manually or automatically, to use the new feature. Libraries can be rewritten to take advantage of this feature, but it is not imperative that they do so. COMPATIBILITY This change is backwards incompatible on the source code level. BREAKING CHANGES: Are any previously valid programs now invalid? If so, list one. All programs that use auto as a name for an identifier would become invalid. EXISTING PROGRAMS: How do source and class files of earlier platform versions interact with the feature? Can any new overloadings occur? Can any new overriding occur? The feature is completely transparent to the class files. Class files do not contain any information about the variables declared using 'auto'. REFERENCES [1] Thanks to Jeremy Manson (his proposal served as a template for this one) http://mail.openjdk.java.net/pipermail/coin-dev/2009-February/000009.html [2] Jaako Jarvi and Bjarne Stroustrup. Decltype and auto (revision 3). Paper N1607, JTC1-SC22/WG21, February 17 2004. Online: http://www.open-std.org/jtc1/ sc22/wg21/docs/papers/2004/n1607.pdf; same as ANSI NCITS/J16 04-0047. [3] James Gosling, Bill Joy, Guy Steele, and Gilad Bracha. The Java Language Specification, 3rd Edition. Addison Wesley, 2004. EXISTING BUGS: Please include a list of any existing Sun bug ids related to this proposal. 6242254, 4983159, 6368076 URL FOR PROTOTYPE (optional): none On Thu, May 21, 2009 at 7:00 PM, Per Bothner wrote: > On 05/21/2009 09:45 AM, Tim Lebedkov wrote: >> >> On Wed, May 20, 2009 at 11:52 AM, Maurizio Cimadamore >> ?wrote: >>> >>> often JavaFX users complain about the impossibility of writing code like: >>> >>> var x = "Hello"; >>> x = 1; //type-error here, Integer cannot be assigned to String >> >> In my opinion the JavaFX implementation is better: it is easier to >> implement and >> more type safe. I'll add this example to the proposal. > > The problem is that gets into awkwardness of the "most specific type" > issues. ?For example: > > ?var x = 0; // Inferred to be integer > ?x = x + 0.1; // Oops > > What we'd like to do is infer the type to be the "union type" > (or most specific shared super-type) of all the assignments to > a variable. ?This of course requires all the assignments to be > visible, which is why we made the default visibility in JavaFX > "script-local" (rather than package-local as in Java). > > An increment as above would normally cause a cycle (because the > variable is used in the RHS of the assignment), but it is > possible to special-case increments (and appending), and that > would seem worthwhile. > > (Conditional expressions also use "union types".) > > Unfortunately, we haven't had time to implement a better > type inference algorithm. > -- > ? ? ? ?--Per Bothner > per at bothner.com ? http://per.bothner.com/ > From Joe.Darcy at Sun.COM Sun May 24 12:21:53 2009 From: Joe.Darcy at Sun.COM (Joseph D. Darcy) Date: Sun, 24 May 2009 12:21:53 -0700 Subject: JCK feedback on "Strings in Switch" proposal In-Reply-To: <4A1969C2.402@gmx.de> References: <4A12A923.9060501@sun.com> <4A1969C2.402@gmx.de> Message-ID: <4A199E51.2020706@sun.com> Ulf Zibis wrote: > Am 19.05.2009 14:42, Dmitry Miltsov schrieb: >> Hello, >> >> The JCK engineers have reviewed the "Strings in switch" proposal >> and found one issue to clarify. >> >> "14.11 The switch Statement" states: >> ------------------------------------------------------------------ >> ... >> Otherwise, execution continues by comparing the value of the >> Expression with each case constant. Then there is a choice: >> * If one of the case constants is equal to the value of the >> expression, then we say that the case matches ... >> ------------------------------------------------------------------ >> >> It would be good to clarify what "equal" means in case of the >> String values. It would be useful to mention that in this case >> the result of comparison will be "expression.equals(constant)", >> not "expression == constant" as for other types. >> > > I think it would be better to define "expression == constant" for > several reasons. > (1) "switch..case" syntax historically is expected to be very fast. > See discussions on: > http://forums.java.net/jive/message.jspa?messageID=4146#4146 > http://forums.java.net/jive/message.jspa?messageID=14216#14216 > http://forums.java.net/jive/thread.jspa?threadID=504 > (2) Comparison for identity would better match to legacy semantics of > "switch..case" statement. No, it would not. Comparing strings for "==" equality is a common programming error so the semantics of strings in switch should be defined in terms of .equals equality. -Joe From howard.lovatt at iee.org Sun May 24 16:00:59 2009 From: howard.lovatt at iee.org (Howard Lovatt) Date: Mon, 25 May 2009 09:00:59 +1000 Subject: VERSION 2: Re: Proposal: Type inference for variable definition/initialization using the 'auto' keyword. Message-ID: <3dd3f56a0905241600p49f455eesa51a451be6394c75@mail.gmail.com> The example: final auto list = new ArrayList(); seems strange, why not: final list = new ArrayList(); After all you are trying to reduce verbosity and making final declarations the same length as variable ones will encourage people to use final more, which is a good thing. The use of just final has been proposed by many people for Java already, it won't break code. Also this final only construct is consistent with other languages e.g. Scala, JavaFX, etc. that use def and var (final and auto respectively). -- Howard. From Ulf.Zibis at gmx.de Mon May 25 07:14:38 2009 From: Ulf.Zibis at gmx.de (Ulf Zibis) Date: Mon, 25 May 2009 16:14:38 +0200 Subject: JCK feedback on "Strings in Switch" proposal In-Reply-To: <4A199E51.2020706@sun.com> References: <4A12A923.9060501@sun.com> <4A1969C2.402@gmx.de> <4A199E51.2020706@sun.com> Message-ID: <4A1AA7CE.4080206@gmx.de> >> I think it would be better to define "expression == constant" for >> several reasons. >> (1) "switch..case" syntax historically is expected to be very fast. >> See discussions on: >> http://forums.java.net/jive/message.jspa?messageID=4146#4146 >> http://forums.java.net/jive/message.jspa?messageID=14216#14216 >> http://forums.java.net/jive/thread.jspa?threadID=504 >> (2) Comparison for identity would better match to legacy semantics of >> "switch..case" statement. > > No, it would not. Comparing strings for "==" equality is a common > programming error so the semantics of strings in switch should be > defined in terms of .equals equality. I think, I got your opinion. Variables are equal, if the values of their chunk of bits are identical (not generally, but in case of primitives and String objects). Variables are identical, if the memory location of their chunk of bits is the same. So primitive variables are never identical, as their chunk of bits are stored in different memory locations, and pedantically argued, "i == j" (for primitives) is always false, they should be compared by "i.equals(j)". Theoretically we could define "==" as comparison method for the switch..case construct, and accept the upper imprecision as legal for primitives. If the programmer wants comparison by equals(), he should explicitly write the syntax for it, e.g. in the way, I have proposed in my "switch for objects and expressions"-proposal. Having this, comparing by "==" can be seen as a programmatically shortcut for "equals()" in case of interned String objects (Literals are automatically interned by definition). There are 3 interesting, widely used types of comparison of Strings: - s1 == s1 - s2.equals(s2) - s2.equalsIgnoreCase(s2) The first 2 are covered by the given "Strings in Switch" proposal. IMHO we should not abandon the attempt to provide a smart syntax for the 3rd type of comparison in case of Strings, and even similar for general objects. if..else constructs seem not to be smart. -Ulf From reinier at zwitserloot.com Mon May 25 08:01:47 2009 From: reinier at zwitserloot.com (Reinier Zwitserloot) Date: Mon, 25 May 2009 17:01:47 +0200 Subject: JCK feedback on "Strings in Switch" proposal In-Reply-To: <4A1AA7CE.4080206@gmx.de> References: <4A12A923.9060501@sun.com> <4A1969C2.402@gmx.de> <4A199E51.2020706@sun.com> <4A1AA7CE.4080206@gmx.de> Message-ID: Creating a string switch proposal for equalsIgnoreCase reeks of creating the kitchen sink language: Stuff everything into a language construct. If that's a good idea, where do we stop? How about comparing strings not via case insensitivity, but intended syntactic meaning (where ? is equal to a to is equal to ?, and ? is equal to both 'u' and 'ue', etcetera - java doesn't have this method in a library, unfortunately which is why this kind of comparison isn't done often, but for obvious reasons, it should be used far more often than it is now). You're effectively elevating the concept of a case insensitive string comparison to a part of the JLS, whereas currently it isn't; it's just 1 library method and 1 static comparator object in the String class. Perl tried this 'everything into the language spec' concept. It's a - bad- idea. That sort of language level flexibility can only be gained in one way: DSL friendliness in the language. Where ordinary code that calls methods on objects can be written so that it looks just like a language construct, in other words. Python does quite a bit of this, by offering __get__ and __set__ so you can let any object react to foo[x] and foo[x] = bar, even __del__ to react to 'del foo', which is a python language construct to undefine a variable. The point is: Java isn't like that. I doubt it ever will be; that just makes for a different language altogether. We're going to have to deal with that, and not by stuffing every random idea into a language feature, or trying to ascertain that language features that are added must cover all the bases. Java isn't that flexible, and trying to appease all use cases leads to things like EJB 2.0: Unmitigated disasters. Having said that, I can imagine one way that is easy to remember, doesn't try to exert itself too much to try to conform to every use case, and is still flexible enough to give people a switch for case insensitivity: regexps. Put regular expressions in the case blocks (with some sort of unique identifier, and not just 'parse all string constants into regexps'. We don't want to repeat the API mistake of String.replaceAll, after all! RegExps, via regexp parameters, can configure case insensitivity. Requiring that the regexps are constants should also allow as sufficiently advanced javac to precompile the regexps, which isn't too important, but in a pinch helps performance when using very complex regexps. Not neccessarily in favour, and for consistency's sake, the special regexp notation should be valid anywhere else and be of type 'Pattern', so it's quite a change, but something to think about. Biggest argument against is that you usually want the matcher object, which would play havoc with the syntax, you'd have something like: switch ( Matcher m : someString ) { case /foo(.*)bar/: System.out.println(m.group(1)); break; case /barbaz+/: //etcetera } NB: On the topic of doing a direct == comparison: There is really no point to ever doing that. Many languages offload this feature (reference identity check) to a library call, generally because comparing two objects' reference identities is pretty much always the wrong thing to do unless you're trying to write a method that tries to draw a graph of the way objects are related to each other in memory, which is a job for a profiler and not for your code. In java, hypothetically, this would be along the lines of System.isEqualReference(a, b);. The fact that java's == is used for reference identity instead of an amalgamation of a null check and an .equals() call results in a proposal to fix this somehow every other week, and a lot of headache amongst java coders. Confusion around reference identity shows up every other day on freenode's ##java, for example. That should give some indication as to the wisdom of applying reference identity to the string switch idea. --Reinier Zwitserloot On May 25, 2009, at 16:14, Ulf Zibis wrote: > >>> I think it would be better to define "expression == constant" for >>> several reasons. >>> (1) "switch..case" syntax historically is expected to be very fast. >>> See discussions on: >>> http://forums.java.net/jive/message.jspa?messageID=4146#4146 >>> http://forums.java.net/jive/message.jspa?messageID=14216#14216 >>> http://forums.java.net/jive/thread.jspa?threadID=504 >>> (2) Comparison for identity would better match to legacy semantics >>> of >>> "switch..case" statement. >> >> No, it would not. Comparing strings for "==" equality is a common >> programming error so the semantics of strings in switch should be >> defined in terms of .equals equality. > > I think, I got your opinion. > Variables are equal, if the values of their chunk of bits are > identical > (not generally, but in case of primitives and String objects). > Variables are identical, if the memory location of their chunk of bits > is the same. So primitive variables are never identical, as their > chunk > of bits are stored in different memory locations, and pedantically > argued, "i == j" (for primitives) is always false, they should be > compared by "i.equals(j)". Theoretically we could define "==" as > comparison method for the switch..case construct, and accept the upper > imprecision as legal for primitives. If the programmer wants > comparison > by equals(), he should explicitly write the syntax for it, e.g. in the > way, I have proposed in my "switch for objects and expressions"- > proposal. > > Having this, comparing by "==" can be seen as a programmatically > shortcut for "equals()" in case of interned String objects (Literals > are > automatically interned by definition). > > There are 3 interesting, widely used types of comparison of Strings: > - s1 == s1 > - s2.equals(s2) > - s2.equalsIgnoreCase(s2) > > The first 2 are covered by the given "Strings in Switch" proposal. > IMHO we should not abandon the attempt to provide a smart syntax for > the > 3rd type of comparison in case of Strings, and even similar for > general > objects. > if..else constructs seem not to be smart. > > -Ulf > > > From tim.lebedkov at googlemail.com Mon May 25 13:31:16 2009 From: tim.lebedkov at googlemail.com (Tim Lebedkov) Date: Mon, 25 May 2009 22:31:16 +0200 Subject: VERSION 2: Re: Proposal: Type inference for variable definition/initialization using the 'auto' keyword. In-Reply-To: <3dd3f56a0905241600p49f455eesa51a451be6394c75@mail.gmail.com> References: <3dd3f56a0905241600p49f455eesa51a451be6394c75@mail.gmail.com> Message-ID: Hello Howard, (Jeremy - FYI) I have thought about it also. It would be useful to make "auto" optional. It was just not in the original proposal. And it would help (I'm not quite sure whether it is enough) with the "final" proposal from Jeremy Manson http://mail.openjdk.java.net/pipermail/coin-dev/2009-February/000009.html. Making "auto" optional would also allow code like static a = "clouds"; or private b = 44; I'm not quite sure yet whether I can change my proposal and about the implications and acceptance (and possible danger to the whole proposal) of this change. Regards --Tim On Mon, May 25, 2009 at 1:00 AM, Howard Lovatt wrote: > The example: > > final auto list = new ArrayList(); > > seems strange, why not: > > final list = new ArrayList(); > > After all you are trying to reduce verbosity and making final > declarations the same length as variable ones will encourage people to > use final more, which is a good thing. The use of just final has been > proposed by many people for Java already, it won't break code. ?Also > this final only construct is consistent with other languages e.g. > Scala, JavaFX, etc. that use def and var (final and auto > respectively). > > ?-- Howard. > From howard.lovatt at iee.org Mon May 25 15:48:52 2009 From: howard.lovatt at iee.org (Howard Lovatt) Date: Tue, 26 May 2009 08:48:52 +1000 Subject: VERSION 2: Re: Proposal: Type inference for variable definition/initialization using the 'auto' keyword. In-Reply-To: References: <3dd3f56a0905241600p49f455eesa51a451be6394c75@mail.gmail.com> Message-ID: <3dd3f56a0905251548x54d12882tb6f43f6763e3186c@mail.gmail.com> The suggestion of making auto optional seems like a good idea to me as it has a lot of use cases. -- Howard. 2009/5/26 Tim Lebedkov : > Hello Howard, > (Jeremy - FYI) > > I have thought about it also. It would be useful to make "auto" optional. > It was just not in the original proposal. And it would help (I'm not > quite sure whether it is enough) with the "final" proposal from Jeremy > Manson > http://mail.openjdk.java.net/pipermail/coin-dev/2009-February/000009.html. > > Making "auto" optional would also allow code like > > static a = "clouds"; > > or > > private b = 44; > > I'm not quite sure yet whether I can change my proposal and about the > implications and acceptance (and possible danger to the whole > proposal) of this change. > > Regards > --Tim > > > On Mon, May 25, 2009 at 1:00 AM, Howard Lovatt wrote: >> The example: >> >> final auto list = new ArrayList(); >> >> seems strange, why not: >> >> final list = new ArrayList(); >> >> After all you are trying to reduce verbosity and making final >> declarations the same length as variable ones will encourage people to >> use final more, which is a good thing. The use of just final has been >> proposed by many people for Java already, it won't break code. ?Also >> this final only construct is consistent with other languages e.g. >> Scala, JavaFX, etc. that use def and var (final and auto >> respectively). >> >> ?-- Howard. >> > > ______________________________________________________________________ > This email has been scanned by the MessageLabs Email Security System. > For more information please visit http://www.messagelabs.com/email > ______________________________________________________________________ > -- -- Howard. From reinier at zwitserloot.com Mon May 25 17:12:07 2009 From: reinier at zwitserloot.com (Reinier Zwitserloot) Date: Tue, 26 May 2009 02:12:07 +0200 Subject: VERSION 2: Re: Proposal: Type inference for variable definition/initialization using the 'auto' keyword. In-Reply-To: References: <3dd3f56a0905241600p49f455eesa51a451be6394c75@mail.gmail.com> Message-ID: <66FA6ACD-2620-4A74-87CC-C5B9919C003C@zwitserloot.com> Why not drop the 'auto' keyword entirely? Using just 'final' has plenty of advantages: 1. No need to add a new keyword, which, lets face it, project coin is - NEVER- going to allow, ever. 'module' is okay because it's context sensitive, but auto cannot be. The following code: auto x = 10; is technically parsable right now, in java 1.6: It's like 'String x = 10;' except instead of 'String' we have a type named 'auto', which is technically legal even though its against convention by having a type with a lowercase first letter. 2. No confusion around the following code: auto list = new ArrayList(); list = new LinkedList(); //fail: LinkedList is not an ArrayList! NB: It is infeasible to automagically detect that 'list' should be typed as just a List, and its quite a stretch for java to start considering ALL assignments and type the variable name with the intersection type(s). Compared to such antics, the rules for 'final' are much, much simpler: The type of the variable is the type of the RHS, unless the RHS is itself an intersection type, in which case for now we can just say such a construct isn't legal, and maybe later add support for intersection types for variables; such a change would be entirely backwards and migration compatible. 3. Less impactful; Assigning into a variable whose type is inferred from an expression is a much bigger deal than inferring the type of an unchanging reference. In the latter case, the link between the inferred type of a variable and its contents is obvious: It's the type of the content, period. In the former case, the type of a variable can be different from the content if you've reassigned, which leads to confusion. NB: Howard, making 'auto' optional is a very bad idea, IMO. It wouldn't be consistent: "a = 4;" can now mean either: assign the result of expression '4' to the existing variable named 'a', and make sure the type of the expression is compatible with the type of 'a', OR: Create a new variable named 'a', and infer the type off of the expression '4', then assign the result of that expression to it. I -really- doubt java is the type of language to roll with creating variables on the fly when assigning to them, python-style. I rate the odds of that going into coin as 'when pigs fly'. Thus, we are stuck with inferring 'auto' only if there are OTHER keywords involved, but other than 'final', that never happens for method locals. Thus, you must be talking about type inference for fields, which is far too big a change for coin; consider: 1. Fields can be accessed outside of scope, which means the type information on the variable is much more important. Typing a list as 'ArrayList' instead of a 'List' is a bad thing for a field, but only a very minor style incursion for a final method local, and yet outlawing 'auto foo = new ArrayList();' seems arbitrary and wrong. 2. Even for a private field, where access is restricted to reflection, the scope of the field is much larger than for method locals, which considerably adds to the damage done by not being explicit about the type. For method locals, the places where the variable is used is usually fairly easy to spot (and if not, you should be splitting up your methods!). For fields, this is obviously not the case. You lose perspective of your inferred type. --Reinier Zwitserloot On May 25, 2009, at 22:31, Tim Lebedkov wrote: > Hello Howard, > (Jeremy - FYI) > > I have thought about it also. It would be useful to make "auto" > optional. > It was just not in the original proposal. And it would help (I'm not > quite sure whether it is enough) with the "final" proposal from Jeremy > Manson > http://mail.openjdk.java.net/pipermail/coin-dev/2009-February/000009.html > . > > Making "auto" optional would also allow code like > > static a = "clouds"; > > or > > private b = 44; > > I'm not quite sure yet whether I can change my proposal and about the > implications and acceptance (and possible danger to the whole > proposal) of this change. > > Regards > --Tim > > > On Mon, May 25, 2009 at 1:00 AM, Howard Lovatt > wrote: >> The example: >> >> final auto list = new ArrayList(); >> >> seems strange, why not: >> >> final list = new ArrayList(); >> >> After all you are trying to reduce verbosity and making final >> declarations the same length as variable ones will encourage people >> to >> use final more, which is a good thing. The use of just final has been >> proposed by many people for Java already, it won't break code. Also >> this final only construct is consistent with other languages e.g. >> Scala, JavaFX, etc. that use def and var (final and auto >> respectively). >> >> -- Howard. >> > From howard.lovatt at iee.org Mon May 25 18:23:46 2009 From: howard.lovatt at iee.org (Howard Lovatt) Date: Tue, 26 May 2009 11:23:46 +1000 Subject: VERSION 2: Re: Proposal: Type inference for variable definition/initialization using the 'auto' keyword. In-Reply-To: <66FA6ACD-2620-4A74-87CC-C5B9919C003C@zwitserloot.com> References: <3dd3f56a0905241600p49f455eesa51a451be6394c75@mail.gmail.com> <66FA6ACD-2620-4A74-87CC-C5B9919C003C@zwitserloot.com> Message-ID: <3dd3f56a0905251823yaa2640arfa013510ef90cb35@mail.gmail.com> Hi Reinier, General comment: I don't think the diamond proposal goes far enough and would like something along the lines of either: auto c = new Cell( "Foo" ); or Cell c = new( "Foo" ); If only: final c = new Cell( "Foo" ); made it - then this would at least be a step in the right direction. Detailed comments inline. 2009/5/26 Reinier Zwitserloot : > Why not drop the 'auto' keyword entirely? Using just 'final' has plenty of > advantages: > > 1. No need to add a new keyword, which, lets face it, project coin is > -NEVER- going to allow, ever. That might be true, which is why I keep suggesting a source keyword to allow Java to move forward (see previous coin discussions) > 'module' is okay because it's context > sensitive, but auto cannot be. The following code: > > auto x = 10; > > is technically parsable right now, in java 1.6: It's like 'String x = 10;' Yes - auto should be a normal keyword [snip] > 3. Less impactful; Assigning into a variable whose type is inferred from an > expression is a much bigger deal than inferring the type of an unchanging > reference. In the latter case, the link between the inferred type of a > variable and its contents is obvious: It's the type of the content, period. > In the former case, the type of a variable can be different from the content > if you've reassigned, which leads to confusion. See comment at end > NB: Howard, making 'auto' optional is a very bad idea, IMO. It wouldn't be > consistent: > > "a = 4;" It is Tim's suggestion to make auto optional, rather than mine, but the way I read his suggestion was that there had to be a keyword already for auto to be optional. Therefore the above example would be an assignment to an already declared variable rather than a variable declaration and hence no problem - Tim am I correct in this interpretation of your suggestion? [snip] > 2. Even for a private field, where access is restricted to reflection, the > scope of the field is much larger than for method locals, which considerably > adds to the damage done by not being explicit about the type. For method > locals, the places where the variable is used is usually fairly easy to spot > (and if not, you should be splitting up your methods!). For fields, this is > obviously not the case. You lose perspective of your inferred type. This is the sort of detail an expert group could nut out. I don't think it is fundamental to the proposal. Personally I don't have this problem in typed languages with type inference, i.e. JavaFX, Scala, etc., and don't see this as a problem. This is a variation on Postel's Prescription (?Be liberal in what you accept, and conservative in what you send?), i.e. the return type, field type, and local type are all types of output therefore a specific class is fine - whereas a method argument should be an interface. -- Howard. > > > ?--Reinier Zwitserloot > > > > On May 25, 2009, at 22:31, Tim Lebedkov wrote: > >> Hello Howard, >> (Jeremy - FYI) >> >> I have thought about it also. It would be useful to make "auto" optional. >> It was just not in the original proposal. And it would help (I'm not >> quite sure whether it is enough) with the "final" proposal from Jeremy >> Manson >> http://mail.openjdk.java.net/pipermail/coin-dev/2009-February/000009.html. >> >> Making "auto" optional would also allow code like >> >> static a = "clouds"; >> >> or >> >> private b = 44; >> >> I'm not quite sure yet whether I can change my proposal and about the >> implications and acceptance (and possible danger to the whole >> proposal) of this change. >> >> Regards >> --Tim >> >> >> On Mon, May 25, 2009 at 1:00 AM, Howard Lovatt >> wrote: >>> >>> The example: >>> >>> final auto list = new ArrayList(); >>> >>> seems strange, why not: >>> >>> final list = new ArrayList(); >>> >>> After all you are trying to reduce verbosity and making final >>> declarations the same length as variable ones will encourage people to >>> use final more, which is a good thing. The use of just final has been >>> proposed by many people for Java already, it won't break code. ?Also >>> this final only construct is consistent with other languages e.g. >>> Scala, JavaFX, etc. that use def and var (final and auto >>> respectively). >>> >>> ?-- Howard. >>> >> > > > ______________________________________________________________________ > This email has been scanned by the MessageLabs Email Security System. > For more information please visit > http://www.messagelabs.com/email______________________________________________________________________ > -- -- Howard. From reinier at zwitserloot.com Mon May 25 20:00:40 2009 From: reinier at zwitserloot.com (Reinier Zwitserloot) Date: Tue, 26 May 2009 05:00:40 +0200 Subject: VERSION 2: Re: Proposal: Type inference for variable definition/initialization using the 'auto' keyword. In-Reply-To: <3dd3f56a0905251823yaa2640arfa013510ef90cb35@mail.gmail.com> References: <3dd3f56a0905241600p49f455eesa51a451be6394c75@mail.gmail.com> <66FA6ACD-2620-4A74-87CC-C5B9919C003C@zwitserloot.com> <3dd3f56a0905251823yaa2640arfa013510ef90cb35@mail.gmail.com> Message-ID: <57A11785-9E44-48F3-8264-A48B97BE00FD@zwitserloot.com> I proposed the source keyword in an almost official coin proposal, waiting only on a few minor issues to be resolved, and that proposal got tarred, feathered, then hung by the neck until dead. Evidently, a 'source' keyword isn't going to happen for coin, no matter how much we lobby for it. I took it as read that proposals are supposed to be halfway realistic, but in case that wasn't obvious: The odds of 'auto' being introduced in Project Coin, or in fact, for any java 7 change, are zero. > Cell c = new( "Foo" ); > Bad idea; you can't make that work if the LHS is an interface type, and yet very many java methodlocals and fields are in fact interfaces. The construct either can't be used, or leads to bad programming practice, such as : ArrayList l = new(); with ArrayList written out explicitly on the LHS just to make this syntax work. This is very bad; even if such a construct is final, the way the type is written out on the LHS explicitly suggests that the author intended for 'l' to be an ArrayList and not a List. I can live with this syntax for final variables, but I find 'final foo = new Type();' much more readable and it seems to me to fit better in how java works now. > It is Tim's suggestion to make auto optional, rather than mine, but > the way I read his suggestion was that there had to be a keyword > already for auto to be optional. It may be Tim's suggestion, but either way the notion of making 'auto' optional makes no sense to me: It could only possibly work for fields (whereas this is FAR more useful for method locals), AND it lacks consistency, AND it does not absolve the need for 'auto' (or some other keyword) to exist. What's the point of making 'auto' optional, then? [snip: Whether auto behaviour is allowed for fields is a thing for expert groups] Let's go back to realism for a moment: This list, and plenty of java polls in the past, have shown that any kind of type inference has some positive support, but plenty of detractors. 'auto' for fields is very unlikely to happen. Fortunately, there's -nothing- stopping java 8 or java 9 from adopting 'auto' behaviour for fields IF the community and experience with auto behaviour for method locals suggests its a good idea. Keeping the door open for such a future change requires no effort at all and does not impinge on the merits of this proposal (that is; no need to weaken its flexibility or syntax in order to make sure the future expansion remains an option). That's a lucky break - we should use it. I really do like 'final foo = expr;' quite a bit, so I want it to succeed. It seems to me that taking it slow stands a very small chance. Submit with just final and just method locals, and if an expert group determines its perfectly fine to extend this behaviour to non-finals or fields, they can make the changes themselves. --Reinier Zwitserloot On May 26, 2009, at 03:23, Howard Lovatt wrote: > Hi Reinier, > > General comment: I don't think the diamond proposal goes far enough > and would like something along the lines of either: > > auto c = new Cell( "Foo" ); > > or > > Cell c = new( "Foo" ); > > If only: > > final c = new Cell( "Foo" ); > > made it - then this would at least be a step in the right direction. > > Detailed comments inline. > > 2009/5/26 Reinier Zwitserloot : >> Why not drop the 'auto' keyword entirely? Using just 'final' has >> plenty of >> advantages: >> >> 1. No need to add a new keyword, which, lets face it, project coin is >> -NEVER- going to allow, ever. > > That might be true, which is why I keep suggesting a source keyword to > allow Java to move forward (see previous coin discussions) > >> 'module' is okay because it's context >> sensitive, but auto cannot be. The following code: >> >> auto x = 10; >> >> is technically parsable right now, in java 1.6: It's like 'String x >> = 10;' > > Yes - auto should be a normal keyword > > [snip] > >> 3. Less impactful; Assigning into a variable whose type is inferred >> from an >> expression is a much bigger deal than inferring the type of an >> unchanging >> reference. In the latter case, the link between the inferred type >> of a >> variable and its contents is obvious: It's the type of the content, >> period. >> In the former case, the type of a variable can be different from >> the content >> if you've reassigned, which leads to confusion. > > See comment at end > >> NB: Howard, making 'auto' optional is a very bad idea, IMO. It >> wouldn't be >> consistent: >> >> "a = 4;" > > It is Tim's suggestion to make auto optional, rather than mine, but > the way I read his suggestion was that there had to be a keyword > already for auto to be optional. Therefore the above example would be > an assignment to an already declared variable rather than a variable > declaration and hence no problem - Tim am I correct in this > interpretation of your suggestion? > > [snip] > >> 2. Even for a private field, where access is restricted to >> reflection, the >> scope of the field is much larger than for method locals, which >> considerably >> adds to the damage done by not being explicit about the type. For >> method >> locals, the places where the variable is used is usually fairly >> easy to spot >> (and if not, you should be splitting up your methods!). For fields, >> this is >> obviously not the case. You lose perspective of your inferred type. > > This is the sort of detail an expert group could nut out. I don't > think it is fundamental to the proposal. Personally I don't have this > problem in typed languages with type inference, i.e. JavaFX, Scala, > etc., and don't see this as a problem. This is a variation on Postel's > Prescription (?Be liberal in what you accept, and conservative in what > you send?), i.e. the return type, field type, and local type are all > types of output therefore a specific class is fine - whereas a method > argument should be an interface. > > -- Howard. > >> >> >> --Reinier Zwitserloot >> >> >> >> On May 25, 2009, at 22:31, Tim Lebedkov wrote: >> >>> Hello Howard, >>> (Jeremy - FYI) >>> >>> I have thought about it also. It would be useful to make "auto" >>> optional. >>> It was just not in the original proposal. And it would help (I'm not >>> quite sure whether it is enough) with the "final" proposal from >>> Jeremy >>> Manson >>> http://mail.openjdk.java.net/pipermail/coin-dev/2009-February/000009.html >>> . >>> >>> Making "auto" optional would also allow code like >>> >>> static a = "clouds"; >>> >>> or >>> >>> private b = 44; >>> >>> I'm not quite sure yet whether I can change my proposal and about >>> the >>> implications and acceptance (and possible danger to the whole >>> proposal) of this change. >>> >>> Regards >>> --Tim >>> >>> >>> On Mon, May 25, 2009 at 1:00 AM, Howard Lovatt >> > >>> wrote: >>>> >>>> The example: >>>> >>>> final auto list = new ArrayList(); >>>> >>>> seems strange, why not: >>>> >>>> final list = new ArrayList(); >>>> >>>> After all you are trying to reduce verbosity and making final >>>> declarations the same length as variable ones will encourage >>>> people to >>>> use final more, which is a good thing. The use of just final has >>>> been >>>> proposed by many people for Java already, it won't break code. >>>> Also >>>> this final only construct is consistent with other languages e.g. >>>> Scala, JavaFX, etc. that use def and var (final and auto >>>> respectively). >>>> >>>> -- Howard. >>>> >>> >> >> >> ______________________________________________________________________ >> This email has been scanned by the MessageLabs Email Security System. >> For more information please visit >> http://www.messagelabs.com/email______________________________________________________________________ >> > > > > -- > -- Howard. From Dmitry.Miltsov at Sun.COM Tue May 26 06:41:16 2009 From: Dmitry.Miltsov at Sun.COM (Dmitry Miltsov) Date: Tue, 26 May 2009 17:41:16 +0400 Subject: JCK feedback on "Improved Exception Handling for Java" proposal Message-ID: <4A1BF17C.8010909@sun.com> Hello, The JCK engineers have reviewed the "Improved Exception Handling for Java" proposal. We have no comments on the specification and testability of the proposed change. Thanks, Dmitry Miltsov, JCK engineer From Joe.Kearney at morganstanley.com Tue May 26 06:56:10 2009 From: Joe.Kearney at morganstanley.com (Joe Kearney) Date: Tue, 26 May 2009 14:56:10 +0100 Subject: VERSION 2: Re: Proposal: Type inference for variable definition/initialization using the 'auto' keyword. In-Reply-To: <66FA6ACD-2620-4A74-87CC-C5B9919C003C@zwitserloot.com> References: <3dd3f56a0905241600p49f455eesa51a451be6394c75@mail.gmail.com> <66FA6ACD-2620-4A74-87CC-C5B9919C003C@zwitserloot.com> Message-ID: It seems to me that to restrict auto variables not to be intersection types misses the most useful applications of a proposal to infer types of variables. If the proposal is merely to save me entering the type of the variable, then quite apart from the type system difficulties being discussed, this saves nothing when you're using an IDE. It takes two keystrokes in eclipse to assign an expression to a local variable, and you get a choice of each type up the hierarchy. I'm sure you can do the same in the other IDEs. Given the documentary benefit of having the type name presented to you in the code, and the fact that the auto proposal would seem to me to encourage coding against implementation types I don't see any win here, and personally would probably continue to use real type names in variable declarations. (I'm aware that people's opinions on both of these points differ, these aren't the main point of my post.) On the other hand, if we can use intersection types with auto/final/whatever then this genuinely adds something new to the language, that is not/cannot be done by the IDE. As a comparison, as I understand it, this is the main benefit given by the var construct in C#, especially in combination with LINQ. Joe 2009/5/26 Reinier Zwitserloot > Compared to such antics, the rules for 'final' are much, much simpler: The > type of the variable is the type of the RHS, unless the RHS is itself an > intersection type, in which case for now we can just say such a construct > isn't legal, and maybe later add support for intersection types for > variables; such a change would be entirely backwards and migration > compatible. From reinier at zwitserloot.com Tue May 26 07:43:02 2009 From: reinier at zwitserloot.com (Reinier Zwitserloot) Date: Tue, 26 May 2009 16:43:02 +0200 Subject: VERSION 2: Re: Proposal: Type inference for variable definition/initialization using the 'auto' keyword. In-Reply-To: References: <3dd3f56a0905241600p49f455eesa51a451be6394c75@mail.gmail.com> <66FA6ACD-2620-4A74-87CC-C5B9919C003C@zwitserloot.com> Message-ID: <5A68CB10-51AF-4E4D-875B-7E9DF3D41D43@zwitserloot.com> IDE automatizations are one way. I can let eclipse generate all my toString, getters, constructor, hashCode and equals boilerplate for me, but once eclipse generates pagefuls of noise, that noise will no longer be going away. The same happens, though with smaller effect, when you let your IDE turn: new HashMap>>(); into: final Map>> foo = new HashMap>>(); instead of: final foo = new HashMap>>(); or even: final FileInputStream fis = new FileInputStream(fileName); versus: final fis = new FileInputStream(fileName); However, FWIW, yes, having intersection types would be nicer, and generating a compiler error when there's no singular top type is probably far too confusing in the first place. So, yes - amend my suggestion to state that intersection types are much preferable to copping out when the RHS doesn't translate neatly to a single type. --Reinier Zwitserloot On May 26, 2009, at 15:56, Joe Kearney wrote: > It seems to me that to restrict auto variables not to be > intersection types misses the most useful applications of a proposal > to infer types of variables. If the proposal is merely to save me > entering the type of the variable, then quite apart from the type > system difficulties being discussed, this saves nothing when you're > using an IDE. > > It takes two keystrokes in eclipse to assign an expression to a > local variable, and you get a choice of each type up the hierarchy. > I'm sure you can do the same in the other IDEs. Given the > documentary benefit of having the type name presented to you in the > code, and the fact that the auto proposal would seem to me to > encourage coding against implementation types I don't see any win > here, and personally would probably continue to use real type names > in variable declarations. (I'm aware that people's opinions on both > of these points differ, these aren't the main point of my post.) > > On the other hand, if we can use intersection types with auto/final/ > whatever then this genuinely adds something new to the language, > that is not/cannot be done by the IDE. As a comparison, as I > understand it, this is the main benefit given by the var construct > in C#, especially in combination with LINQ. > > Joe > > 2009/5/26 Reinier Zwitserloot > Compared to such antics, the rules for 'final' are much, much > simpler: The type of the variable is the type of the RHS, unless the > RHS is itself an intersection type, in which case for now we can > just say such a construct isn't legal, and maybe later add support > for intersection types for variables; such a change would be > entirely backwards and migration compatible. > From Joe.Kearney at morganstanley.com Tue May 26 08:05:36 2009 From: Joe.Kearney at morganstanley.com (Joe Kearney) Date: Tue, 26 May 2009 16:05:36 +0100 Subject: VERSION 2: Re: Proposal: Type inference for variable definition/initialization using the 'auto' keyword. In-Reply-To: <5A68CB10-51AF-4E4D-875B-7E9DF3D41D43@zwitserloot.com> References: <3dd3f56a0905241600p49f455eesa51a451be6394c75@mail.gmail.com> <66FA6ACD-2620-4A74-87CC-C5B9919C003C@zwitserloot.com> <5A68CB10-51AF-4E4D-875B-7E9DF3D41D43@zwitserloot.com> Message-ID: Again, I realise that documentation of the type vs length and other considerations is a contentious issue. For the case of types with lots of parameters, however, it might be interesting to note that these will be covered nicely by the other typing proposals: final Map>> foo = new HashMap<>(); You're right that the IDE won't help shorten long non-paramatrised type names if you don't want to see that in the code at all. My personal opinion is that "auto" is of limited value if the intention is only to shorten type names, especially in light of what the IDE can do for you. But I can see that it solves this part of the problem for those who hold other opinions. Thanks, Joe 2009/5/26 Reinier Zwitserloot > IDE automatizations are one way. I can let eclipse generate all my > toString, getters, constructor, hashCode and equals boilerplate for > me, but once eclipse generates pagefuls of noise, that noise will no > longer be going away. The same happens, though with smaller effect, > when you let your IDE turn: > > new HashMap>>(); > > into: > > final Map>> foo = new HashMap List>>(); > > instead of: > > final foo = new HashMap>>(); > > > or even: > > final FileInputStream fis = new FileInputStream(fileName); > > versus: > > final fis = new FileInputStream(fileName); > > > However, FWIW, yes, having intersection types would be nicer, and > generating a compiler error when there's no singular top type is > probably far too confusing in the first place. So, yes - amend my > suggestion to state that intersection types are much preferable to > copping out when the RHS doesn't translate neatly to a single type. > > --Reinier Zwitserloot > > > > On May 26, 2009, at 15:56, Joe Kearney wrote: > > > It seems to me that to restrict auto variables not to be > > intersection types misses the most useful applications of a proposal > > to infer types of variables. If the proposal is merely to save me > > entering the type of the variable, then quite apart from the type > > system difficulties being discussed, this saves nothing when you're > > using an IDE. > > > > It takes two keystrokes in eclipse to assign an expression to a > > local variable, and you get a choice of each type up the hierarchy. > > I'm sure you can do the same in the other IDEs. Given the > > documentary benefit of having the type name presented to you in the > > code, and the fact that the auto proposal would seem to me to > > encourage coding against implementation types I don't see any win > > here, and personally would probably continue to use real type names > > in variable declarations. (I'm aware that people's opinions on both > > of these points differ, these aren't the main point of my post.) > > > > On the other hand, if we can use intersection types with auto/final/ > > whatever then this genuinely adds something new to the language, > > that is not/cannot be done by the IDE. As a comparison, as I > > understand it, this is the main benefit given by the var construct > > in C#, especially in combination with LINQ. > > > > Joe > > > > 2009/5/26 Reinier Zwitserloot > > Compared to such antics, the rules for 'final' are much, much > > simpler: The type of the variable is the type of the RHS, unless the > > RHS is itself an intersection type, in which case for now we can > > just say such a construct isn't legal, and maybe later add support > > for intersection types for variables; such a change would be > > entirely backwards and migration compatible. > > > > > From rssh at gradsoft.com.ua Tue May 26 05:25:29 2009 From: rssh at gradsoft.com.ua (Ruslan Shevchenko) Date: Tue, 26 May 2009 15:25:29 +0300 (EEST) Subject: VERSION 2: Re: Proposal: Type inference for variable definition/initialization using the 'auto' keyword. In-Reply-To: References: <3dd3f56a0905241600p49f455eesa51a451be6394c75@mail.gmail.com> <66FA6ACD-2620-4A74-87CC-C5B9919C003C@zwitserloot.com> Message-ID: > It seems to me that to restrict auto variables not to be intersection > types > misses the most useful applications of a proposal to infer types of > variables. If the proposal is merely to save me entering the type of the > variable, then quite apart from the type system difficulties being > discussed, this saves nothing when you're using an IDE. > Economically, value of code owning is mostly cost of reading than cost of writing. I. e. I think 'IDE can do this' is not very valuable argument. > can do the same in the other IDEs. Given the documentary benefit of having > the type name presented to you in the code, and the fact that the auto > proposal would seem to me to encourage coding against implementation types > I > don't see any win here, and personally would probably continue to use real > type names in variable declarations. (I'm aware that people's opinions on > both of these points differ, these aren't the main point of my post.) > I guess, that main value of 'auto' proposal is not think about exact verbose implementation type at all, during writing and reading code. Pattern 'use interface names for variable types' exists (not fully, but I guess in many) on absence of auto keyword. Most local variables are short living and have no assignments from different implementations of interface. And if we need exactly detail type - we still can write one. > On the other hand, if we can use intersection types with > auto/final/whatever > then this genuinely adds something new to the language, that is not/cannot > be done by the IDE. As a comparison, as I understand it, this is the main > benefit given by the var construct in C#, especially in combination with > LINQ. > > Joe > > 2009/5/26 Reinier Zwitserloot > >> Compared to such antics, the rules for 'final' are much, much simpler: >> The >> type of the variable is the type of the RHS, unless the RHS is itself an >> intersection type, in which case for now we can just say such a >> construct >> isn't legal, and maybe later add support for intersection types for >> variables; such a change would be entirely backwards and migration >> compatible. > > From java.net at twistedprotein.com Tue May 26 09:08:04 2009 From: java.net at twistedprotein.com (Brendon McLean) Date: Tue, 26 May 2009 18:08:04 +0200 Subject: VERSION 2: Re: Proposal: Type inference for variable definition/initialization using the 'auto' keyword. In-Reply-To: References: <3dd3f56a0905241600p49f455eesa51a451be6394c75@mail.gmail.com> <66FA6ACD-2620-4A74-87CC-C5B9919C003C@zwitserloot.com> Message-ID: <276B8A7A-FF3D-4394-87AF-62E4149D7F78@twistedprotein.com> On 26 May 2009, at 14:25, Ruslan Shevchenko wrote: > Economically, value of code owning is mostly cost of reading than > cost of writing. I. e. I think 'IDE can do this' is not very valuable > argument. Traditionally so, but IDEs are on their way to addressing the readability aspect too. The upcoming early access of IntelliJ IDEA can code fold: fillMap(Collections.>emptyMap()); to: fillMap(Collections.<~>emptyMap()); Expect the herd to follow. (likewise, anonymous inner classes can fold too and I can pretend that a closures proposal succeeded). I realise there's a purity issue here; one shouldn't need an IDE to make head or tail of code. But personally, I would rather Java ages gracefully and look at my code through ruby-tinted IDE goggles than make changes which compromise Java's simplicity. Regards, Brendon. From tim.lebedkov at googlemail.com Tue May 26 15:09:06 2009 From: tim.lebedkov at googlemail.com (Tim Lebedkov) Date: Wed, 27 May 2009 00:09:06 +0200 Subject: VERSION 2: Re: Proposal: Type inference for variable definition/initialization using the 'auto' keyword. In-Reply-To: <3dd3f56a0905251823yaa2640arfa013510ef90cb35@mail.gmail.com> References: <3dd3f56a0905241600p49f455eesa51a451be6394c75@mail.gmail.com> <66FA6ACD-2620-4A74-87CC-C5B9919C003C@zwitserloot.com> <3dd3f56a0905251823yaa2640arfa013510ef90cb35@mail.gmail.com> Message-ID: Hello Howard, yes, you need auto a=4; of final a=4; a=4 is an assignment Regards --Tim On Tue, May 26, 2009 at 3:23 AM, Howard Lovatt wrote: > Hi Reinier, > > General comment: I don't think the diamond proposal goes far enough > and would like something along the lines of either: > > auto c = new Cell( "Foo" ); > > or > > Cell c = new( "Foo" ); > > If only: > > final c = new Cell( "Foo" ); > > made it - then this would at least be a step in the right direction. > > Detailed comments inline. > > 2009/5/26 Reinier Zwitserloot : >> Why not drop the 'auto' keyword entirely? Using just 'final' has plenty of >> advantages: >> >> 1. No need to add a new keyword, which, lets face it, project coin is >> -NEVER- going to allow, ever. > > That might be true, which is why I keep suggesting a source keyword to > allow Java to move forward (see previous coin discussions) > >> 'module' is okay because it's context >> sensitive, but auto cannot be. The following code: >> >> auto x = 10; >> >> is technically parsable right now, in java 1.6: It's like 'String x = 10;' > > Yes - auto should be a normal keyword > > [snip] > >> 3. Less impactful; Assigning into a variable whose type is inferred from an >> expression is a much bigger deal than inferring the type of an unchanging >> reference. In the latter case, the link between the inferred type of a >> variable and its contents is obvious: It's the type of the content, period. >> In the former case, the type of a variable can be different from the content >> if you've reassigned, which leads to confusion. > > See comment at end > >> NB: Howard, making 'auto' optional is a very bad idea, IMO. It wouldn't be >> consistent: >> >> "a = 4;" > > It is Tim's suggestion to make auto optional, rather than mine, but > the way I read his suggestion was that there had to be a keyword > already for auto to be optional. Therefore the above example would be > an assignment to an already declared variable rather than a variable > declaration and hence no problem - Tim am I correct in this > interpretation of your suggestion? > > [snip] > >> 2. Even for a private field, where access is restricted to reflection, the >> scope of the field is much larger than for method locals, which considerably >> adds to the damage done by not being explicit about the type. For method >> locals, the places where the variable is used is usually fairly easy to spot >> (and if not, you should be splitting up your methods!). For fields, this is >> obviously not the case. You lose perspective of your inferred type. > > This is the sort of detail an expert group could nut out. I don't > think it is fundamental to the proposal. Personally I don't have this > problem in typed languages with type inference, i.e. JavaFX, Scala, > etc., and don't see this as a problem. This is a variation on Postel's > Prescription (?Be liberal in what you accept, and conservative in what > you send?), i.e. the return type, field type, and local type are all > types of output therefore a specific class is fine - whereas a method > argument should be an interface. > > ?-- Howard. > >> >> >> ?--Reinier Zwitserloot >> >> >> >> On May 25, 2009, at 22:31, Tim Lebedkov wrote: >> >>> Hello Howard, >>> (Jeremy - FYI) >>> >>> I have thought about it also. It would be useful to make "auto" optional. >>> It was just not in the original proposal. And it would help (I'm not >>> quite sure whether it is enough) with the "final" proposal from Jeremy >>> Manson >>> http://mail.openjdk.java.net/pipermail/coin-dev/2009-February/000009.html. >>> >>> Making "auto" optional would also allow code like >>> >>> static a = "clouds"; >>> >>> or >>> >>> private b = 44; >>> >>> I'm not quite sure yet whether I can change my proposal and about the >>> implications and acceptance (and possible danger to the whole >>> proposal) of this change. >>> >>> Regards >>> --Tim >>> >>> >>> On Mon, May 25, 2009 at 1:00 AM, Howard Lovatt >>> wrote: >>>> >>>> The example: >>>> >>>> final auto list = new ArrayList(); >>>> >>>> seems strange, why not: >>>> >>>> final list = new ArrayList(); >>>> >>>> After all you are trying to reduce verbosity and making final >>>> declarations the same length as variable ones will encourage people to >>>> use final more, which is a good thing. The use of just final has been >>>> proposed by many people for Java already, it won't break code. ?Also >>>> this final only construct is consistent with other languages e.g. >>>> Scala, JavaFX, etc. that use def and var (final and auto >>>> respectively). >>>> >>>> ?-- Howard. >>>> >>> >> >> >> ______________________________________________________________________ >> This email has been scanned by the MessageLabs Email Security System. >> For more information please visit >> http://www.messagelabs.com/email______________________________________________________________________ >> > > > > -- > ?-- Howard. > From tim.lebedkov at googlemail.com Tue May 26 15:10:18 2009 From: tim.lebedkov at googlemail.com (Tim Lebedkov) Date: Wed, 27 May 2009 00:10:18 +0200 Subject: VERSION 2: Re: Proposal: Type inference for variable definition/initialization using the 'auto' keyword. In-Reply-To: <66FA6ACD-2620-4A74-87CC-C5B9919C003C@zwitserloot.com> References: <3dd3f56a0905241600p49f455eesa51a451be6394c75@mail.gmail.com> <66FA6ACD-2620-4A74-87CC-C5B9919C003C@zwitserloot.com> Message-ID: Hello Reinier, see my comments below On Tue, May 26, 2009 at 2:12 AM, Reinier Zwitserloot wrote: > Why not drop the 'auto' keyword entirely? Using just 'final' has plenty of > advantages: I assume you know about the main disadvantage, but I'll write it one more time: You cannot define a mutable variable using "final". > > 1. No need to add a new keyword, which, lets face it, project coin is > -NEVER- going to allow, ever. 'module' is okay because it's context > sensitive, but auto cannot be. The following code: > > auto x = 10; > > is technically parsable right now, in java 1.6: It's like 'String x = 10;' > except instead of 'String' we have a type named 'auto', which is technically > legal even though its against convention by having a type with a lowercase > first letter. > I hope we can have a new keyword :-) > 2. No confusion around the following code: > > auto list = new ArrayList(); > list = new LinkedList(); //fail: LinkedList is not an ArrayList! > > NB: It is infeasible to automagically detect that 'list' should be typed as > just a List, and its quite a stretch for java to start considering ALL > assignments and type the variable name with the intersection type(s). > Compared to such antics, the rules for 'final' are much, much simpler: The > type of the variable is the type of the RHS, unless the RHS is itself an > intersection type, in which case for now we can just say such a construct > isn't legal, and maybe later add support for intersection types for > variables; such a change would be entirely backwards and migration > compatible. > compiler should probably generate 2 errors for the second line here: final list = new ArrayList(); list = new LinkedList(); //fail: LinkedList is not an ArrayList! 1st error: you cannot assign a new value to a final variable 2nd error: incompatible types It seems "final" instead of "auto" has no real advantage here > 3. Less impactful; Assigning into a variable whose type is inferred from an > expression is a much bigger deal than inferring the type of an unchanging > reference. In the latter case, the link between the inferred type of a > variable and its contents is obvious: It's the type of the content, period. > In the former case, the type of a variable can be different from the content > if you've reassigned, which leads to confusion. > If "auto" is more "impactful", then in a very small degree. > > NB: Howard, making 'auto' optional is a very bad idea, IMO. It wouldn't be > consistent: > > "a = 4;" > > can now mean either: assign the result of expression '4' to the existing > variable named 'a', and make sure the type of the expression is compatible > with the type of 'a', OR: Create a new variable named 'a', and infer the > type off of the expression '4', then assign the result of that expression to > it. > > I -really- doubt java is the type of language to roll with creating > variables on the fly when assigning to them, python-style. I rate the odds > of that going into coin as 'when pigs fly'. Thus, we are stuck with > inferring 'auto' only if there are OTHER keywords involved, but other than > 'final', that never happens for method locals. Thus, you must be talking > about type inference for fields, which is far too big a change for coin; > consider: you'll need either auto a = 4; or final a = 4; a = 4 is an assignment > > 1. Fields can be accessed outside of scope, which means the type information > on the variable is much more important. Typing a list as 'ArrayList' instead > of a 'List' is a bad thing for a field, but only a very minor style > incursion for a final method local, and yet outlawing 'auto foo = new > ArrayList();' seems arbitrary and wrong. > > 2. Even for a private field, where access is restricted to reflection, the > scope of the field is much larger than for method locals, which considerably > adds to the damage done by not being explicit about the type. For method > locals, the places where the variable is used is usually fairly easy to spot > (and if not, you should be splitting up your methods!). For fields, this is > obviously not the case. You lose perspective of your inferred type. the usage of instance fields outside of the declaring class are rare. Additionally we have at least 3 sources for the type information: - JavaDoc - .class files - IDE Regards --Tim > > > ?--Reinier Zwitserloot > > > > On May 25, 2009, at 22:31, Tim Lebedkov wrote: > >> Hello Howard, >> (Jeremy - FYI) >> >> I have thought about it also. It would be useful to make "auto" optional. >> It was just not in the original proposal. And it would help (I'm not >> quite sure whether it is enough) with the "final" proposal from Jeremy >> Manson >> http://mail.openjdk.java.net/pipermail/coin-dev/2009-February/000009.html. >> >> Making "auto" optional would also allow code like >> >> static a = "clouds"; >> >> or >> >> private b = 44; >> >> I'm not quite sure yet whether I can change my proposal and about the >> implications and acceptance (and possible danger to the whole >> proposal) of this change. >> >> Regards >> --Tim >> >> >> On Mon, May 25, 2009 at 1:00 AM, Howard Lovatt >> wrote: >>> >>> The example: >>> >>> final auto list = new ArrayList(); >>> >>> seems strange, why not: >>> >>> final list = new ArrayList(); >>> >>> After all you are trying to reduce verbosity and making final >>> declarations the same length as variable ones will encourage people to >>> use final more, which is a good thing. The use of just final has been >>> proposed by many people for Java already, it won't break code. ?Also >>> this final only construct is consistent with other languages e.g. >>> Scala, JavaFX, etc. that use def and var (final and auto >>> respectively). >>> >>> ?-- Howard. >>> >> > > From reinier at zwitserloot.com Tue May 26 15:26:54 2009 From: reinier at zwitserloot.com (Reinier Zwitserloot) Date: Wed, 27 May 2009 00:26:54 +0200 Subject: VERSION 2: Re: Proposal: Type inference for variable definition/initialization using the 'auto' keyword. In-Reply-To: References: <3dd3f56a0905241600p49f455eesa51a451be6394c75@mail.gmail.com> <66FA6ACD-2620-4A74-87CC-C5B9919C003C@zwitserloot.com> Message-ID: <79AAC28A-4D99-4FEF-B31A-69437722C208@zwitserloot.com> replies inline. --Reinier Zwitserloot On May 27, 2009, at 00:10, Tim Lebedkov wrote: > I assume you know about the main disadvantage, but I'll write it one > more time: > You cannot define a mutable variable using "final". That's an advantage, actually, because mutating a variable whose type is auto inferenced by its first assignment is problematic. e.g: auto foo = new ArrayList(); foo = new LinkedList(); //this fails, and that is a clear failure of the compiler to Do What I Mean. > > I hope we can have a new keyword :-) > We can't. You can ask Joe if you aren't willing to take my word for it, but I'll eat my right shoe if a new global keyword (vs. a context sensitive one like 'module'), especially something as common as 'auto', which I'm sure exists as many a variable name already, is deemed acceptable for Project Coin. Seriously. Pigs flying, hell freezing over, and other such statements aren't hyperbole here. >> > compiler should probably generate 2 errors for the second line here: > > final list = new ArrayList(); > list = new LinkedList(); //fail: LinkedList is not an ArrayList! > > 1st error: you cannot assign a new value to a final variable > 2nd error: incompatible types > > It seems "final" instead of "auto" has no real advantage here > Wahuh? I don't get what you're saying. In the 'final' case, the behaviour is no different compared to what happens now: Trying to reassign a final variable gets you a 'you can't reassign final variables' error. Great - that's what final is for. I would have expected that problem. However, in the incompatible types case, we now have an error where previously, before the auto proposal, there wouldn't have been an error, because the author would have instinctively used List instead of ArrayList. I would NOT have expected this error. In fact, in other languages you wouldn't even get that error, because the type of the LHS is inferred from *all* RHS expression types assigned to it. I already mentioned why this strategy is not feasible for java. > > If "auto" is more "impactful", then in a very small degree. I backed up my argument. You can't just say "it isn't" and wave a magic wand. You have to take my arguments and prove why they are either wrong, or trivial. > > you'll need either > > auto a = 4; > or > final a = 4; > > a = 4 is an assignment > Yes. Which is inconsistent, and means that 'auto' does need to exist, so what's the point of doing this in the first place? If you could make the need for a keyword go away altogether, you'd be on to something very important (given that you just can't add a keyword for Project Coin - not gonna happen). So, what's the goal? Saving 5 characters of typing? If your main aim in this proposal is to shave off a bunch of 5 character sequences, I think you're doing this for all the wrong reasons. The advantages of eliding the LHS type is not just saving characters (though, for certain types, you can save quite a few of them; a lot more than 5!) - it's not having to bother looking up a type, adding an import statement in certain cases, and having code migrate automatically even if the RHS expression changes type because you're still in the pre-API-lockdown phase of development. >> > the usage of instance fields outside of the declaring class are rare. > Additionally we have at least 3 sources for the type information: Irrelevant; it's not about figuring out what the type is - it's that the type will likely be wrong, because it's needlessly specific (ArrayList vs. List). From Joe.Darcy at Sun.COM Tue May 26 15:45:31 2009 From: Joe.Darcy at Sun.COM (Joe Darcy) Date: Tue, 26 May 2009 15:45:31 -0700 Subject: VERSION 2: Re: Proposal: Type inference for variable definition/initialization using the 'auto' keyword. In-Reply-To: <79AAC28A-4D99-4FEF-B31A-69437722C208@zwitserloot.com> References: <3dd3f56a0905241600p49f455eesa51a451be6394c75@mail.gmail.com> <66FA6ACD-2620-4A74-87CC-C5B9919C003C@zwitserloot.com> <79AAC28A-4D99-4FEF-B31A-69437722C208@zwitserloot.com> Message-ID: <4A1C710B.4000106@sun.com> On 05/26/09 03:26 PM, Reinier Zwitserloot wrote: > replies inline. > > --Reinier Zwitserloot > > > > On May 27, 2009, at 00:10, Tim Lebedkov wrote: > > >> I assume you know about the main disadvantage, but I'll write it one >> more time: >> You cannot define a mutable variable using "final". >> > > That's an advantage, actually, because mutating a variable whose type > is auto inferenced by its first assignment is problematic. e.g: > > auto foo = new ArrayList(); > foo = new LinkedList(); //this fails, and that is a clear failure of > the compiler to Do What I Mean. > > >> I hope we can have a new keyword :-) >> >> > > We can't. You can ask Joe if you aren't willing to take my word for > it, but I'll eat my right shoe if a new global keyword (vs. a context > sensitive one like 'module'), especially something as common as > 'auto', which I'm sure exists as many a variable name already, is > deemed acceptable for Project Coin. Seriously. Pigs flying, hell > freezing over, and other such statements aren't hyperbole here. > No new keywords in Project Coin! -Joe From neal at gafter.com Tue May 26 16:04:46 2009 From: neal at gafter.com (Neal Gafter) Date: Tue, 26 May 2009 16:04:46 -0700 Subject: VERSION 2: Re: Proposal: Type inference for variable definition/initialization using the 'auto' keyword. In-Reply-To: <4A1C710B.4000106@sun.com> References: <3dd3f56a0905241600p49f455eesa51a451be6394c75@mail.gmail.com> <66FA6ACD-2620-4A74-87CC-C5B9919C003C@zwitserloot.com> <79AAC28A-4D99-4FEF-B31A-69437722C208@zwitserloot.com> <4A1C710B.4000106@sun.com> Message-ID: <15e8b9d20905261604r26407bf4v293e039db2622068@mail.gmail.com> On Tue, May 26, 2009 at 3:45 PM, Joe Darcy wrote: > >> I hope we can have a new keyword :-) > >> > >> > > > > We can't. You can ask Joe if you aren't willing to take my word for > > it, but I'll eat my right shoe if a new global keyword (vs. a context > > sensitive one like 'module'), especially something as common as > > 'auto', which I'm sure exists as many a variable name already, is > > deemed acceptable for Project Coin. Seriously. Pigs flying, hell > > freezing over, and other such statements aren't hyperbole here. > > > > No new keywords in Project Coin! It turns out this particular context can easily be handled by a context-sensitive keyword (e.g. if you have a type named "auto" in scope, then that is the type of the variable, otherwise the type is inferred from the right-hand-side). However, I agree with Joe's previous assessment that this category of proposed changes doesn't (in isolation) pay for itself, especially given the likely addition of the "diamond new" inference on constructors. Which makes me wonder why discussion continues on the topic. From Ulf.Zibis at gmx.de Wed May 27 01:10:44 2009 From: Ulf.Zibis at gmx.de (Ulf Zibis) Date: Wed, 27 May 2009 10:10:44 +0200 Subject: Extend switch .. case statement for all types and simple expressions In-Reply-To: References: <49D14427.5070105@gmx.de> <49D33129.2090600@gmx.de> <4A19686D.4080207@gmx.de> Message-ID: <4A1CF584.6000701@gmx.de> Am 27.05.2009 09:15, Daniel Cheng schrieb: > On Sun, May 24, 2009 at 11:31 PM, Ulf Zibis wrote: > >> Am 02.04.2009 11:34, Daniel Cheng schrieb: >> >>> On Wed, Apr 1, 2009 at 5:17 PM, Ulf Zibis wrote: >>> >>> >>>> I would like to add, that the MAJOR ADVANTAGE of my proposal is, >>>> that the numerous grades/levels of this proposal could be implemented >>>> step by step, depending on the complexity of changes, which could be >>>> done for JDK 7. >>>> More sophisticated grades/levels could be seamlessly added later. >>>> This would be impossible, if the concurring syntax of "Strings in >>>> switch", which only compares for equality, comes to account. >>>> Also Multiple switch expressions and case ranges >>>> >>>> could seamlessly be integrated in my proposal. >>>> >>>> As I argued more detailed before, default semantic of "switch..case" >>>> should stay on determining the cases by IDENTITY. >>>> Strings, which are equal, could simply be made identical by >>>> String#intern(). >>>> >>>> >>> Except, using some combination of gc options, intern'ed String won't be >>> gc'ed. >>> >>> >>> >> Literals are always intern'd, so the wouldn't gc'ed either. >> >> > > What if your "myStringFromElsewere" does not matches anything ? > In the "miss" case, new string is intern'ed. > Your heap space would be ~20 bytes smaller. ;-) In other words, if your program deals with millions of strings-from-elsewhere, your should... - use the gc options - use if..else construct instead - wait for integration of "Extend switch .. case statement for all types and simple expressions" proposal, so you can use "switch (myStringFromElsewere.equals())" -Ulf From Joe.Darcy at Sun.COM Wed May 27 15:52:23 2009 From: Joe.Darcy at Sun.COM (Joe Darcy) Date: Wed, 27 May 2009 15:52:23 -0700 Subject: For further consideration, round 2 Message-ID: <4A1DC427.7050903@sun.com> Greetings. The first group of proposals selected for further consideration were * Strings in switch, Joe Darcy * Improved Exception Handling for Java, Neal Gafter * Automatic Resource Management, Josh Bloch * Improved Type Inference for Generic Instance Creation, Jeremy Manson * Elvis and Other Null-Safe Operators, Written by Neal Gafter and submitted by Stephen Colebourne * Simplified Varargs Method Invocation, Bob Lee After due deliberation, and next set of proposals meeting the Project Coin criteria for further consideration are: * Logically a combined proposal for better integral literals: * Byte and Short Integer Literal Suffixes, Bruce Chapman * Binary Literals, Derek Foster * Underscores in numbers, Derek Foster * Language support for JSR 292, John Rose * Indexing access syntax for Lists and Maps, Shams Mahmood Imam * Collection Literals, Joshua Bloch * Large arrays (revised), James Lowden All the selected proposals were reviewed and judged to have favorable effort to reward ratios and to preserve the essential character of the language. Work should continue refining the selected proposals and producing prototypes. In particular, a unified proposal for integer literals should be produced. Language change proposals not on the combined "for further consideration" list will not be included in JDK 7; there is no need for continued discussion about them on the Project Coin mailing list. Detailed rationales for why particular proposals were not selected will not be provided. Final selection of the five or so proposals to be included in the platform will occur within the next few months. Regards, -Joe From Joe.Darcy at Sun.COM Wed May 27 15:53:06 2009 From: Joe.Darcy at Sun.COM (Joe Darcy) Date: Wed, 27 May 2009 15:53:06 -0700 Subject: 64-bit array functionality implemented via libraries? Message-ID: <4A1DC452.1080807@sun.com> Hello. As another point in the design space, assuming indexing access syntax is available for user-defined types and the existence of collection literals, I'd like to see what implementing 64-bit array functionality via libraries would look like. A libraries-based approach that does not require VM changes, but could benefit from them later, has a higher probability of being included in JDK 7. -Joe From Joe.Darcy at Sun.COM Wed May 27 15:56:51 2009 From: Joe.Darcy at Sun.COM (Joe Darcy) Date: Wed, 27 May 2009 15:56:51 -0700 Subject: Thoughts on unified integer literal improvements Message-ID: <4A1DC533.2060202@sun.com> Hello. On the set of improved integer literal features, I think combining the underscores as separators and binary literals is straightforward given separately correct grammars for each change. As an alternate to "y" and "s" suffices, I suggesting considering a "u" suffix to mean unsigned. Literals with a trailing "u" would have type int; widening conversions of such literals would 0 extend and narrowing conversions would range check on the width of set bits. For example, byte b = 0xABu // equivalent to (0xAB & 0xFF) long ell = 0xFFFFFFFFu; // A positive long value I think this approach has some advantages over the "y" suffix; in particular I think it gives more desirable behavior in cases like this: byte b = 0xFFy // a negative byte value byte b = 0xFFu // also a negative byte value short s = 0xFFy // a negative short value, -128; // byte value is signed extended short s = 0xFFu // a positive short value, +127 int i = 0xFFy // -128 int i = 0xFFu // 127 -Joe From pbenedict at apache.org Thu May 28 00:30:58 2009 From: pbenedict at apache.org (Paul Benedict) Date: Thu, 28 May 2009 02:30:58 -0500 Subject: Thoughts on unified integer literal improvements Message-ID: Forgive any obtuseness on my part, but I believe the 'y' suffix is esoteric and unnecessary. I don't remember any other programming language that has that literal suffix. Is it perhaps something novel? byte b1 = 0xFF; byte b2 = 3; Can someone explain to me why this shouldn't straight compile? Or why widening must occur to the literal since the type is clearly known to the compiler? It should be an error if the token cannot fit into a byte memory space (e.g., 0x100). Paul From mthornton at optrak.co.uk Thu May 28 00:35:23 2009 From: mthornton at optrak.co.uk (Mark Thornton) Date: Thu, 28 May 2009 08:35:23 +0100 Subject: Thoughts on unified integer literal improvements In-Reply-To: References: Message-ID: <4A1E3EBB.8060107@optrak.co.uk> Paul Benedict wrote: > byte b1 = 0xFF; > byte b2 = 3; > > Can someone explain to me why this shouldn't straight compile? Because 0xFF is equivalent to 255 which is outside the range of byte. Compare with byte b1 = 0xFFFFFFFF; It is a consequence of the (unfortunate) choice of bytes as signed. Mark From Ulf.Zibis at gmx.de Thu May 28 00:42:34 2009 From: Ulf.Zibis at gmx.de (Ulf Zibis) Date: Thu, 28 May 2009 09:42:34 +0200 Subject: Extend switch .. case statement for Object types and simple expressions In-Reply-To: <4A133644.40104@sun.com> References: <49D10FE6.3000404@gmx.de> <4A133644.40104@sun.com> Message-ID: <4A1E406A.8070904@gmx.de> Joe, again, can you please be more specific, which examples are confusing for you, and in which way? Am 20.05.2009 00:44, Joe Darcy schrieb: > Hello. > > Catching up on comments. > > On 03/30/09 11:31 AM, Ulf Zibis wrote: >> AUTHOR(S): Ulf Zibis, Cologne, Germany >> >> OVERVIEW >> FEATURE SUMMARY: Extend switch .. case statement for Object types and >> simple expressions. >> MAJOR ADVANTAGE: >> - Increases readability of source in concurrence to if .. else if .. >> else syntax. >> - Sophisticated jumps. >> MAJOR BENEFIT: >> Stop some programmers escaping to some modern scripting language. >> MAJOR DISADVANTAGE: >> Programmers from other languages, especially C, may be confused about >> such rich syntax. >> > > I'm also a bit confused over what exactly is being proposed; it does > feel to me to be a rather aggressive change to switch. Yes, fulfilling all given examples would be a rather aggressive change to switch. But you could start from example (1), and stop, where the change seems to be too radical. Confusing examples ? -Ulf From pbenedict at apache.org Thu May 28 00:47:34 2009 From: pbenedict at apache.org (Paul Benedict) Date: Thu, 28 May 2009 02:47:34 -0500 Subject: Thoughts on unified integer literal improvements In-Reply-To: <4A1E3EBB.8060107@optrak.co.uk> References: <4A1E3EBB.8060107@optrak.co.uk> Message-ID: Thanks Mark :-) Then I believe the 'u' suffix is more straightforward. I can mentally make the connection that 'u' means an 'unsigned' literal. I prefer that over any other letter suffix. byte b1 = 0xFFu; // you get -127 Paul On Thu, May 28, 2009 at 2:35 AM, Mark Thornton wrote: > Because 0xFF is equivalent to 255 which is outside the range of byte. > Compare with > > byte b1 = 0xFFFFFFFF; > > It is a consequence of the (unfortunate) choice of bytes as signed. > > Mark > > Paul Benedict wrote: >> byte b1 = 0xFF; >> byte b2 = 3; >> >> Can someone explain to me why this shouldn't straight compile? From Joe.Darcy at Sun.COM Thu May 28 00:54:02 2009 From: Joe.Darcy at Sun.COM (Joseph D. Darcy) Date: Thu, 28 May 2009 00:54:02 -0700 Subject: Thoughts on unified integer literal improvements In-Reply-To: References: <4A1E3EBB.8060107@optrak.co.uk> Message-ID: <4A1E431A.4090906@sun.com> Paul Benedict wrote: > Thanks Mark :-) Then I believe the 'u' suffix is more straightforward. > ...and "u" is used in C to mean unsigned; although if I understand the C rules correctly, unsigned literals in C can only be assigned to unsigned variables. With this proposal, Java would have unsigned int literals but only a *signed* int type. -Joe > I can mentally make the connection that 'u' means an 'unsigned' > literal. I prefer that over any other letter suffix. > > byte b1 = 0xFFu; // you get -127 > > Paul > > On Thu, May 28, 2009 at 2:35 AM, Mark Thornton wrote: > >> Because 0xFF is equivalent to 255 which is outside the range of byte. >> Compare with >> >> byte b1 = 0xFFFFFFFF; >> >> It is a consequence of the (unfortunate) choice of bytes as signed. >> >> Mark >> >> Paul Benedict wrote: >> >>> byte b1 = 0xFF; >>> byte b2 = 3; >>> >>> Can someone explain to me why this shouldn't straight compile? >>> > > From pbenedict at apache.org Thu May 28 01:05:52 2009 From: pbenedict at apache.org (Paul Benedict) Date: Thu, 28 May 2009 03:05:52 -0500 Subject: Thoughts on unified integer literal improvements In-Reply-To: <4A1E431A.4090906@sun.com> References: <4A1E3EBB.8060107@optrak.co.uk> <4A1E431A.4090906@sun.com> Message-ID: On Thu, May 28, 2009 at 2:54 AM, Joseph D. Darcy wrote: > With this proposal, Java would have unsigned int literals but only a > *signed* int type. I still don't like the 'y' or 's' suffixes. As was being proposed: int i = 0xFFy; // -128 int i = 0xFFu; // 127 But I would prefer an outright negative symbol in addition to the suffix: int i = -0xFFu; // -128 int i = 0xFFu; // 127 And maybe even enforcing wrapping it in parenthesis before negating it: int i = -(0xFFu); // -128 Paul From brucechapman at paradise.net.nz Thu May 28 03:42:33 2009 From: brucechapman at paradise.net.nz (Bruce Chapman) Date: Thu, 28 May 2009 22:42:33 +1200 Subject: Thoughts on unified integer literal improvements In-Reply-To: <4A1DC533.2060202@sun.com> References: <4A1DC533.2060202@sun.com> Message-ID: <4A1E6A99.7090801@paradise.net.nz> Joe Darcy wrote: > Hello. > > On the set of improved integer literal features, I think combining the > underscores as separators and binary literals is straightforward given > separately correct grammars for each change. > > As an alternate to "y" and "s" suffices, I suggesting considering a > "u" suffix to mean unsigned. Literals with a trailing "u" would have > type int; widening conversions of such literals would 0 extend and > narrowing conversions would range check on the width of set bits. For > example, > Doesn't that idea has some problems introducing it into the language and type system? if it is "Literals with a trailing "u" would have type int;" then the type is int, and the value just the same as for when there was no suffix. If the widening and narrowing changes behaviour for these literals only, how can this be done unless these literals are of some new type, or the type system knows about the notation used to declare the value? And if we can have unsigned ints surreptitiously like this, then lets have unsigned byte as well, and unsigned byte arrays. Yeeha - now I'm really happy. :) But taking that idea, and combining it with the autosizing integer literal proposal such that we use the "u" suffix to denote autosizing (rather than only having it work for hex literals with the 0h prefix), now that might fly, and could work for decimal and octal and binary as well. I'll have to do some more thinking thru on this, and now is not an ideal time for me. > byte b = 0xABu // equivalent to (0xAB & 0xFF) do you mean // equivalent to (byte) 0xAB ? (because (0xAB & 0xFF) is already equivalent to 0xAB) > > long ell = 0xFFFFFFFFu; // A positive long value but int hell = 0xFFFFFFFFu; // -1 ??? > > I think this approach has some advantages over the "y" suffix; in > particular I think it gives more desirable behavior in cases like this: > > byte b = 0xFFy // a negative byte value > byte b = 0xFFu // also a negative byte value > > > short s = 0xFFy // a negative short value, -128; > // byte value is signed extended > short s = 0xFFu // a positive short value, +127 do you mean // a positive short value, +255? > > int i = 0xFFy // -128 > int i = 0xFFu // 127 > > -Joe > Bruce From Ulf.Zibis at gmx.de Thu May 28 07:35:58 2009 From: Ulf.Zibis at gmx.de (Ulf Zibis) Date: Thu, 28 May 2009 16:35:58 +0200 Subject: JCK feedback on "Strings in Switch" proposal In-Reply-To: References: <4A12A923.9060501@sun.com> <4A1969C2.402@gmx.de> <4A199E51.2020706@sun.com> <4A1AA7CE.4080206@gmx.de> Message-ID: <4A1EA14E.1090608@gmx.de> Am 25.05.2009 17:01, Reinier Zwitserloot schrieb: > Creating a string switch proposal for equalsIgnoreCase reeks of > creating the kitchen sink language: Stuff everything into a language > construct. If that's a good idea, where do we stop? How about > comparing strings not via case insensitivity, but intended syntactic > meaning (where ? is equal to a to is equal to ?, and ? is equal to > both 'u' and 'ue', etcetera - java doesn't have this method in a > library, unfortunately which is why this kind of comparison isn't done > often, but for obvious reasons, it should be used far more often than > it is now). You're effectively elevating the concept of a case > insensitive string comparison to a part of the JLS, whereas currently > it isn't; it's just 1 library method and 1 static comparator object in > the String class. I think you have misunderstood me mentioning "string switch proposal for equalsIgnoreCase". I just want to see the switch..case construct serving as general purpose _n-way fork_ in program flow. IMHO it's a smart syntax providing perfect readability. Only for _2-way fork_ the if..else construct is smart syntax. Additionally if..else_if..else_if.. construct has the disadvantage of missing fall-through facility. The examples show just one thinkable syntax, to feed a discussion for alternative ideas. I rethought my proposal and come to more general syntax: Proposal for SYNTAX SPECIFICATION: switch (expression1 | booleanExpressionTemplate(?) | substitution_of_?) { case: [booleanOperator ]expression2 | substitution_of_? | booleanExpressionTemplate(?) {...} ... } if booleanOperator is missing: - expression1 is primitive value --> execute: expression1 == expression2 - expression1 is reference --> execute: expression1.equals(expression2) (sophisticated special case to aviod potential NPE): - expression1 is reference and expression2 is CONSTANT --> execute: expression2.equals(expression1) Examples for booleanExpressionTemplate(?) and it's possible substitution: "Math.sin(?) > 0.5" --> foo(bar), floatVar, intVar, PRIM_CONST (including autoboxed Number objects) "? >= 10 && ? < 20" --> foo(bar), primitiveVar, PRIM_CONS (including autoboxed Number objects) "?.equals(objectExp)" --> foo(bar), objectVar, OBJ_CONST (allows objectVar to be null) "objectExp.equals(?)" --> foo(bar), objectVar, OBJ_CONST (allows ? to be null) "stringExp.equalsIgnoreCase(?)" --> string(bar), stringVar, STRING_CONST, "litteral" Examples for "expression1.. [booleanOperator ]expression2" and mixed : switch (stringExp) { case == STRING_CONST1 : // compare for identity {...} case STRING_CONST2 : // compare for equality {...} case STRING_CONST3.equals(?) : // compare for equality, avoiding NPE {...} case STRING_CONST4.equalsIgnoreCase(?) : // compare for equality ignoring case {...} case ?.subString(?.indexOf(STRING_CONST5)).startsWith(STRING_CONST6) : // sophisticated {...} default: {...} } switch (primitiveExp) { case == CONST1 : // compare for equality {...} case CONST2 : // compare for equality {...} case myList.get(3) : // autoboxing {...} case > CONST3 : // compare for greater than {...} case ? >= 10 && ? < 20 : // range check {...} ... } -Ulf From Ulf.Zibis at gmx.de Thu May 28 07:40:42 2009 From: Ulf.Zibis at gmx.de (Ulf Zibis) Date: Thu, 28 May 2009 16:40:42 +0200 Subject: Extend switch .. case statement for all types and simple expressions (2nd update) In-Reply-To: <49D14427.5070105@gmx.de> References: <49D14427.5070105@gmx.de> Message-ID: <4A1EA26A.8040802@gmx.de> I just want to see the switch..case construct serving as general purpose _n-way fork_ in program flow. IMHO it's a smart syntax providing perfect readability. Only for _2-way fork_ the if..else construct is smart syntax. Additionally if..else_if..else_if.. construct has the disadvantage of missing fall-through facility. I have rethought my proposal and come to more general syntax: Proposal for SYNTAX SPECIFICATION: switch (expression1 | booleanExpressionTemplate(?) | substitution_of_?) { case: [booleanOperator ]expression2 | substitution_of_? | booleanExpressionTemplate(?) {...} ... } if 'booleanOperator' is missing: - expression1 is primitive value --> execute: expression1 == expression2 - expression1 is reference --> execute: expression1.equals(expression2) (sophisticated special case to aviod potential NPE): - expression1 is reference and expression2 is CONSTANT --> execute: expression2.equals(expression1) Examples for booleanExpressionTemplate(?) and it's possible substitution: "Math.sin(?) > 0.5" --> foo(bar), floatVar, intVar, PRIM_CONST (including autoboxed Number objects) "? >= 10 && ? < 20" --> foo(bar), primitiveVar, PRIM_CONS (including autoboxed Number objects) "?.equals(objectExp)" --> foo(bar), objectVar, OBJ_CONST (allows objectVar to be null) "objectExp.equals(?)" --> foo(bar), objectVar, OBJ_CONST (allows ? to be null) "stringExp.equalsIgnoreCase(?)" --> string(bar), stringVar, STRING_CONST, "litteral" Examples for "expression1.. [booleanOperator ]expression2" and mixed : switch (stringExp) { case == STRING_CONST1 : // compare for identity {...} case STRING_CONST2 : // compare for equality {...} case STRING_CONST3.equals(?) : // compare for equality, avoiding NPE {...} case STRING_CONST4.equalsIgnoreCase(?) : // compare for equality ignoring case {...} case ?.subString(?.indexOf(STRING_CONST5)).startsWith(STRING_CONST6) : // sophisticated {...} default: {...} } switch (primitiveExp) { case == CONST1 : // compare for equality {...} case CONST2 : // compare for equality {...} case myList.get(3) : // autoboxing {...} case > CONST3 : // compare for greater than {...} case ? >= 10 && ? < 20 : // range check {...} ... } -Ulf Am 31.03.2009 00:13, Ulf Zibis schrieb: > AUTHOR(S): Ulf Zibis, Cologne, Germany > > OVERVIEW > FEATURE SUMMARY: Extend switch .. case statement for all types and simple expressions. > MAJOR ADVANTAGE: > - Increases readability of source in concurrence to if .. else if .. else syntax. > - Sophisticated jumps. > - maybe in some cases javac and hotspot has chance to compute better optimized code. > MAJOR BENEFIT: > Stop some programmers escaping to some modern scripting language. > MAJOR DISADVANTAGE: > Programmers from other languages, especially C, may be confused about such rich syntax. > > EXAMPLES > SIMPLE EXAMPLE: > (1): > switch( myObject) { > case CONSTANT1 : doSomething(); break; > case CONSTANT2 : doSomethingElse(); break; > default : doSomethingDefault(); > } > (2): > switch( myString) { > case equals("red") : stop(); break; > case equals("green") : go(); break; > default : openYourEyesForCrossingTraffic(); > } > (3): > switch( myString) { > case equalsIgnoreCase("RED") : sureStop(); break; > case equalsIgnoreCase("GREEN") : sureGo(); break; > default : beAwareOfPoliceWachtingYou(); > } > > ADVANCED EXAMPLE: > (4): > switch( primitiveInt) { > case == 10 : doOnlyIf10(); // alternative syntax for 'case 10:' > case < 10 : > case >= 20 : break; > default : doOnlyInRange(); > } > (5): > switch( primitiveInt) { > case (>= 10 && < 20) : doOnlyInRange(); > default : throw new Exception("Out of range"); > } > (6): > switch( myString) { > case contains("foo") : doSomething(); break; > case regionMatches(true, 2, otherString, 4, 6) : doSomethingElse(); break; > default : doSomethingDefault(); > } > (7): > switch( myString.equals()) { // alternative: myString.equals(..) > case "foo" : foo(); break; > case "bar" : bar(); break; > default : dontCare(); > } > (8): > switch( className.startsWith("String", ..)) { // alternative: className.startsWith("String", ?) > case 0 : doForSimpleName(); break; > case 9 : doForFullName(); break; > default : canNotDecide(); > } > (9): > switch( anyObjectOrPrimitive instanceof) { // note, that casting is solved implicit > case boolean, byte, ... float : break; // Don't do anything > case double : forDouble(anyObjectOrPrimitive); > case HashMap : > case TreeMap : forPlattformMap(anyObjectOrPrimitive); break; > case Map : forOtherMap(anyObjectOrPrimitive); break; > default : forObject(anyObjectOrPrimitive); > } > (10): (minimizee chance for NPE) > switch( .equals(myString)) { // alternative: ?.equals(myString) > case "foo" : foo(); break; > case "bar" : bar(); break; > default : dontCare(); > } > (11): > switch( some_lethargic_function_we_cant_call_much().equals(..) ) { > case "this": > case "that": this_or_that(); break; > case "bigjump": big(); // fall > case "jump": jump(); break; > case "secondlastchance": > case "lastchance": last_chance(); break; > default: do_default(); > } > .. as replacement for: > String sSomeString = some_lethargic_function_we_cant_call_much(); > if( sSomeString.equals( "this" ) || sSomeString.equals( "that" ) ) > this_or_that(); > else if( sSomeString.equals( "jump" ) || sSomeString.equals( "bigjump" ) ) > { > if( sSomeString.equals( "bigjump" ) ) > big(); > jump(); > } else if( sSomeString.equals( "secondlastchance" ) || > sSomeString.equals( "lastchance" ) ) > { > last_chance(); > } else do_default(); > > ALTERNATIVES: > (12): > switch( myString) { // note the '.', I personally would prefer this alternative! > case .equals("red") : stop(); break; > case .equals("green") : go(); break; > default : openYourEyesForCrossingTraffic(); > } > (13): > switch( primitiveInt) { // note the '.' > case (. >= 10 && . < 20) : doOnlyInRange(); > // case (? >= 10 && ? < 20) : doOnlyInRange(); // alternative > default : throw new Exception("Out of range"); > } > > > DETAILS > SPECIFICATION: > The new syntax should be interpreted as > switch ( leftExpressionPart ) { > case rightExpressionPart1 : > case rightExpressionPart2 : > ... > default : > } > The result of entire expression should be boolean type. > There is shortcut for: > leftExpressionPart: intVariable > rightExpressionPart: == intLiteral > (the '==' could be ommitted.) > > COMPILATION: > Compiler could first pre-compile to appropriate if..then..else syntax. > Bytecode would not be affected, but in special cases it could be more compact, if noted > pre-compilation would be replaced by sophisticated optimization. > TESTING: > Compiler byte-code results for new syntax should be same than from equivalent hand-coded legacy > if..then..else syntax > . Exception: sophisticated optimization. > LIBRARY SUPPORT: No supporting libraries are needed for the feature? > REFLECTIVE APIS: There should not be any affection to reflection API. > OTHER CHANGES: No. > MIGRATION: > No refactoring is needed to stay compatible. > > COMPATIBILITY > BREAKING CHANGES: > No previously valid programs are now invalid. > ... but ATTENTION: > If proposals from some other guys regarding "Strings in switch" would be taken into JDK 7, there > won't be any compatible way to implement my more general proposal in future version of JDK !!! > --> So switch .. case statement should compare for IDENTITY if not syntactically determined otherwise. > --> compare for EQUALITY would also break semantic of existing switch .. case statement. > Another reason, why I'm against comparing for equality by default syntax, is, that it is good > practice to use String constants instead of widely spreaded String literals with same signature for > numerous reasons (performance, error prone, ...). The "only-for-String" syntax would lead > programmers to stay on widely spreaded String literals of same value. > If constant is not available for switch variable (e.g. if read from stream), variable could be > internalized before, so it's instance becomes identical to the existing constant. > ===>> If just "Strings in switch" is taken over for JDK 7, there is NO NEED, to compare for equality. > EXISTING PROGRAMS: > Source and class files of earlier platform versions interact with the feature without any notice. > > REFERENCES > http://mail.openjdk.java.net/pipermail/coin-dev/2009-February/000001.html > http://mail.openjdk.java.net/pipermail/coin-dev/2009-March/000213.html > http://mail.openjdk.java.net/pipermail/coin-dev/2009-March/000855.html > http://mail.openjdk.java.net/pipermail/coin-dev/2009-March/001089.html > http://forums.java.net/jive/thread.jspa?messageID=27781沅 > http://forums.java.net/jive/thread.jspa?messageID=15769㶙 > http://forums.java.net/jive/thread.jspa?messageID=27773汽 > http://forums.java.net/jive/thread.jspa?messageID=11393ⲁ > http://lasu2string.blogspot.com/2008/12/string-switch-small-language-changes-on.html > EXISTING BUGS: > http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=5012262 > URL FOR PROTOTYPE (optional): > > > > > > > > From neal at gafter.com Thu May 28 08:32:25 2009 From: neal at gafter.com (Neal Gafter) Date: Thu, 28 May 2009 08:32:25 -0700 Subject: Extend switch .. case statement for Object types and simple expressions In-Reply-To: <4A1E406A.8070904@gmx.de> References: <49D10FE6.3000404@gmx.de> <4A133644.40104@sun.com> <4A1E406A.8070904@gmx.de> Message-ID: <15e8b9d20905280832x4e4f7673h2361b5942e3e6ae7@mail.gmail.com> Ulf- I don't think Joe is complaining about examples. Examples are nice for motivating and teaching language changes, but not for fully understanding them. Your specification is very short and doesn't give enough detail to understand or evaluate the proposal. You suggest "stopping" where the changes seem too radical, but the specification doesn't appear to have any separable parts. Regards, Neal On Thu, May 28, 2009 at 12:42 AM, Ulf Zibis wrote: > again, can you please be more specific, which examples are confusing for > you, > and in which way? > > > Am 20.05.2009 00:44, Joe Darcy schrieb: > > I'm also a bit confused over what exactly is being proposed. > From Joe.Darcy at Sun.COM Thu May 28 12:36:27 2009 From: Joe.Darcy at Sun.COM (Joseph D. Darcy) Date: Thu, 28 May 2009 12:36:27 -0700 Subject: Extend switch .. case statement for Object types and simple expressions In-Reply-To: <15e8b9d20905280832x4e4f7673h2361b5942e3e6ae7@mail.gmail.com> References: <49D10FE6.3000404@gmx.de> <4A133644.40104@sun.com> <4A1E406A.8070904@gmx.de> <15e8b9d20905280832x4e4f7673h2361b5942e3e6ae7@mail.gmail.com> Message-ID: <4A1EE7BB.9020201@sun.com> Yes, the specification section essentially fails to explain what the construct is intended to mean, which alone is grounds for disqualification. In any case (pun intended), since this proposal was not selected for further consideration continued discussion of it in this forum is superfluous. -Joe Neal Gafter wrote: > Ulf- > > I don't think Joe is complaining about examples. Examples are nice > for motivating and teaching language changes, but not for fully > understanding them. Your specification is very short and doesn't give > enough detail to understand or evaluate the proposal. You suggest > "stopping" where the changes seem too radical, but the specification > doesn't appear to have any separable parts. > > Regards, > Neal > > On Thu, May 28, 2009 at 12:42 AM, Ulf Zibis > wrote: > > again, can you please be more specific, which examples are > confusing for you, > and in which way? > > > Am 20.05.2009 00:44, Joe Darcy schrieb: > > I'm also a bit confused over what exactly is being proposed. > > From mthornton at optrak.co.uk Thu May 28 13:35:13 2009 From: mthornton at optrak.co.uk (Mark Thornton) Date: Thu, 28 May 2009 21:35:13 +0100 Subject: 64-bit array functionality implemented via libraries? In-Reply-To: <4A1DC452.1080807@sun.com> References: <4A1DC452.1080807@sun.com> Message-ID: <4A1EF581.9090202@optrak.co.uk> Joe Darcy wrote: > Hello. > > As another point in the design space, assuming indexing access syntax is > available for user-defined types and the existence of collection > literals, I'd like to see what implementing 64-bit array functionality > via libraries would look like. > Not quite sure what you are looking for here as the public interface seems fairly obvious apart from minor details. public abstract class LargeArray implements Cloneable, Serializable { public final long length; protected LargeArray(long length) {...} public T clone(); } public class LargeObjectArray extends LargeArray> { public LargeObjectArray(long length) {...} public E get(long index) {...} public void set(long index, E value) {...} } public class LargeIntArray extends LargeArray { public LargeIntArray(long length) {...} public int get(long index) {...} public void set(long index, int value) {...} } // etc for the other primitives However this can only be used with the proposed [] access, if that is not based on the existing List/Collection interfaces as they have integer rather than long size and index types. Mark Thornton From Joe.Darcy at Sun.COM Thu May 28 13:42:23 2009 From: Joe.Darcy at Sun.COM (Joseph D. Darcy) Date: Thu, 28 May 2009 13:42:23 -0700 Subject: Thoughts on unified integer literal improvements In-Reply-To: <4A1E6A99.7090801@paradise.net.nz> References: <4A1DC533.2060202@sun.com> <4A1E6A99.7090801@paradise.net.nz> Message-ID: <4A1EF72F.2080303@sun.com> Bruce Chapman wrote: > Joe Darcy wrote: >> Hello. >> >> On the set of improved integer literal features, I think combining >> the underscores as separators and binary literals is straightforward >> given separately correct grammars for each change. >> >> As an alternate to "y" and "s" suffices, I suggesting considering a >> "u" suffix to mean unsigned. Literals with a trailing "u" would have >> type int; widening conversions of such literals would 0 extend and >> narrowing conversions would range check on the width of set bits. >> For example, >> > Doesn't that idea has some problems introducing it into the language > and type system? I don't think the problems are insurmountable :-) There would need to be new rules for primitive widening and narrowing conversion and on how "unsignedness" propagated. For example, "0x2u + 0x1u" would probably *not* be considered unsigned, just a plain literal. > > if it is "Literals with a trailing "u" would have type int;" then the > type is int, and the value just the same as for when there was no > suffix. If the widening and narrowing changes behaviour for these > literals only, how can this be done unless these literals are of some > new type, or the type system knows about the notation used to declare > the value? The trailing "u" would trigger some new rules, but fundamentally they are just plain old int values once they are no longer considered a literal. > And if we can have unsigned ints surreptitiously like this, then lets > have unsigned byte as well, and unsigned byte arrays. Yeeha - now I'm > really happy. :) > > > > But taking that idea, and combining it with the autosizing integer > literal proposal such that we use the "u" suffix to denote autosizing > (rather than only having it work for hex literals with the 0h prefix), > now that might fly, and could work for decimal and octal and binary as > well. > > I'll have to do some more thinking thru on this, and now is not an > ideal time for me. > >> byte b = 0xABu // equivalent to (0xAB & 0xFF) > do you mean // equivalent to (byte) 0xAB ? (because (0xAB & 0xFF) is > already equivalent to 0xAB) >> >> long ell = 0xFFFFFFFFu; // A positive long value > but > int hell = 0xFFFFFFFFu; // -1 ??? Correct -- since "u" denoted an unsigned value, promoting an unsigned literal to a wider format 0 extends rather than sign extends. >> >> I think this approach has some advantages over the "y" suffix; in >> particular I think it gives more desirable behavior in cases like this: >> >> byte b = 0xFFy // a negative byte value >> byte b = 0xFFu // also a negative byte value >> >> >> short s = 0xFFy // a negative short value, -128; >> // byte value is signed extended >> short s = 0xFFu // a positive short value, +127 > do you mean // a positive short value, +255? Yes, I meant +255. -Joe From Ulf.Zibis at gmx.de Fri May 29 08:33:42 2009 From: Ulf.Zibis at gmx.de (Ulf Zibis) Date: Fri, 29 May 2009 17:33:42 +0200 Subject: Extend switch .. case statement for Object types and simple expressions In-Reply-To: <4A1EE7BB.9020201@sun.com> References: <49D10FE6.3000404@gmx.de> <4A133644.40104@sun.com> <4A1E406A.8070904@gmx.de> <15e8b9d20905280832x4e4f7673h2361b5942e3e6ae7@mail.gmail.com> <4A1EE7BB.9020201@sun.com> Message-ID: <4A200056.4050603@gmx.de> Am 28.05.2009 21:36, Joseph D. Darcy schrieb: > Yes, the specification section essentially fails to explain what the > construct is intended to mean, which alone is grounds for > disqualification. In any case (pun intended), since this proposal was > not selected for further consideration continued discussion of it in > this forum is superfluous. Thanks for explaining this. Hopefully I've learned enough from this round, and can provide better proposal next coin project. Yes, it's too late. > > -Joe > > Neal Gafter wrote: >> Ulf- >> >> I don't think Joe is complaining about examples. Examples are nice >> for motivating and teaching language changes, but not for fully >> understanding them. Your specification is very short and doesn't >> give enough detail to understand or evaluate the proposal. You >> suggest "stopping" where the changes seem too radical, but the >> specification doesn't appear to have any separable parts. I meant this in referring to the given examples. Additionally, it's hard for me to understand, what it may be, which is confusing. -Ulf >> >> Regards, >> Neal >> >> On Thu, May 28, 2009 at 12:42 AM, Ulf Zibis > > wrote: >> >> again, can you please be more specific, which examples are >> confusing for you, >> and in which way? >> >> >> Am 20.05.2009 00:44, Joe Darcy schrieb: >> > I'm also a bit confused over what exactly is being proposed. >> >> > >