Project Coin got its name because it is about making "small change"(s) to the Java programming language for JDK 7. Sun's Joe Darcy has been leading the project. In his blog post, Project Coin: The Final Five (Or So), has announced which small changes will actually make it into JDK 7. Here's the list:
Currently in Java you must manage the release of non-memory finite resources manually with try-finally. This change will make that more concise and less error prone. For example, instead of this:
Improved type inference for generic instance creation (full proposal)
Currently in Java you often have to repeat yourself when instantiating a generic type and placing it in a variable. This change would let you do the same thing more concisely. For example, instead of this:
Map<String, List<String>> anagrams = new HashMap<String, List<String>>();
You'll be able to write this:
Map<String, List<String>> anagrams = new HashMap<>();
Currently in Java you get a compiler warning if you try to invoke a varargs method with a non-reifiable varargs type. This change will move the warning from the call site to the method declaration.
An omnibus proposal for better integral literals
This change combines two proposals that will add new ways to write integer literals, Binary literals and Underscores in numbers. The first proposal will allow you to write binary literals like 0b101 or 0B101. The second proposal will enable you to place underscores in longer numbers to make them more readable. For example, here's the maximum long written with underscores: 9_223_372_036_854_775_807L.
Language support for collections
This item combines two proposals, Collection literals and Indexing access syntax for Lists and Maps. The first proposal would make expressions that initialize new Lists, Sets, and Maps more concise. For example, instead of this way of initializing an immutable List:
JSR 292 is focused on supporting dynamically typed languages on the Java Platform. This proposal changes the Java language so that these features are available from Java. For example, this proposal would allow you to dynamically invoke any method on a variable of type java.dyn.Dynamic. This will always compile. At runtime, if the method exists, the invocation will succeed:
Dynamic x = (any type of expression can go here);
Object y = x.foo("ABC").bar(42).baz();
I wonder why they didn't consider Pythons with-statement semantics [1] when they designed resource management, at least among the alternatives, which is both more general and more flexible.
The idea of having better support for declaring data structures is great, particularly for Maps, but I wonder how elegant the implementation will turn out to be.
For instance, I get why the { foo: bar } syntax returns a unmodifiable map (sane default given that you're not giving the programmer a chance to pick the Map implementation) but if you want a modifiable one, will this work?
In general, I'm a bit uncomfortable with these cases where the meaning of an expression being dependent on where it's declared. For instance, in java currently, you can use the {} syntax for arrays without the new MyType[] in front of it if it's an assignment statement, but not, say, when inlining the array in a method call: foo({1, 2, 3}, "bar");
The {} syntax is now really being overloaded, which I find somewhat confusing and inelegant.
"Language support for collections" says it combines collection literals and list/map indexing/access proposals -- yet the proposal only seems to include the former capability (perhaps with syntax garnered from the latter?).
Automatic resource management leaves it unclear as to which interface(s) will be handled. Closeable presumably, but will there be any others?
Finally, I can see no justification for excluding "Improved Exception Handling for Java". Neil's proposal was well thought out, clearly helpful, and seemed like an automatic for inclusion. There are certainly lots of cases where I miss this capability today.
The type inference is backwards. Instead of deducing the type of a variable from an expression, the type of the expression is deduced by the type of the variable.
Also I prefer Lombok's @Cleanup approach to the automatic resource management specified here.
With Lombok you simply have
@Cleanup BufferedReader br = new BufferedReader(new FileReader(path));
That's it. This is shorter and simpler and (finally) gives C++-destructor-like resource management in that cleanup is automatic at the end of the variable's scope.
Lombok also allows you to specify a cleanup method other than "close" as part of the annotation.
I'm not saying that annotations are necessarily the way to achieve this, but the ability to say "hey, clean this thing up automatically at the end of the scope" in one place without adding additional {} bracing is pretty nice.
I suppose the {} bracing makes the cleanup ordering clear, but this could clearly behave like a stack (last @Cleanup variable in a given scope gets cleaned up first, etc) and *optionally* be clarified via {} bracing.
> Automatic resource management leaves it unclear as to > which interface(s) will be handled. Closeable presumably, > but will there be any others?
As I read it there is a new interface that is being introduced: Disposable<E> that this feature will depend upon similar to how the for(:) loop depends on Iterable<E>.
Map<String, List<String>> anagrams = new
> HashMap<>();
Really? That is bass ackwards. > > This is much more intuitive: >
Map<> anagrams = new HashMap<String,
> List<String>>();
Or better: >
var anagrams = new HashMap<String,
> List<String>>();
Right. Why limit this only to instance creation? The rhs of a variable assignment is going to be a method invocation a lot (most?) of the time, and this inference doesn't do anything to help in that case.
I guess if you believe strongly in manifest typing and that the declaration should always be there no matter what, then this approach makes sense.
> Right. Why limit this only to instance creation? The rhs > of a variable assignment is going to be a method > invocation a lot (most?) of the time, and this inference > doesn't do anything to help in that case. > > I guess if you believe strongly in manifest typing and > that the declaration should always be there no matter > what, then this approach makes sense.
The issue with leaving the type off the right hand side is that you quickly have no idea of any types at all.
Pretty soon you have a whole mess of code like:
var foo = obj1.bar(); var baz = obj2.wacky(foo); ...
What's the type of anything? Nobody knows unless you have everything loaded into an IDE and even then you can't tell until you float the mouse over each var to ask it.
Worse, the type of foo and bar can now change without your knowledge. Some other developer changes bar() and wacky() to return a different return type, foo and baz change as well *silently* and your code is now doing something different without you ever being the wiser. Some may argue that's a good thing, but it can lead to silent but deadly consequences. Dealing with this explicitly up front by having the expected type asserted in the calling code is preferable.
Overall, Java has always valued local clarity and type assertion. I don't see changing that now. If you want this to change use JavaScript, Scala, or Groovy. On the other hand, repeating types on rhs and lhs when they're the same is ludicrous, which is what the <> proposal addresses.
> Pretty soon you have a whole mess of code like: > > var foo = obj1.bar(); > var baz = obj2.wacky(foo); > ... > > What's the type of anything? Nobody knows unless you have > everything loaded into an IDE and even then you can't tell > until you float the mouse over each var to ask it.
I dunno, man. If someone writes
WackyManifestType foo = obj1.bar().wacky(foo);
I typically don't find myself agonizing over the type of bar().
Knowing the type of something, when you aren't in an IDE, seems like a fairly limited bit of knowledge, unless you also know all the methods on that type. I've got a terrible memory, so it's far more important to me that I have code completion after I hit '.' when I'm coding than I know what the type of the preceding expression is. YMMV.
> Worse, the type of foo and bar can now change without your > knowledge. Some other developer changes bar() and wacky() > to return a different return type, foo and baz change as > well *silently* and your code is now doing something > different without you ever being the wiser. Some may > argue that's a good thing, but it can lead to silent but > deadly consequences. Dealing with this explicitly up > front by having the expected type asserted in the calling > code is preferable.
Not to me, it isn't. It makes refactors far more violent than necessary. Change the return type of a method from, say, List to Set and everyone who had the misfortune of declaring a local variable of type List when calling that method needs to be updated, even though the change is almost certainly innocuous.
Deadly consequences? Really? I'd like to see a real world example, rather than a hypothetical case. We've been using chained methods for a decade now. Does anyone have an example of a horrible bug that crept in because someone changed the return type of an interior method in a method chain?
This line of justification for manifest typing strikes me like the justification of java wildcards, which solve a hypothetical problem, writing a bad value to a generic location, that we just didn't see a lot of in pre-generic code. (Did you get a lot of ClassCastExceptions when working with pre-generics Collections?) Similarly, people have been chaining methods together for years now without declaring types and everything has worked fine. Why should local variables be so special?
> Overall, Java has always valued local clarity and type > assertion. I don't see changing that now. If you want > this to change use JavaScript, Scala, or Groovy. On the > other hand, repeating types on rhs and lhs when they're > the same is ludicrous, which is what the <> proposal > addresses.
I can't argue with that. Java is clearly a manifest typing based language, now and forever.
Beyond Scala there is always C#, but I'd rather use Gosu. ;)
The core disagreement here is probably around the relative importance of various goals of a type system. One goal is to provide the maximum amount of type safety and verification for your code. Another goal is to enable tools such as code completion and refactoring in order to make developers more productive.
I think the second goal is the most important. The first goal, while certainly useful (I would hate to do a major refactor in a dynamic language,) is less important to me and can be sacrificed judiciously in the name of programmer convenience and simplicity. Part of my willingness to sacrifice the first goal comes from my general impression that static verification is an inherently limited tool and thus should be taken seriously... but not too seriously.
It's a judgment call, to be sure, and I see the other side of the argument, but that's my take.
> Right. Why limit this only to instance creation? The rhs > of a variable assignment is going to be a method > invocation a lot (most?) of the time, and this inference > doesn't do anything to help in that case.
Java already can do type inference for method calls. The Google Collections API leverages this in static factory methods such as:
> > Right. Why limit this only to instance creation? The > rhs > > of a variable assignment is going to be a method > > invocation a lot (most?) of the time, and this > inference > > doesn't do anything to help in that case. > > Java already can do type inference for method calls. The > Google Collections API leverages this in static factory > methods such as: >
> > You can then just say Map<String, Integer> myMap = > Maps.newHashMap(); > > The idea of the improved type inference for generic > instance creation proposal is to make the same thing work > for constructors.
Right, but the method has to be generic. How many generic methods do you call per day? How many non-generic methods? How many constructors? How many generic constructors? My answers: few, lots, some, some. So #2 is the common case for me at least, and this proposal does nothing to help me out.
I can see the symmetry argument, but my point, and Fred Garvin's point, is why only limit your inference to a left-to-right mechanism, where manifest typing is still required? And your answer to that revolves around your opinion on the power-to-weight ratio of manifest typing of local variables.
> Right, but the method has to be generic. How many generic > methods do you call per day? How many non-generic > methods? How many constructors? How many generic > constructors? My answers: few, lots, some, some. So #2 > is the common case for me at least, and this proposal does > nothing to help me out.
Really? You don't think it's annoying to have to type the generic type twice? I'm often tempted to leave the constructor type off and add @SuppressWarnings("unchecked"). I use generic Maps a lists often.
> Really? You don't think it's annoying to have to type the > generic type twice? I'm often tempted to leave the > constructor type off and add > @SuppressWarnings("unchecked"). I use generic Maps a > lists often.
It isn't just the typing but the fact that the line disappears off the right hand side of the screen.
Flat View: This topic has 15 replies
on 2 pages
[
12
|
»
]