A good percentage of lines in Java programs look like this:
SomeLongClassName foo = new SomeLongClassName(args);This could be a static, instance, or local variable. Of course, sometimes the two class names are different. For example:
SomeInterfaceName bar = new SomeInterfaceImplementation(args);But the former case is so prevalent and so frustrating to type, that I propose a shortcut syntax. I rejected the C++ syntax because one design goal of the JLS is to have a visible 'new' keyword wherever objects are created.
SomeLongClassName foo = new(args);should be equivalent to
SomeLongClassName foo = new SomeLongClassName(args);
C++ requires special syntax to enable automatic disposal on scope exit. For instance, the following code:
void foo() { Bar * const p = new Bar(); doSomething(); }does not release the resource when the scope exits. Instead, you have to use a different syntax:
void foo() { Bar p(); doSomething(); }Now the resource is disposed when the scope exits. The same is true in Java. If you code:
void foo() { final Bar p = new Bar(); doSomething(); }then nothing is disposed when the function exits - exactly like in C++. If however, you write:
void foo() { final Bar p = new Bar(); try { doSomething(); } finally { p.dispose(); } }then the Bar is guarranteed to be disposed - exactly like in C++.
So what's the beef? The functionality is exactly the same. I wish that the syntax for the automatic disposal case in Java were simpler - something closer to C++ syntax. In particular, I want the syntax for automatic disposal to be *shorter* than the syntax for manual disposal - not longer. What I want is some "syntactic sugar".
package java.lang; public interface Disposable { void dispose(); }
class MyFiler implements Disposable { MyFiler(String name) { ... } public void dispose() { closeAll(); } ... }then the following:
void foobar() { // notice I'm using the initialization shortcut described above final MyFiler filer = new("blah..blah"); doSomething(); // shortcut syntax not requried for 'Disposable' feature final MyFiler filer2 = new MyFiler("barsoap"); doSomethingElse(); }would effectively generate this:
void foobar() { final MyFiler filer = new MyFiler("blah..blah"); try { doSomething(); final MyFiler filer2 = new MyFiler("barsoap"); try { doSomethingElse(); } finally { filer2.dispose(); } } finally { filer.dispose(); } }
class Soap implements Disposable { private final MyFiler filer = new("bar"); public void dispose() { } } class Shampoo extends Soap { private final MyFiler filer2 = new("liquid"); }Would generate code equivalent to:
class Soap implements Disposable { private final MyFiler filer = new MyFiler("bar"); public void dispose() { filer.dispose(); } } class Shampoo extends Soap { private final MyFiler filer2 = new MyFiler("liquid"); public void dispose() { filer2.dispose(); super.dispose(); } }
Even if dispose() is called while a reference is retained somewhere, this does not corrupt memory (unlike C++). This feature is just syntactic sugar for a common use of try..finally.
Every class with external (non memory) cleanup required should implement a standard (for your company) interface (say, Disposable). Every Disposable class must provide a 'finalize()' method (separately from the dispose() method). It should check whether the instance was properly disposed, and write a log record which will be seen by a programmer whenever finalize() has to do the dispose(). This way, programmers using your class will be encouraged to use the proper try..finally syntax where needed to avoid the annoying error messages.
Although the language provides for initializing primitive arrays, the current implementation is a joke. A blank array is allocated, then each element is individually set to its value. The workaround is to load a resource file to initialize large primitive arrays.
Without changing the JVM, it would be an improvement if the compiler would create this resource file for you and generate code to load it.
In JDK 1.1 there was a public API for user defined encodings. Furthermore, certain kinds of programs can be made 4 or more times faster by keeping an instance of a Converter loaded instead of passing the encoding name as a String. This feature was taken away in JDK1.1.3! Sun promised to give it back in an improved form - but it still isn't there in Java 2. Our database driver needs to access byte encoded fields, and the performance is unusable without using the sun.io package as per the original JDK1.1 spec. The only other alternative is to roll our own converter classes - which seems silly.