 |
Evolving the Java Language
Posted by kgh on September 13, 2004 at 02:33 PM | Comments (77)
We're starting to think about potential language features
for Dolphin (7.0). So I've been reflecting a little on the
principles that James so brilliantly infused into the original
Java language and which we've tried to preserve as it evolves.
The big core principle is around making programs easy to understand.
Java is focused on being a powerful but simple language, easy to read,
with a consistent clear meaning. It is more important that Java programs be easy to read than to write.
That may sound trivial, but it isn't.
Lessons from C++
Looking back at C++ there were a whole set of factors at work that
made reading source code difficult:
Many project teams working with C++ adopted conventions
to create simpler subsets of C++. "We'll use this, but won't
use that." This helped. However, it lead to the problem
of language fragmentation, where different teams adopted
different language subsets and then got cognitive dissonance
when they read one another's source.
The Java approach
The Java language took a very different approach. Java tries
to be an unobtrusive language. As a developer, you should
be able to focus on what your application code is doing and on
how it interacts with libraries.
Code should do what it seems to do - people shouldn't need
to worry about clever language side effects or about what "=" means this week.
This focus on clarity and on readability has affected
Java in many ways. It has led to a focus on keeping the
language simple and clear. It has led to relatively
conservative uses of syntax and minimized the places where
user defined code can modify base semantics.
As another part of this principle, there is also a strong focus on having
"one standard language" which means the same thing everywhere.
It should be possible for a Java
developer to start reading a chunk of new Java source code and to
be able to rely on a consistent set of language semantics.
I shouldn't have to worry about different vendors
implementing language features in different ways.
And I really shouldn't have to read your compiler flags in order
to understand what your source code will do.
So part of our investment in the Java language includes a
strong focus on both a very precise specification (currently
driven by Sun's esteemed
Computational Theologist,
Gilad Bracha)
and also an extensive language compatibility test suite.
Language updates in Tiger
Now principles are good, but so are pragmatics. If we
stuck too rigorously to our principles, we'd probably
never dare make any changes to the language. It is
natural for things to evolve, and we want to be able
to make developers more productive, within the spirit
of the language. But we are also very
conscious that adding individually useful features
may slowly undermine the deep values of the language.
A lot of thought went into the Tiger language features.
We reviewed scores of potential language
changes before settling on the small set that made
it into Tiger.
There is always a risk in any change, but I think the
Tiger features will help developers without disrupting
their ability to understand Java code.
- Generics are clearly a major change which add important
new type systems ideas. But they provide a deep benefit
in improved source readability (you can see what specific
types are being used, you don't have to guess) and in improved
type checking, which is a core Java virtue.
- I'm a big fan of both the extended for loop semantics and
the auto-boxing and unboxing features. At first glance
they run the risk of heading into the C++ quagmire of
user defined side effects. But in reality, they are both
tightly bounded and run little risk of surprising developers.
And they do remove some common drudgery.
- JSR-175 (Metadata Annotations) is one of the biggest
opportunities and one of the biggest risks in Tiger. It adds
a great deal of expressive power. It defines explicit
language support for a style of declarative programming
which was previously addressed through scattered ad-hoc mechanisms
(such as JavaBeans method naming conventions or marker interfaces
or EJB deployment descriptors).
By promoting this declarative programming style into the
language we hope to improve overall readability. We've also
tried to define clear rules for what annotations can and
can not do, to minimize the risks of weird side effects.
For Dolphin, as for Tiger, a lot of people both inside
and outside of Sun will be involved in reviewing any language change
proposals. The detailed designs will be handled through the JCP.
But my suspicion is that
we'll probably continue to stay very
conservative on changes, as each little change also
carries its little wad of additional complexity.
We're unlikely to add
a macro preprocessor (sorry) or any general form of operator
overloading, or full-blown AOP, or any other mechanism for redefining and obscuring core semantics.
But we will look for new language ideas that help developers
with common problems. For example, one area I'm personally interested
in is some kind of "friends" import mechanism to make large
multi-package projects easier to manage.
One platform, many languages
One last thought: the Java language is only one language
for the Java Platform. It has one particular set of values,
which seem to be particularly good for creating large,
maintainable programs.
But different developers want different things at different
times. It's OK to have multiple languages, each of which
is well designed for a specific kind of programming.
When I'm doing a quick Sunday morning hack, sometimes
I want something more scripty, and I don't want to have
to track all those checked exceptions.
So I'd like to see more use of alternate languages on top
of the Java platform, with different goals and styles.
For example, I was really pleased to see the "Groovy" language
brought into the JCP. It is designed as a new
Java platform language,
but with its own goals and design center that are very
different from the classic Java language. Happiness!
My personal suspicion is that the Java language is good
for at least another 20 to 30 years, if we are careful in managing its
evolution. But I also expect that over time new research ideas will emerge and
slowly gain acceptance and at some point we'll want a new synthesis
that will create a great new simple language. And of course
we'll want to make sure that sparkling new language runs on the Java
Platform!
- Graham
Bookmark blog post: del.icio.us Digg DZone Furl Reddit
Comments
Comments are listed in date ascending order (oldest first) | Post Comment
-
No nulls allowed
A very useful feature would be to explicitly saying whether a variable can be assigned a null value or not. Since this feature must be backwards compatible, a new syntax for non-null types should be created, something like:
public void myMethod(String- s) {
//no NPE can happen while manipulating s
}
I am not saying - must be used for this, but I am just promoting an idea here. This could lead to safer code and, even better, fail-safe code since the compiler would be able to say you were breaking your own rules. Please do consider this.
Posted by: mister__m on September 13, 2004 at 04:07 PM
-
friend imports
If this "friend"-import is, what I think it is, I would be very happy. I often have API-projects with hundreds of classes, where only a few classes must be known by clients to use the API. Normally you would only make these classes public and the remainder package-private. But I also want to manage my classes in some usefull packages and sub-packages. This leads to the necessarity to declare some classes public, even though they should not be used by clients of the API.
Posted by: fatihc on September 13, 2004 at 04:36 PM
-
No nulls allowed
the "no null" compile time check seems like a fantastic idea. It has my backing straight away. NullPointerExceptions are one of the most evil things about the Java language and for the most part are also one of the most pointless exceptions. The sort of change sugggested above would sort it straight away and would also require no change to the actual runtime, just the compiler. Just as the throws clause of methods is only used in compile time checking, so should this flag be. If it was subverted after compile time, then NullPointer would result as normal. Doing this would not bring any performance drops into the language and would make development so much easier.
One other thing I would really like to see in Java is an idea from JavaScript: the "with" keyword. It modifies the scope of the code in encompasses to save the typists fingers. Observe:
Java:
someObject.doMethod1(blah,blah,blah);
someObject.doMethod2(yadda,yadda);
a=b+5;
someObject.doMethod3(a,9);
someObject...........
Javascript:
with (someObject) {
doMethod1(blah,blah,blah);
doMethod2(yadda,yadda);
a=b+5;
doMethod3(a,9);
}
I know it makes referring to some objects refs. weird since inside the with block you would then have to use the "this" keyword explicitly, but again this is something that needs only compiler changes, not JVM changes, since all it needs to do is insert the object name during compilation. Just an idea.
Posted by: scurry on September 13, 2004 at 05:02 PM
-
friend imports
Sorry my original post got snipped. Here comes the remainder:
If you could daclare a class package-private and though say "I am the friend of class X in package Y, so he can import and use me", that would help in the situations I described above.
Posted by: fatihc on September 13, 2004 at 05:12 PM
-
No nulls allowed
Michael,
I don't get what you mean by this being a compile-time issue. Do you mean the compiler would automatically generate a code like the above?
if ( s == null ) throw new IllegalArgumentException( "parameter s cannot be null" )
If that's what you mean, I think the same effect could be achieved using plain annotations. In fact, you'd be referring to just a particular type of pre-condition, while annotations could be more generic (though this special 'hack' would cover the most common pre-condition).
-- Felipe
Posted by: felipeal on September 13, 2004 at 07:22 PM
-
No nulls allowed
Something like this?
Posted by: coxcu on September 13, 2004 at 08:17 PM
-
More languages for the JVM
More well supported languages are needed if the JVM is going to really outlast Java. There are a wealth of languages for the JVM, but nothing has anywhere near the support and success of Java.
Personally, I would love to see Sun support Jython and C for the JVM. My "day job" is enhancing a huge application that is written in Java, C, Jython, and Python. Right now, that app is only being supported on Windows--even though all of the C code was originally written for Unix. A good C compiler for the JVM would go a long way towards moving such apps off of native platforms and fully onto Java.
There is a huge amount of legacy C, Fortran, and even more (shudder) COBOL.
Posted by: coxcu on September 13, 2004 at 08:47 PM
-
No nulls allowed
I'd love to get rid of having to check for nulls, but...
String- s = someObject.getSomeString();
myMethod(s);
getSomeString would be required to return String- instead of String, right? But what if getSomeString was written before this new feature was added to Java, or the implementor of the method just didn't think of adding the non-null predicate (even if the method might just consist of return "some string")?
That's the same problem as with the const keyword in C++: it would be great if EVERY programmer would define ALL stuff that's not intended to be changed as const. But if just one person forgets to do so once, the whole system might become corrupted.
Therefore, I think it is better to use something like AOP for this kind of precondition checking. This won't help to get rid of NullPointerExceptions since it is applied at runtime, but at least you don't have to type the 'is null' check in every method.
Posted by: el_barto on September 14, 2004 at 01:18 AM
-
design by contract
I'd like to see more support for design by contract (that old Eiffel construct). I remember reading that James Gosling actually included this in Oak, the precursor to Java, but it was subsequently dropped due to time pressure.
Currently, we have assert() which works OK for pre and post-conditions (although a method-level construct for describing it would be nice sugar), but we don't have support for class invariants.
Ideally they'd be integrated into the existing assertion framework so we could enable and disable them at runtime and at a nice level of granularity.
One other thing - perhaps by Java 7.0 we will finally have a standard way to do user input masking at the console?! And I don't mean by using a native library or a buffer-flush thread!! I'm referring to that old workhorse of a bug report, #4050435, which has been open since May 7th, 1997.
cheers, mike
Posted by: mikeburke on September 14, 2004 at 03:10 AM
-
design by contract
apologies for the 's but there's no preview button for submitting posts..
Posted by: mikeburke on September 14, 2004 at 03:11 AM
-
No nulls allowed
For this to work at compile time, the non-null constraint would have to cascade upwards like an uncaught exception.
Consider if foo(s) calls bar(s not null) then the compiler does not know if s is null. Should it force foo to be not null also? And the callers of foo?
Posted by: arae on September 14, 2004 at 03:54 AM
-
Few ideas
The "with" syntax is nice, and not too different to static imports (or any kind of imports really). As long as the compiler flags any ambiguities...
Closures and/or method delegates would be nice.
Properties too, would be able to clarify things. Such as :
public String familyName {
get {
return _familyName != null ? _familyName : "";
}
set(String arg) {
if (arg != null) _familyName = arg.toUpperCase();
}
}
This is a simple example, so it might seem simple. But it's a nice way of exposing properties whilst sanity-checking them, implicitly firing event listeners, dropping the "set" to make it read-only, or whatever. It's certainly cleaner than "is", "get", and "set", which are OK sometimes, but when the property name is something plural or in a foreign language, it just looks contrived and ugly, and makes code less accessible to non-English developers.
Some people say "I don't want to execute a lot of code just by setting a property" : well, a "setter" method has the same risks. And setting a member variable directly can put an object into an unexpected state.
Posted by: chris_e_brown on September 14, 2004 at 07:06 AM
-
Working around checked exceptions
I have always been for checked exceptions (static checking as well as the throws clause) in Java, but feel we can improve the situation a tad.
My 2 bytes: how about a new unsafe code block that makes it possible to throw an exception without declaring it? Calling methods will not be required to catch/rethrow these but may possibly be provided a compile-time warning.
Posted by: nerddawg on September 14, 2004 at 07:23 AM
-
Minor things I'd like to see
I'd like to have a JARPATH option so I can refer to all the jars in a directory without having to build up a long classpath.
I'd like a way to set TCP options for all sockets, maybe via a system property. I have run into problems with firewalls dropping persistent connections where setting TCP_KEEPALIVE would fix the problem.
More generally, I'd like an easier way to create socket factories. You'd think that you could add socket behaviors by chaining factories together - your factory calls the default factory to create the socket, then you modify various options. Unfortunately, there is no getSocketImplFactory method. Also, you can't create instances of or extend PlainSocketImpl. I could live without this if I could set the TCP options, though.
Closures, like the ones in Ruby or Groovy would be really nice (I guess this isn't such a minor thing, though)
Posted by: thewookie on September 14, 2004 at 09:31 AM
-
Working around checked exceptions
Unless I miss you intent, I don't think the ease of use warrants a new keyword. These would be roughly equivalent, right?
unsafe {
// throw stuff here
}
and
try {
// throw stuff here
} catch (Throwable t) {
throw new RuntimeException(t);
}
Posted by: coxcu on September 14, 2004 at 09:44 AM
-
Minor things I'd like to see
Adding a JARPath option seems like a stopgap measure. A better solution would be to unify java and Webstart, so that java can launch apps using a JNLP configuration file.
Posted by: coxcu on September 14, 2004 at 09:49 AM
-
friend imports
This need really shows how languages interact with methodology. The introduction of inner classes effectively made packages bigger. The adoption of JUnit has effectively made packages much smaller.
Posted by: coxcu on September 14, 2004 at 09:54 AM
-
Help on closure
I know I am ignorant but maybe someone can tell me what I could do with closures, which I can not do with an interface plus anonymous class.
By the way I would like to see PHP ported to the Java Platform. It's just so widly used and easy for web-development.
Posted by: chrisichris on September 14, 2004 at 10:02 AM
-
Default values in arguments
How about default values in arguments?
Such as:
int add(int a, int b=2) {
return a + b;
}
Yes I know it could be overloaded as:
int add(int a, int b) {
return a + b;
}
int add(int a) {
return a + 2;
}
What do you think?
Posted by: javaonmymind on September 14, 2004 at 11:03 AM
-
Looks at the lessons from Smalltalk
From "Design Principles Behind Smalltalk" (
http://users.ipa.net/~dwighth/smalltalk/byte_aug81/design_principles_behind_smalltalk.html)
"Good Design: A system should be built with a minimum set of unchangeable parts; those parts should be as general as possible; and all parts of the system should be held in a uniform framework."
Java is complex an not uniform (int -> Integer, etc, and now has special cases for dealing with generics, static methods, etc). This is not good, only adds unnecesary complexy.
I like Smalltalk... but if I doesn't have another choice but to use Java.... I want more simplicity, for example:
- Who needs primitive types like int, byte, etc? I want first class Objects.
- Who needs generics... I want closures (like ST Blocks)
I don't know why Sun did a lot of work with the Self language just to forget it
Posted by: diegof79 on September 14, 2004 at 11:04 AM
-
No nulls allowed
This feature is already available today in the Nice programming language. It's a great feature. You write String when you want a non-null string, and ?String when a null is allowed. It works, and it works well. Nice also adds multimethods, design by contract, painless interaction with Java, and lots of other great features as well. Give it a try.
Posted by: xoltar on September 14, 2004 at 11:11 AM
-
Future of Java
Hi,
I'm a Java developer for more than 4 years now. I consider myself a "not-so-bad" developer.
As I was very exited with the new features of Java 5, I started a project (JVeez) to play with this new features.
My opinion has a bit evolved now.
For example, about the generics. I didn't read any real tutorial about them but as I though that this was in line with the focus on "ease and readability" I supposed that it would be straightforward.
Clearly, simple things are really done better : "List" is clearly more expressive thanthe simple "List". However, no later than yesterday I had to fight with the compiler to have something also simple work :
List list = ....
....
public void addPersons(List otherList)
{
list.addAll(otherList);
}
Thanks to a tutorial, I found a solution but I didn't fully understand it.
This leads me to wonder if generics will *always* improve readility. Not sure anymore.
Also, in order to prevent backward compatibility, the generics had to be constrained and as a result, we get something that is something not-that-easy to understand and that doesn't bring for example execution speed enhancement.
I still didn't play too much with auto-(un)boxing but I expect to find some cases where it will be more an annyance than a benefit.
I've seen Java evolving during the past years and become bigger and bigger, at the cost of inconsistencies appearing to preserve backward compatibility (for example, Enumeration and Iterator at the same time).
I have the very bad feeling that Java is becoming fat.
Personally, I would love to see a new version of Java starting from a clean base with better base APIs (like a new filesystem API, java.io.File is pretty limited). Anyway, I'm really wondering if this backward-compatibility is not already broken (try to run
Posted by: spetrucci on September 14, 2004 at 11:15 AM
-
Future of Java (complete version - sorry ;-)
Hi,
I'm a Java developer for more than 4 years now. I consider myself a "not-so-bad" developer.
As I was very exited with the new features of Java 5.0, I started a project (JVeez) to play with these new features.
My opinion has a bit evolved now.
For example, about the generics. I didn't read any real tutorial about it since I though that this was in line with the focus on "ease and readability". I supposed that it would be straightforward.
Clearly, simple things are really done better : "List" is clearly more expressive than the simple "List". However, no later than yesterday I had to fight with the compiler to have something also simple work :
List list = ....
....
public void addPersons(List otherList)
{
list.addAll(otherList);
}
Thanks to a tutorial, I found a solution but I admit that I didn't fully understand it.
This leads me to wonder if generics will *always* improve readility. Not sure anymore.
In order to prevent backward compatibility, the generics had to be constrained (compared to C# version for example) and as a result, we get something that is something not-that-easy to understand and that doesn't bring, for example, execution speed enhancement.
I still didn't play too much with auto-(un)boxing but I expect to find some cases where it will be more an annyance than a benefit.
I've seen Java evolving during the past years to become bigger and bigger, at the cost of inconsistencies appearing to preserve backward compatibility (for example, Enumeration and Iterator coexistence).
I have the very bad feeling that Java is becoming fat.
Personally, I would love to see a new version of Java starting from a clean base with better base APIs (like a new filesystem API, java.io.File is pretty limited). Anyway, I'm really wondering if this backward-compatibility is not already broken (try to run a complex Java 1.0 app in 5.0).
From what I can read, it's not gonna happen. This brings the risk that a new language, sharing the same spirit than Java but modernized, and backed by another big company and a strong community, might take the lead one of these day (not necessarly C# and M$ but who knows).
My 2 cents.
Regards,
Sebastien.
Posted by: spetrucci on September 14, 2004 at 11:24 AM
-
Can we have operator overloading for the Number class?
I know that operator overloading goes against the java-style (as multiple inheritance and so on), but since String has already a little operator overloading ("+" = concatenation) why shouldn't we have aritmethic symbols for arithmetic calculation.
Working with BigInteger, even doing the simplest calculation results in an unreadable mess.
Notice: I'm not proposing a C++-style operator overload but a String-style operator overload
for add, subtract, multiply, divide (+-*/).
The problem could be with different Number subclass. You'd expect them to work, but...
Long aLongNumber=new Long(10);
BigInteger aBigInteger= new BigInteger("500");
BigInteger result= aLongNumber+aBigInteger;
would result in
Long aLongNumber=new Long(10);
BigInteger aBigInteger= new BigInteger("500");
BigInteger result= aLongNumber.add(aBigInteger);
And this would return a compile-time exception..
Posted by: insac on September 14, 2004 at 11:35 AM
-
Depreciation and Updates
IMHO the first thing to do is to define the general functionality we want from the core java language. For the most part this is done implecitly by what is available, but I think it should be listed explicitly.
From there the language should be focused on three primary thing.
First: Have one or two supported API's for each function. ei... Swing for GUI's, NIO for input/output.
Second: Depreciate and remove unworking or substandard API's. This must be done carefully, and slowly. One candidate would be the current Date Calander mess. Also, depreciated methods/classes should be moved out at in a well defined process.
Third: As part of the review of current API's third party API's should be considered for integration into the language which should replace rather than add too existing code.
I know that much of this violates the backwards compatability rule, however those that require older JVM's could have an available jar to add to their systems, as they have to upgrade to a new JVM in order to break the code.
Another option would be to continue the inclusion of depreciated classes in language, but remove them from view.
Also it bugs me that the hyped features of J2SE 5.0 v1.5 (man I hate that) where mostly sintactical sugar and added no functionality to the language. At least generics added some compile time checking, but it was no real addition. There were some great additions that got no press, such as the entire new theading library in java.util.concurency (something like that).
Overall I believe that we should be careful to keep Java fully functional, up to date, and not bloated.
Posted by: smbell on September 14, 2004 at 11:36 AM
-
design by contract
A method-level construct would be more than just sugar. It would allow you to define your pre/post conditions as a part of an Interface, which you can't do with the current assert() mechanism. assert() also falls short when you overwrite a method, because the assert() calls aren't inhereited -- but a method-level construct could be.
Interface List {
@pre (o != null) "No null elements allowed"
add(Object o);
}
...
jdkListImplementation.add( null ); // blammo
userListImplemention.add(null); // blammo! And the user didn't have to do anything to get this.
Of course, we have JContract at the moment ... but it's a precompile, and DBC is much less useful when your core libraries don't expose any contracts.
Posted by: cflipse on September 14, 2004 at 11:43 AM
-
Visibility Modifiers
I want these finally sorted. Default 'private' visibility would prevent backwards compatibility, so I'll forget about that.
How about a visiblity modifier which is private-protected i.e. accessible by only to that class and its subclasses.
Posted by: archangel on September 14, 2004 at 01:15 PM
-
module concept
Some way of creating modules with a defined interface (and everything else hidden) would be nice. Some of the JAIN JSRs come close.
Posted by: m_r_atkinson on September 14, 2004 at 02:40 PM
-
Limited operator overloading
This did not seem to get posted, so I'm reposting.
Add operator overloading to the java.* and javax.* package hierarchies only.
This would allow limited and well designed operator overloading for such classes as Complex and BigNumber without creating a free-for-all.
Posted by: m_r_atkinson on September 14, 2004 at 02:44 PM
-
immutable classes
Add some way of creating true immutable classes that may be passed by value (at the descretion of the JVM).
Posted by: m_r_atkinson on September 14, 2004 at 02:48 PM
-
Nice features for Dolphin
To make Dolphin safe, robust, simple and backward compatible, then Dolphin architects must look at Nice.
All expected features are already there!
With ideas from this project, all Groovy like features can be added on a smooth path.
Posted by: stratic on September 14, 2004 at 03:00 PM
-
start with Rusty's "Refactoring Java" proposal
In his November 2002 lecture, "Refactoring Java", http://www.cafeaulait.org/slides/javapolis/refactoring/Refactoring_Java.html, Elliotte Rusty Harold raises several issues which would really be the starting point of the current discussion. My personal 2 cents is that his Point 7: "Ditch the AWT", because AWT and Swing is one too many, should become "Unify AWT, Swing and SWT", because these are 2 too many.
Posted by: grumpy on September 14, 2004 at 03:32 PM
-
API fidelity
I would like to give my vote to "Fidelity of the API, and stuff". Fill in the gaps in the API. Fix the L&F:s and make everything with a graphics presentation accelerated on all platforms.
Stop adding features and please start removing old stuff, EVEN IF it means that it will break code <= 1.3. The legacy will soon start to hinder any evolution since everything is "hanging in thin threads".
Sort out Swing and make it the only option in 7.0. Away goes AWT. It has to be done, just look at all the "if (isHeavy) do that" code in the Component tree. Would be good to get rid of that...
So, in short. Pretty please, A major overhaul and cleanup is what I want. It is long overdue. :)
Cheers,
Mikael
Posted by: mgrev on September 14, 2004 at 04:34 PM
-
Retrofitting static null checking
At first glance it doesn't seem to bad. Code compiled with -target 1.6 would be statically null safe. For compatibility, dynamic argument checking would prepended to all (accessible) methods. At runtime old code would also need checks inserted where it implements new interfaces.
Static null checking gets a bit hairy during instance and class initialisation. Member variables may be declared non-null but not yet initialised. A way around the problem for instances is to add an additional modifier for objects that may contain uninitialised non-null references. Perhaps types such as Integer should appear with a default value, like their primitive counterparts. The modifier must also be applicable to methods where 'this' may be uninitialised. However, it is non-trivial to decide where this modifier is applied. For instance many Swing classes invoke many methods in their constructors, which varies from release to release (you don't get that in C++).
Having said all that, in terms of reliability, static null checking is vastly more important than generics' type checking. Search the Bug Parade for ClassCastException and NullPointerException. One term will find a few more hits than the other.
Posted by: tackline on September 14, 2004 at 05:51 PM
-
design by contract
Postconditions should be inherited, but not preconditions. In general a derived type should accept all that its super type does, and possibly more. However its return values should be more restrictive (see covariant return types). However postcondition are less important to check at runtime, so its difficult to see how we can gain anything easily here.
My main problem with design by contract is how to make preconditions public and efficient without revealing internal implementation,
Posted by: tackline on September 14, 2004 at 05:53 PM
-
Few ideas
When I first (and last) saw Modula-2 I thought 'with' was great. However it soon became clear that it produced indecipherable code. I don't see that it has much of a place inside an OO language.
There's two sides to properties: the implementing code and the client code. The C# implementation code is nothing if not nasty. On the client side the problem is Java's noisy syntax (ditch the .(,);{}!). I don't consider swapping address.setPostcode(postcode) for address.postcode = postcode, sufficient gain for the extra complication and non-uniformity. When retrofitting to the Java code base we have to be aware that, unlike C#, member variable and associated property have the same name.
Posted by: tackline on September 14, 2004 at 05:53 PM
-
My little 6.0 must-have list
Firstly improved anonymous classes. Martin Fowler's recent Bliki entry on closures managed to choose examples that were so trivial that Java 1.1+'s anonymous classes and C# 2.0's anonymous delegates would work if inelegantly. However, for a large set of cases, anonymous inner (and local) classes fall down because they cannot modify local variables in the enclosing scope. Saving a small implicit allocation when doing explicit allocations seems against the general theme of Java as an efficient use of programmer time.
The second part of the point is that the anonymous inner class syntax is hideously verbose for the common, simple cases. I'm not going to suggest 'groovy' dynamic typing or C++/C# less-than-OO function types are the way forward. Instead in virtually all cases the required type is implied by the context. Often an interface with a single method, so there's not too much to guess there either. For instance change
` ` comp.addActionListener(new ActionListener() {
` ` ` ` ` ` public void actionPerformed(ActionEvent evt) {
` ` ` ` ` ` ` ` doStuff(evt);
` ` ` ` ` ` }
` ` });
to
` ` comp.addActionListener(new() (* evt) doStuff(evt););
And perhaps nominate default implementations to common interfaces. For instance change
` ` List list = new java.util.ArrayList();
to
` ` List list = new();
even using an array initialiser
` ` List list = { };
The other main thing is operator overloading, but safely. C++ has the idea that the primitive types have immutable semantics. You can't redefine int operator+(int lhs, int rhs) { return this- -rhs- -1; }; giving 2+2 makes 5. However you can add top-level functions like double sin(double); and also mutate libraries. I'm not proposing to do that. So there will be no redefining of =, ==, !=, (), ,, ., or anything else that already has a definition.
However I believe it can be safe to overload +, -, *, /, %, [], !, ~, &, |, ^, ?:, || and && (the last three using the relaxed anonymous inner class semantics above). ! and ~ are trivial. For the others the type of the first operand should be final. The may be in one or other of the classes. So for instance a Matrix class might define public static Matix times(double, Matrix), to allow multiplication by a scallar (vectors could use an extra multiply operator).
Elsewhere I would add a value() method (or make the field public) for Boolean, Byte, Short, etc., that returns the primitive value. Just as an explicit way to unbox, without the danger of writing .intValue() instead of .longValue().
In someways having finite ranges on integers frigtens me. BigInteger (and BigDecimal) should be encouraged by allowing assignment from literals. e.g. BigInteger pointOne = 0.1;.
Perhaps a System.ignore() method that does absolutely nothing, together with an -Xlint option for checking that all variables are used.
For some applications you want a large amount of text within code. SQL, perhaps, or inverted JSP. So multiline string literals. Also the message (or printf) format is a bit of a pain, so introduct interpolable strings. Or perhaps they should send a pair of arguments to a method: log($"${x} at ${y,date,long}") becomes log("{0} at {1,date,long}", new Object[] { x, y }).
A repeated hack is for builder objects to return this from almost every method call. That can be confusing if you are expecting a new object, and is otherwise messy and hacky. See AbstractStringBuilder. So I suggest an expression syntax to repeatedly call an object and evaluate to the object. Together with an annotation to deprecate the use of return values (can return types be directly annotated, or does it have to be on the method?). For instance:
` ` String xyz = new StringBuilder() -> {
` ` ` ` append(x);
` ` ` ` append(y);
` ` ` ` append(z);
` ` }.toString();
or
` ` Map map = new() -> {
` ` ` ` put(k, v);
` ` ` ` put(l, w);
` ` ` ` put(m, x);
` ` };
I'm a fan of checked exception but in certain roles they can get a bit much. A way to wrap and document would be jolly handy (not using AOP!).
Posted by: tackline on September 14, 2004 at 06:01 PM
-
Limited operator overloading
At the very least, overload the arithmetic operators for BigDecimal and friends, just as the + operator is overloaded for the String class.
Posted by: weiqigao on September 14, 2004 at 07:06 PM
-
JARPATH
I vote for JARPATH.
Posted by: weiqigao on September 14, 2004 at 07:12 PM
-
A Modern HTML Rendering Component
See Eric 's Blog for a detailed explanation.
Posted by: weiqigao on September 14, 2004 at 07:16 PM
-
this() as constructor
How about make this() as constructor? It's easy to type and no risk.
class ThisIsA ClassWithLongName {
this() {
this("hi");
}
this(String greeting) {
}
}
Compiler can translate them to normal constructor names to avoid changes in JVM/Classloadding etc.
Programmers can still write normal constructor names for compatibility.
Posted by: xhq on September 14, 2004 at 08:58 PM
-
this() as constructor
How about make this() as constructor? It's easy to type and no risk.
class ThisIsA ClassWithLongName {
this() {
this("hi");
}
this(String greeting) {
}
}
Compiler can translate them to normal constructor names to avoid changes in JVM/Classloadding etc.
Programmers can still write normal constructor names for compatibility.
Posted by: xhq on September 14, 2004 at 08:59 PM
-
Few ideas
I don't propose automatically replacing all getters and setters with properties, but it'd certainly be nice to be able to use this in future APIs. To differentiate a member variable from an associated property, such future APIs could simply prefix the member variable with "_" (such as "_postcode", for your example). Furthermore, sometimes a "property" doesn't map to a member variable : for example, in :
http://java.sun.com/j2se/1.5.0/docs/guide/language/enums.html
...there's a "Planets" enum, where each instance has a mass and radius as member variables, and a surfaceGravity property based on a calculation.
Given that "if it isn't 0 or 1, then it"s syntax sugar", I still believe that properties have their place. Most IDEs, expression languages (such as EL in JSTL, Apache Velocity, et al), and scripting languages provide this feature, and well, frankly, it's more readable. That's what it's all about really, isn't it ?
Posted by: chris_e_brown on September 15, 2004 at 01:04 AM
-
Better date handling and date formatting
Better date handling (immutable instances -- so no synchronization overhead!! --, more readable multi-calendar support) can be done :
http://joda-time.sourceforge.net/
It also offers a thread-safe equivalent to DateFormat. That'd be nice too, if integrated into the standard text formatting libraries...!
Posted by: chris_e_brown on September 15, 2004 at 01:08 AM
-
Contravariant argument types
Tiger added covariant return types, i.e. an overriding method may return a type that extend the return type of the overrriden method.
What about allowing an overriding method to accept types that are subtypes of the argument types from the overriden method ?
Posted by: benb on September 15, 2004 at 01:09 AM
-
Contravariant argument types
oups... of course I meant surtypes of the arguments types from the overriden method.
Posted by: benb on September 15, 2004 at 01:12 AM
-
J2SE 6.0 RFE
"We're unlikely to add a macro preprocessor (sorry) "
But simple compile condition would be nice option:
//#ifdef something
do something
//#else
do something else
//#endif
Posted by: gorazd_praprotn on September 15, 2004 at 01:55 AM
-
Working around checked exceptions
So let's say a() calls b() which is 'unsafe' and throws an exception which a() doesn't handle. What happens when the exception is thown? Surely a() either has to declare that it throws that exception or itself has to be marked as unsafe? Likewise all the way up the call stack. Or perhaps b() would surpress the exception so it never gets to a()?
Surely the former is just a syntactic shortcut to "throws Exception", and the latter is a shortcut to a method-wide try/catch(Exception) with no code in the catch block....? Or have I totally got the wrong end of the stick?
Posted by: javakiddy on September 15, 2004 at 02:46 AM
-
Aliases and locks
As the standard API grows and class names conflict, it would be nice to have a C# style alias facility...
import _utilList = java.util.List;
import _awtList = java.awt.List;
In the above "_utilList" can be used in place of "java.util.List" and "_awtList" in place of "java.awt.List". (The underscore prefix is my attempt at a convention to make aliases recognisable.) Naturally such a feature could be abused to create confusing or even misleading code ... but it may be worth it to get rid of long fully qualified class names.
Also, I was thinking recently about the problems of threading and certain classes. For example some of the collections classes have been duplicated to provide fast thread-unsafe and slow thread-safe versions. I was thinking about the merits (and pitfalls) of creating a mechanism by which a single class could operate in either mode.
If wondered, what if synchronized(o) { ... } didn't throw an exception when o is null, but simply had no effect (no lock). Switching between thread safe and unsafe modes would be as simple as setting or clearing a reference. Naturally this opens up a whole can of worms with regard to stuff like wait/nofity. And to be honest I'm in two minds myself as whether this idea has any merit... but I thought I'd throw it out there and see if anyone could make any sense of it.
Oh, and one final idea: would it be possible (is it possible?) to get javac to compile straight into a target JAR file, rather than onto the filesystem?
Posted by: javakiddy on September 15, 2004 at 03:32 AM
-
Contravariant argument types
isn't that covariant argument types?
contravariant would be as you subclass, the arguments get more general - this is the type safe option
covariant argument types aren't type safe, and i think the solution to that is to use multiple distpatch
as long as its simple to use in practice then i'd agree things like this sound like good candidates for inclusion?
Posted by: asjf on September 15, 2004 at 03:35 AM
-
Few more ideas
Real generics - so they will work with reflection and bring better performance.
Add operator for boxing/unboxing instead of automatic one, so we will explicitly see what happens.
Second operator for comparation, which compare operands via compareTo(). So we will have one comparing primitive values (including reference values) and new comparing object values. It can handle comparation of primitive x wrapper too..
Add unsigned byte for I/O operations, CGI, comfortable byte manipulations
Better Resources handling. You can see this rfe: http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4403721
Better (shorter) syntax for initialization of elementar structures, as Maps, Lists, Sets....
Or at least some methods which make chaining of adds/puts possible.
Look at old bugs and RFEs.. Bug database is full of realy old things.. Nice example is this RFE - http://bugs.sun.com:80/bugdatabase/view_bug.do?bug_id=4057701 . It is third most popular in top 25, 8 years old, still in progress...
Posted by: jarouch on September 15, 2004 at 04:29 AM
-
Working around checked exceptions
It is the try-catch block that I am trying to avoid here such that the compiler or the VM implicitly does that for you.
In a multi-tiered, too often code is littered with try-catch blocks when most classes have no business catching exceptions, because they do precious little. I agree the language provides powerful features that are often misused or misunderstood. The suggestion for an unsafe keyword isn't important in itself (I don't want to see Java go the C# route in this area). What's more important is a way to workaround checked exceptions.
Thank you for your replies javakiddy and coxcu.
Posted by: nerddawg on September 15, 2004 at 05:09 AM
-
A few more contraversal ideas
I would recomend some more contraversal ideas for discussion:
Multiple return values or tuples possibly. This feature can be implemented with minimum or no overhead. It's discussed at http://bugs.sun.com:80/bugdatabase/view_bug.do?bug_id=4222792
Protected types in Ada style. Let's have int<apples> x; int<pears> y; and x = y -> Compile type error.
Some support for design by contract. I hope, this can be done via standartised anotatios.
Possibility to set static type of an variable to more interfaces. The variable than must implement all of them.
The -> operator. It's semantics is follownig: If the left hand operand is null then do nothing else it's equivalent to the dot operator.
=== operator, that is equivalent to == for primitive types and to calls equals() for reference types.
An dynamic call operator, that makes possible to call any method on any object ignoring compile time type. It can be a very usefull for syntaxe suggar reflections.
Couple of new anotations such as @imutable, @oneWay and anotations for AOP
Mutable primitive wrappers and other small but usefull enhancements in API.
Posted by: satai on September 15, 2004 at 05:10 AM
-
A few more contraversal ideas
I'm sorry for the unclosed tag
Posted by: satai on September 15, 2004 at 05:12 AM
-
Already gone too far
I think the readability more than writability principle has already be damaged by Tiger.
For example enumerations save you typing but then you have to learn a whole set of rules for whats in them when reading code. I think some of the for loop constructs add brain cycles when you are reading code too.
The generics would have been nice to have in originally, but it looks like the retrofit has introduced something with lots of caveats and special cases - which adds more brain cycles.
I think Java is great - but you should be focussing on what to remove now (e.g. deprecated APIs) - rather than
what to add.
Posted by: c_armstrong on September 15, 2004 at 05:52 AM
-
Prioritized Listeners
Not a core langage thing but ... here it goes anyway...
I'd often find the need to have the listeners (for instance a MouseListener) to be ordered/sorted in some way.
.addXXXListnener(myLisntener, 110);
for instance would give it the relative order of 100. Swing default can be set to 100 or something (documented). This would make it easy to pre- or post process events without having to resort to tricks or the main event queue.
It is now very hard to "attach" oneself to a generic JComponent and preprocess the events, for whatever reason, since the order in which the listeners are notified are "undefined". It would be easy to do aswell, as the old API don't have to change and can, as now, recieve same order/priority as the swing UI listeners.
Cheers,
Mikael
Posted by: mgrev on September 15, 2004 at 06:20 AM
-
Aliases and locks
There is an RFE for exactly this in the bug database:
http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4478140
vote for it!
Posted by: bmandl on September 15, 2004 at 06:30 AM
-
Already gone too far
The concept of readability vs writability you follow means you should use basic since it has almost no features makes it easy to comprehend.
The rest of us want a smart languages, which means you have to know some extra constructs; you can't get around that. What Graham seems to be pointing at is that things should be consistent above all. I feel that he failed in the static imports thing; since that makes things less consistent and means you have to read a lot of code and do a lot of crossreferencing before you know what things actually mean.
Posted by: zander on September 15, 2004 at 07:53 AM
-
Baby Steps
#1 - Refine the JDK
It's too big, inconsistent, yadda, yadda. Incorporate lessons learned. Remove deprecated stuff. Fix broken designs. Unify programming styles. Adopt best of breed stuff.
#2 - Sponsor research to make VM ideal for dynamic languages.
The papers on porting Scheme, Python, ML, etc. to the JVM say it's possible, but tough. Make it easier.
#3 - Lightweight Objects
Do it right. No more autoboxing. Sane generics. Read David Bacon's papers on the Kava language for details.
Cheers, Jason Aaron Osgood / Seattle WA
Posted by: josgood on September 15, 2004 at 09:28 AM
-
Already gone too far
I think your thinking is too binary Zander :)
Obviously there is a continuum between Basic and C++
I am saying we have now gone too far to the right,
not that we should return to point zero.
If you are 100% sure about erasure and know all the
fiddly bits that enumerations contain (a lot more than just
ordered constants) then congratulations. I just think anyone
new to programming would be overloaded learning Java
now.
Posted by: c_armstrong on September 15, 2004 at 09:31 AM
-
Few ideas
I agree completely--properties seem like a small thing, but they would remove a lot of drudgery.
Of course, we need syntax for accessing properties. I can understand that
obj.prop or obj['prop']
might be a bit radical for Java, so perhaps another operator should be used? How about "double-dot"?
obj..prop
Posted by: cayhorstmann on September 15, 2004 at 10:16 AM
-
Operator overloading
"...what "=" means this week"
Graham seems to be saying operator overloading won't be added because overloading an operator changes its meaning.
This can be true in C++, but needn't be so in Java if operator overloading is implemented properly.
Overloading the + operator needn't change its meaning any more than overriding a method in a subclass changes its meaning. An overridden method is meant to obey the contract of the method it overrides: then anything which is true of the base class method (its 'meaning') is also true of the subclass method. This is the Liskov substitution principle.
For instance, suppose that a Number class defines plus() and minus() methods, and also states in its JavaDoc contract that a.plus(b).minus(b).equals(a); then a Complex class which extends Number has to obey this contract in its own plus() method. Operators are no different - they are just syntax sugar for methods. So operator overloading does _not_ introduce a new problem, just a new syntax for an existing construct.
To make operator overloading as safe as method overriding, we just need explicit contracts for operators like +, -, *, /, % etc. Such contracts, in the form of axioms of arithmetic-like behaviour, are well-known to mathematicians in the form of rings, fields etc. The way to express these contracts in Java would be to require any class overloading the operators to implement special interfaces like java.lang.Field, java.lang.Ring etc. If a programmer chooses to implement one of these interfaces but disobey its contract, this is just a BUG on his part.
There's some quite sensible discussion in this RFE:
http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4905919
Posted by: lucretius on September 15, 2004 at 10:20 AM
-
No nulls allowed
huh? how you work out my name?
Posted by: scurry on September 15, 2004 at 03:23 PM
-
New Javadoc tab--@example
Microsoft's development language provides detailed API document. Almost all API have a example to explain how use this API.
In JDK, API document is poor, most Java newbie don't know how to use this API.
If JavaDoc suport a new tag---@example, it will make the developer to writing consciously some example code in document, and will help user to understand the usage of API.
Posted by: turbochen on September 15, 2004 at 11:08 PM
-
true functions
Currently it is not possible to mark a method as a function (the output only depends on its parameters, there are no side effects).
Being able to create functions greatly improves readability of the code as it is much easier to reason about what is going on. Being able to declare a function is a limited form of design by contract, but a very useful one.
Posted by: m_r_atkinson on September 16, 2004 at 12:50 AM
-
design by contract
+1 for Design by Contract.
If done right, it would greatly aid readability of code, complement JavaDoc and solidify method specifications.
Just please make sure to not make the syntax too hard/ugly to read.
Posted by: cowwoc on September 16, 2004 at 06:25 AM
-
Whoa there, cowboy
Deep breath everybody. Let's keep the syntax as it is. It's why we're all programming Java to begin with. I, for one, do not welcome any C++ overlords. :-)
Spend some time on Java the platform, not Java the language. Figure out a sane way to:
Version the optional extended packages (or whatever they're called this week) and get them out of the core distribution
Start an application on any platform without having to edit or monkey with shell scripts or batch files
Please get isolates in there
Catch an exception chain; e.g. drop into a particular catch block if any exception in the candidate exception's wrapped exceptions is an instance of the relevant class
Have an option for the compiler figure out if you don't have a particular library you need to link against. Maven is somewhat like using a front end loader to plant daisies in this regard; I wish dependency resolution were in the compiler itself, perhaps as a nonstandard option.
Posted by: ljnelson on September 16, 2004 at 07:20 AM
-
A const keyword for me, please.
I would like to see the const keyword resurrected in Java. It helps identify the "read-only" methods. More details in my blog entry I still miss const in Java. Also, you might want to check the proposal for adding const to java in OOPSLA 2004 this October.
Posted by: chakrayadavalli on September 18, 2004 at 06:57 PM
-
Drop the bytecode ISA
It is a pain to optimize. It's also very much Java biased, which makes it a sub-optimal choice if you truly want the JVM to be a multi-language VM at the core.
Standardising on a java binary compatiblity ABI for natively compiled Java code would be nice, as well. gcj is pushing ahead in this direction, and it would be nice if Sun would adopt their approach, when it's finalized.
In my opinion, Java needs bindings to other languages. Despite the WORA marketing campaign, lots of people still write lots of good code in other programming languages, and they show no signs of slowing down, or switching. Unfortunately, people who do cross the self-imposed borders and try to reuse the good work of others in other languages, get accused that they want to split the Java platform.
CNI shows the way for C++, but there are other popular languages where the binding strategy is 'compile to bytecode', which, due to the Java-specificness of the bytecode, is usually a very bad idea. Compare IronPython to Jython for an example of how the J in JVM hurts Java as a platform for interoperability between multiple languages. That's an area where .net is years ahead of Java, unfortunately. I'd love to see bindings for ocaml, perl, .net, and so on as part of the Java platform, but I guess Sun doesn't want that to happen.
Posted by: robilad on September 20, 2004 at 05:52 AM
-
Add immutable not const
Add immutable types, see RFE for why they work better than const and avoid the problems of C++.
Posted by: hlovatt on September 20, 2004 at 04:58 PM
-
You state that "the C++ language itself became very complex. Many new ideas were added incrementally and unfortunately the seams show". I guess that means that adding to java new language features which are not considered to be essential and very necessary should be discarded. But there's this new feature in Tiger called "Formatted Output", which allows you to write thigs like "System.out.printf("%s %5d%n", user,total);". It is announced as something which "will help migrate legacy C applications, as the same text layout can be preserved with little or no change". In other words, this new feature will bring a bit of the unreadability of C straight back to Java. Now we can make methods with an undetermined number of params (javascript style almost!). While most new features in JSE 5 seem fine this one keeps me wondering about how many of this little features will slip into future versions of the language, undermining it slowly until we have a new version of that dreaded C you talk about.
Posted by: jordihs on September 30, 2004 at 04:26 AM
-
I'd like to see a minor (?) extension to the syntax / semantics of catch clauses
that allows me to safely handle a list of exceptions in a single catch phrase.
try {
...
}
catch (NumberFormatException, FileNotFoundException, MyException ex) {
/* The type of 'ex' is the most-derived common supertype of the
listed exceptions. */
System.println("Invalid arguments: " + ex.getMessage();
}
catch (IOException ex) {
ex.printStackTrace();
}
At the moment, the above has to be coded by duplicating the catch clauses.
This makes the code harder to read.
Posted by: crawley on October 03, 2004 at 07:47 PM
-
Two points:
Catching multiple exceptions can be done by taking the body of the catch clause and making it a 'private static void' method.
I would like to be able to declare an exception as 'final', I have yet to see one that isn't! EG:
catch( final Exception e ) {
....
}
Posted by: hlovatt on October 05, 2004 at 08:32 PM
-
Re point 1) above - True. Indeed, I sometimes do this myself. However, a multi-exception catch clause is significantly more readable than putting
the catch logic into a separate method. Besides, the code in a catch clause
can access and update local variables declared in the enclosing method.
Posted by: crawley on October 07, 2004 at 09:15 AM
-
Extending the Java Type System to Support XML I am not a language expert and to be quite honest, I am quite content with Java as a language. Given that I am not a laguage expert, perhaps what I have to say is a load of manure but perhaps it has some worth.
I find Lisp better suited to manipulating XML. I can't really point out and say what it is about Lisp that makes it so but I find it more cohesive to use Lisp than the Java XML APIs. I am not saying that the various Java XML APIs themselves are to blame. The matter came togather for me when I read Programming with Circles, Triangles and Rectangles. In this document Meijer makes the arguement
Just like biological artifacts, this symbiosis is subject to evolution. A heavily used part of the API or common programming pattern is a candidate for promotion to the host programming language. We are all familiar with this situation: we can't imagine a language where numerals, strings, or arrays were available purely via APIs!
I think Java should move its XML support out of its API and into its core type system. I have no clue how this can be engineered but I am sure our community is vast in its experience and its capability to create a prototype. Or perhaps some one already has.
Posted by: suhail on November 19, 2004 at 02:22 AM
-
I forgot to mention the URL for the Meijer document, you can find it at Programming with Circles, Triangles and Rectangles
Posted by: suhail on November 19, 2004 at 02:24 AM
-
I either would like to support some "friends" import mechanism
If I want to create a well encapsulated API I am forced to have all classes in one package rather than having the possibility to structure the classes logically within several (hierarchical) packages. The possibility of structuring packages hierarchically would enforce semantic structuring and result in leaner packages. I could not find a related JSR for this issue until now. If there is a way how I can help to support introduction of such a mechanism, please let me know...
Posted by: rbirenheide on January 10, 2005 at 11:54 PM
|