7.0 wishlist?

H

Harold Yarmouth

There's probably plenty of these floating around already, but here's
bits of mine:

* Sort-of structural typing. Any object can be used where an interface
type is expected if it has the right set of method signatures, whether
or not it "implements" the interface using that keyword. (It still must
to inherit constants defined in the interface, and methodless interfaces
would not get this behavior else everything becomes, among other things,
serializable!)

* Allow extending final classes, subject to the constraint that new
instance fields cannot be defined and none of the final class's methods
can be overriden regardless of whether the method is explicitly "final".
Essentially allows wrapping final classes.

* Add an unsigned byte type.

* Add some way to specify that something should never be null. Perhaps a
! or a * before or after the variable name or type name.

* Allow omitting the names of unused parameters. Common cases would include:
public void ActionPerformed (ActionEvent) {
foo.setVisible(false);
bar.purge();
}

catch (IOException) {
return false;
}

* Constructor type inference. Also allow an alternate constructor
syntax that doesn't repeat the class name, say using * in its place.
So we can avoid some cases of repeating type names, assign
Map<K, V> myMap = new HashMap(), and perhaps also do e.g.
ConcreteType x = new(argument) where ConcreteType has a suitable
public one-argument constructor.

* Disallow public constructors on abstract classes. They are not
callable by any more code than a protected constructor anyway.

* When a type has a one-argument plus() method, + can be used when the
left hand operand is of that type and the right hand operand is of an
argument type for which the former has a one-argument plus() method.
This + binds with the usual precedence for binary + and x + y is
simply an alternate way of saying x.plus(y). Similarly .times and
some others. <= and >= and < and > use compareTo. === and !== get
added and use .equals, and bind with the same precedence as == and !=.
x + y * z is converted by the compiler to the same bytecodes as
x.plus(y.times(z)) and x * y + z to x.times(y).plus(z). += and the
like combine assignment with addition. ++ does .plus(1) and --
.plus(-1). Unary - does .negated() and x - y is x.plus(y.negated()).
For consistency's sake a .plus method is added to String that returns
a concatenation. None of the +=, *= etc. change objects, only
reassigning references; String s; ... s += t is legal and reassigns
the reference s to a new string object. Compiler remains free to
optimize string accumulations to use StringBuilder under the hood,
and programmer remains encouraged to use it explicitly at least in
loops. StringBuilder also gets a .plus method. Both of these take
Object and use its toString if necessary.
In short, a hygienic form of operator overloading.

* Clean up ImageIO and JAI. A lot of the code in these throws various
RuntimeExceptions in response to seeing something it doesn't like in
file or network data. Really, only checked exceptions (and mainly
IOException) should be thrown in response to seeing something you
don't like in externally-obtained data.

* Inverse to the above, get rid of some awkward checked exceptions or
make them RuntimeExceptions. Culprits include NoSuchAlgorithmException
(usually, the algorithm name is hard-coded and so this exception
signals a bug close to where it is thrown, rather than an erroneous
or unexpected condition the program is expected to cope with in
production) and most others where the usual handling by the coder is
to let the exception kill the thread, catch it and throw new
RuntimeException() or Error(), or catch it and do nothing.

* Dead code in a method should be a warning, not an error.

* Hiding a local variable with a nested-scope local variable should be a
warning, not an error.

* Provide a better way to deal with OutOfMemoryError or low memory in
general, as well as a JVM mode in which a program can use as much
memory as it needs, but the VM will also not greedily take everything
the OS will give it. In this, it may maintain a "load factor" similar
to a HashMap for the entire heap, trying to keep it near 75% full, and
a JVM option to tweak this may exist. Higher gives poorer GC
performance but leaves more RAM for the OS; lower gives better GC
performance but uses more memory; no value throws OOME unless the OS
won't give the Java process memory it needs.
Add System.addLowMemoryListener() or similarly. Listeners are notified
if free memory dips below some threshold, running on a temporary
worker thread and perhaps doing things like flush caches.

* Provide a nicer way to deal with resource release. Possibly have a
Releasable interface added, which specifies a dispose() method and
which would be applied to many objects like streams and JFrames
that already have such a method or a similar method. Methods that
get a non-Swing-container Releasable and don't either return it or
use try...finally to dispose it generate a warning. A do() method
in the same interface takes a Runnable and calls the runnable
then disposes the releasable.

* Especially given the above: a shortcut for new Runnable() { public
void run () { ... }}. Let a brace block appearing where an expression
is expected be equivalent to the above, with the contents of the
brace block in place of the ellipsis (...). Then you can do e.g.
SwingUtilities.invokeLater({foo.setVisible(true);});
Also allow this short form to throw checked exceptions, which it
will be assumed the calling code might throw. (So
SwingUtilities.invokeLater({myOutputStream.write("foo");});
would be treated by the compiler as able to throw IOException,
though in fact it would arise in another thread entirely; on
the other hand, using Runnables as custom control blocks like
the Releasable.do() suggested above would result in the
exception being thrown out of do() and into the code that
physically contains the block. Most invocations of runnables
into separate threads are not with ones that throw unhandled checked
exceptions anyway.

* Allow array literals in expressions other than assignment RHS.
Why the devil is foo(1, "string literal", 3) allowed but
foo(1, {array, literal}, 3) is not, even when foo's second
parameter type is Object?
(The above two can be disambiguated: array literals and statement
blocks are syntactically distinguishable, and array literals will
generally be used where the parameter type is an array type or
Object and runnable literals where the parameter type is Runnable.)

* Have array constructors added to the collection classes:
(with the above as well)
new HashSet({2, 3, 5, 7, 11, 13});
new ArrayList({"foo", "bar", "baz", "quux"});
new HashMap({{"key1", "value1"}, {"key2", "value2"}});

* Add java.lang.Pair<K, V>. Make some existing classes Pair
implementations, e.g. Dimension extends Pair<Integer, Integer>,
possibly also Rectangle extends Pair<Dimension, Dimension>,
Map.Entry<K,V> extends Pair<K,V>, etc.
Two-element array literals allowed where Pair is expected and
produce Pair literals.

* [int x]; defines a final box containing an int, an instance of a
Box<T> with T == Integer, which has methods T get() and void set(T).
One can then do e.g.
[JFrame foo = new JFrame()];
...
SwingUtilities.invokeLater({foo.get().setVisible(true);});
given the above runnable-literal suggestion.
Add a : operator that expands to ".get()." and we have:
SwingUtilities.invokeLater({foo:setVisible(true);});
Almost a closure, there!
The : operator also lets us use WeakReference and the like
more nicely, if we add another touch to handle the case of null.
ref:doSomething()?System.out.println("something was null!");, say.

* In many more cases it might be useful to have a shortcut to
if (x == null) value = this else value = that
so how about more generally allowing x.foo?ifNull -- the ? clause
is executed whenever x is null and the method call when it's not.
Or just allow x?expression1:expression2 for non-Booleans testing
for null.

* Another source of boilerplate code is:
Type t;
try {
t = someExpressionThatMayThrow();
} catch (FooException e) {
...
return/continue/break/throw foo/whatever
}
t.doSomething();

where you don't want to doSomething() if the exception got raised,
doSomething() itself may raise the same exception but it shouldn't be
caught in the same catch, or similarly.
Let an alternate form be:
try {
Type t = someExpressionThatMayThrow();
} continue {
t.doSomething();
} catch (FooException e) {
...
}
which is not shorter, but doesn't break up t's declaration and
assignment. This, among other things, lets t be final, and also
lets the catch fall through without "t may not be assigned!". In
some cases it may save lots of boilerplate code:
Type t = null;
try {
t = someExpressionThatMayThrow();
} catch (FooException e) {
fooNotifier.logError(e.getMessage());
failed = true;
}
if (t != null) {
t.doSomething();
}
Yuck! This occurs a lot in I/O code though, usually with Type
actually InputStream or one of its close relatives. Often we
want to handle failure to open the stream specially versus
a failure once we already have the stream open, though both
throw IOException. Sometimes, for instance, we want to flag
an error in some way if the open fails, but let the IOException
bubble up to the caller if the subsequent I/O fails, as the
latter is "more exceptional" than the former.
The key to the above is to have t remain in scope in the
"continue" block.
(Other ugliness this might relieve includes some cases of nested try
blocks.)

* Full closures. Let anonymous inner classes access nonfinal local
variables of the enclosing scope, by having the compiler put all
such variables used by such inner classes transparently into an
Object[] array rather than directly on the stack, or something of
the sort. (The syntax of using them wouldn't change; only how they
got stored, so they had mutable references on the heap, and thus also
the bytecode generated where they were accessed. The compiler would
also not need to generate type checks when dereferencing this array,
as there'd be no way of getting at it directly in user code.)
Furthermore, let {code} used as an expression rather than a statement
stand for new Object() { public Type1 run(Type2 arg1, Type3 arg2...)
{ code }}. Add "it implements the interface if it is method-compatible
with it" from high up on this list and this gets you Runnable literals
in the void return, no arguments case. Types inferred by what the
expression's type needs to be to fit -- there would need to be a new
type in the system for type-tuples, which would also be useful for
reifying generics and where the <void> tuple represents Runnable,
<void, int> an interface specifying void run (int x), and so on.
Lastly, closures could use "return return x" to throw a
ClosureNonLocalReturnException wrapping an x, and passing a closure
to a method would implicitly wrap the method call in try { ... }
catch (ClosureNonLocalReturnException e) { return e.getWrapped(); }
-- implementing non-local returns. (If the closure "escaped" its
context and then non-local returned, it would manifest in a
RuntimeException: the uncaught ClosureNonLocalReturnException.
The JIT compiler could optimize the generation of nonlocal returns
that proved to be always implicitly caught by eliding generation of
their stack traces. (In practise, each nonlocal return would have
to throw a new anonymous subclass of that exception -- each time
a method was invoked that contained such closures it would cause
the generation of a new anonymous subclass and that class would
be caught by the implicit catch blocks in that invocation of that
method. This would be the conceptual behavior, anyway. In actuality
the generated bytecodes would probably look like those from an
explicit throw of an exception that takes a wrapped value and
an id integer, plus those from an explicit catch clause resembling
if (e.getID() != id) throw e; return e.getWrapped();
The method bytecode would also need to generate this id, and a new
one each call; System.nanoTime() might work on present processors.
An efficient atomic integer incrementor might be needed ultimately,
or an efficient implementation of ThreadLocal, with a bipartite ID
of the thread's identityHashCode and a thread-local incrementing ID.

* Object.identityHashCode().

* Equalizer to go with Comparator, provides equals and hashCode by
proxy, can be used with HashSet and HashMap to provide substitute
key equality and hash functions the way Comparator can provide a
substitute compareTo for TreeSet and TreeMap.

* WeakValueHashMap, LinkedWeakHashMap, and LinkedWeakValueHashMap.
These would all be useful implementing caches where you want the
mapping to go away if the value is no longer in use, but calls
for the value to return the pre-existing object if one existed.
WeakValueHashMap already sort-of exists in one under-the-hood bit
of non-user-reusable Java: the implementation of string interning,
starting whenever they finally got it to GC unused interned strings.
Trying to implement one yourself is a bear, because there's no way
to automatically do something when a reference dies.

* ReferenceQueue.addListener(Reference r) to let you automatically do
something when a reference is enqueued. Or provide a protected method
in Reference that is called when the reference is cleared or is
about to be cleared, so you can e.g. subclass WeakReference, override
this method, and do something specific (such as remove a mapping
from a map).
Closest you can currently get is to use a WeakHashMap of the
same object to
new Object() { protected void finalize() { do.whatever(); }}
and pray.

* Allow subclassing an enum with the subclasses able to REMOVE (not
add!) values. An enum that can be any of X, Y, or Z is a subtype,
rather than a supertype, of one that can be any of X, Y, Z, A, or B
because it is substitutable for the latter but not vice-versa; the
actual created classes would be Super with subclasses Sub, Super.A,
Super.B, Super.X, Super.Y, and Super.Z and subclasses of Sub Sub.X,
Sub.Y, and Sub.Z, with some change to the underlying code to not treat
Sub itself as an enum value for Super and to treat Sub.X, Sub.Y, and
Sub.Z as convertible to their Super counterparts. The former change is
easy: ignore non-leaf subclasses. The latter is also easy, so long as
enum subclasses can't add methods, fields, or similarly.
Might as well also allow creating supertypes, an enum with additional
values that is assignable FROM the original enum but not TO it.
These might be best implemented not as true under-the-hood subclasses
at all, but as parallel types with implicit conversions among them.
 
J

Joshua Cranmer

Harold said:
There's probably plenty of these floating around already, but here's
bits of mine:

* Sort-of structural typing. Any object can be used where an interface
type is expected if it has the right set of method signatures, whether
or not it "implements" the interface using that keyword. (It still must
to inherit constants defined in the interface, and methodless interfaces
would not get this behavior else everything becomes, among other things,
serializable!)

I smell a lot of unexpected bugs coming from this. Note that if you
already have the right method signatures, you could just take the
interface onto the implements list.
* Allow extending final classes, subject to the constraint that new
instance fields cannot be defined and none of the final class's methods
can be overriden regardless of whether the method is explicitly "final".
Essentially allows wrapping final classes.

No, essentially makes final classes worthless.
* Add some way to specify that something should never be null. Perhaps a
! or a * before or after the variable name or type name.

How about adding a @NotNull annotation and then running your own static
checker?
* When a type has a one-argument plus() method, + can be used when the
left hand operand is of that type and the right hand operand is of an
argument type for which the former has a one-argument plus() method.

[ ... ]

A poor way of doing operator overloading. There are better proposals out
there.
some others. <= and >= and < and > use compareTo. === and !== get
added and use .equals, and bind with the same precedence as == and !=.

Except many other languages use == as equivalent to the equals method
and === as equivalent to Java. Also note that you'll fall down with
nulls here.
* Provide a better way to deal with OutOfMemoryError or low memory in
general, as well as a JVM mode in which a program can use as much
memory as it needs, but the VM will also not greedily take everything
the OS will give it.

Judicious use of WeakReference and SoftReference helps, and there are
also suitable APIs in java.lang.management that already provide much of
this functinoality.
* Especially given the above: a shortcut for new Runnable() { public
void run () { ... }}.

[ ... ]

I take it you haven't heard of closures.
* Allow array literals in expressions other than assignment RHS.
Why the devil is foo(1, "string literal", 3) allowed but
foo(1, {array, literal}, 3) is not, even when foo's second
parameter type is Object?

new Object[] {array, literal} ?
* Have array constructors added to the collection classes:
(with the above as well)
new HashSet({2, 3, 5, 7, 11, 13});
new ArrayList({"foo", "bar", "baz", "quux"});
new HashMap({{"key1", "value1"}, {"key2", "value2"}});

new HashSet(Arrays.asList(2, 3, 5, 7, 11, 13));

So much cleaner IMO.

There's also this for the last one:
new HashMap() {{
this.put("key1", "value1");
this.put("key2", "value2");
}};
* In many more cases it might be useful to have a shortcut to
if (x == null) value = this else value = that
so how about more generally allowing x.foo?ifNull -- the ? clause
is executed whenever x is null and the method call when it's not.
Or just allow x?expression1:expression2 for non-Booleans testing
for null.

x == null ? expr1 : expr2 is not at all verbose and much easier to
distinguish on scanning.
* Full closures.

Someone beat you to this.
* Allow subclassing an enum with the subclasses able to REMOVE (not
add!) values.

Very ugly.

Most of your features have little chance of being added since some are
doable in existing syntax anyways, and many of them would require making
deep changes for what I see as little value.
 
M

Mark Space

Harold said:
There's probably plenty of these floating around already, but here's

* Sort-of structural typing. Any object can be used where an interface
type is expected if it has the right set of method signatures, whether
or not it "implements" the interface using that keyword. (It still must

Interesting but not my cuppa. Break down and just type "implements" on
your class please.
* Allow extending final classes, subject to the constraint that new
instance fields cannot be defined and none of the final class's methods

Feels yicky. Consider composition instead of inheritance.

* Add an unsigned byte type.

Probably too late for this, but sure it would have been handy.
* Add some way to specify that something should never be null. Perhaps a
! or a * before or after the variable name or type name.

Does this require a runtime check on each assignment? Could be a lot of
overhead...
* Allow omitting the names of unused parameters. Common cases would
include:

I agree with Joshua, typo-city.
* Constructor type inference. Also allow an alternate constructor

Generic methods can do this now. I think it might be handy for Sun to
provide some generic methods to initialize the classes you mention.
Rolling your own for your own classes isn't hard.
* Disallow public constructors on abstract classes. They are not
callable by any more code than a protected constructor anyway.
super();?


* When a type has a one-argument plus() method, + can be used when the
left hand operand is of that type and the right hand operand is of an

OK with me but apparently this ran into technical troubles. Too
complicated for now.
* Clean up ImageIO and JAI. A lot of the code in these throws various
RuntimeExceptions in response to seeing something it doesn't like in

At least they shouldn't be throwing unsubclassed RuntimeException. Are
they?

* Inverse to the above, get rid of some awkward checked exceptions or
make them RuntimeExceptions. Culprits include NoSuchAlgorithmException

Probably also a good idea.
* Dead code in a method should be a warning, not an error.

Sure, makes debugging hard. Or at least allow a switch to make it a
warning during development.

A good IDE will comeent out dead code in a hurry though...
* Hiding a local variable with a nested-scope local variable should be a
warning, not an error.

Dunno about this, just pick a different variable name.
* Provide a better way to deal with OutOfMemoryError or low memory in

Hmm, I haven't looked at any existing frameworks for using
SoftReferences, but I'd head over to Apache.org and take a look.
Personally I think the garbage collector is probably about as
complicated at Sun can handle at this time.
the OS will give it. In this, it may maintain a "load factor" similar
to a HashMap for the entire heap, trying to keep it near 75% full, and

It's been discussed here, at least. I don't know how hard this would
be, but I'm in favor of it, Sun willing. The incremental garbage
collector gets pretty close to this, imo. It slowly prunes out un-used
objects as the program runs, thereby keeping actual memory footprint to
a minimum. Used objects can't be pruned by anyone, of course.
* Provide a nicer way to deal with resource release. Possibly have a
Releasable interface added, which specifies a dispose() method and

I think they already have as nice a method as they can. Use finalize()
if you must. Personally I set all my windows to "DISPOSE_ON_CLOSE" so
they just to it for me.

* Especially given the above: a shortcut for new Runnable() { public
void run () { ... }}. Let a brace block appearing where an expression

Well... closures may be on their way. Let's hold out for the correct
solution.
* Allow array literals in expressions other than assignment RHS.

Java arrays need a type, I think, which isn't aways inferable from the
context. Not sure how well this would work in practice.
* Have array constructors added to the collection classes:
new HashMap({{"key1", "value1"}, {"key2", "value2"}});

This would be handy, but what type are those arrays?
* Add java.lang.Pair<K, V>. Make some existing classes Pair

This is so easy to roll your own, I'm sure that's why no one has done it
for you.
implementations, e.g. Dimension extends Pair<Integer, Integer>,

I think if Sun started messing with these, they'd go the other way.
Dimension is slow. Use the individual X and Y methods instead.
* [int x]; defines a final box containing an int, an instance of a
SwingUtilities.invokeLater({foo:setVisible(true);});

Or you could substitute a "." for the ":" and save yourself a lot of
useless code. :rollseyes:
* In many more cases it might be useful to have a shortcut to
if (x == null) value = this else value = that

I'm with Joshua, the ternary operator is fine.
* Another source of boilerplate code is:
Let an alternate form be:
try {
Type t = someExpressionThatMayThrow();
} continue {
t.doSomething();
} catch (FooException e) {
...

No opinion. I've written your "yuck" code myself. It's really not that
common though, usually just doing file IO, which can be encapsulated
pretty well.
* Full closures. Let anonymous inner classes access nonfinal local

JSR is done, I think. I'm not really fond of more anonymous classes
though, I wish something more efficient could be used.

* Object.identityHashCode().

An un-overridable hashcode? I guess, though I wonder if all platforms
can always provide an "identity" for each object. What happens when an
object gets shipped across a network several times? Will it loose it's
identity?

* Equalizer to go with Comparator, provides equals and hashCode by

A lot of libraries need to change to use this. Sure, if someone is
willing to do the work.
* WeakValueHashMap, LinkedWeakHashMap, and LinkedWeakValueHashMap.
These would all be useful implementing caches where you want the

I think the Apache folks may have a framework or three. Didn't actually
check though...
* ReferenceQueue.addListener(Reference r) to let you automatically do

No opinion.
* Allow subclassing an enum with the subclasses able to REMOVE (not

Probably going to break a lot of stuff and make enums a lot less
efficient. Please roll your own removable enum.
 
A

Andreas Leitgeb

Harold Yarmouth said:
* Sort-of structural typing. Any object can be used where an interface
type is expected if it has the right set of method signatures,

There isn't any real distinction between marker interfaces
like Cloneable and "normal" interfaces. As long as
obj instanceof SomeEmptyInterface is not made trivially true
(which of course it shouldn't be under any circumstances)
it's also not possible to make obj instanceof FooInterface
appear to be true, just based on existence of some methods.

And any other type of compatibility inconsistent with the
instanceof-operator is right out of question, anyway.

I don't think this fits into Java.
* Allow extending final classes, subject to the constraint that new
instance fields cannot be defined and none of the final class's methods
can be overriden regardless of whether the method is explicitly "final".
Essentially allows wrapping final classes.

Yes, yes, yes! Not sure, if you got that idea yourself, or
from reading <[email protected]>.
(in case google distorts it: "slrngfmc50.4jb.avl" is the part
before the "at")
As I brought it, it would subsume the functionality
of proposed typedefs plus add some more useful usecases.
* Add an unsigned byte type.
adding unsigned primitive types of all sizes generally would be
cool, but then Java should also spend some extra effort on sane
semantics:
e.g. any negative value would have to be trivially smaller
than any unsigned value, and an unsigned value beyond the
range of the other signed value would have to be trivially
always larger. That is grossly unlike C's behaviour for
operators with mixed-signedness operands. And that isn't
yet all to it (what sign would be the result of mixed-
signedness addition?)
Complicated as that would become, I doubt it has any chance
of getting into 7.0. I fear the problem about signed byte
is too fubar'ed to be repaired anytime soon.
* Add some way to specify that something should never be null. Perhaps a
! or a * before or after the variable name or type name.

Sounds cool, principially, but I don't like to add a "line noise
character" for that feature, but rather some keyword.
It wouldn't be possible to create arrays of non-null types,
unless there'd also be syntax to pre-initialize the elements.
* Allow omitting the names of unused parameters. Common cases would include:
public void ActionPerformed (ActionEvent) {
Really little gain, given that most of the times one really should
do something with the value (especially in catch-blocks), and in
other cases, the name of some parameter gives a hint as to what
is expected there, (and may be used as such by overrides).
Also, for unused method-arguments, the name is usually referred to
by the javadocs. You do javadoc your methods, don't you?
* Constructor type inference. Also allow an alternate constructor
syntax that doesn't repeat the class name, say using * in its place.
May be useful in a few special cases, but sends a wrong message in
most other cases:

One shouldn't really use HashMap<...> typed variables in one's
code, but rather Map<...> typed ones for more flexibility lateron
(just assign a TreeMap instance to the Map variable instead of a
HashMap and don't bother with having to change all the variable's
types.)

The proposal would encourage use of:
HashMap<...> hashMap = new *(...);
which would be a bad thing.

(This argument doesn't apply against typdef'ing HashMap to MyTypeMap,
since the alias could still be quite easily changed at one place, if
so needed.)
* Disallow public constructors on abstract classes. They are not
callable by any more code than a protected constructor anyway.
Indeed, for abstract classes' constructors: public is equivalent to
protected. So public could be mapped to protected for those. I see
no gain from that mapping, and even much less gain from demanding
programmers to change "public" to "protected". Since they are in
that case equivalent, it means it doesn't really narrow accessibility.
(which otherwise is a generally good thing to do, of course)
* When a type has a one-argument plus() method, + can be used ...
operator overloading through special method names and signatures.
Quite a controversial topic.
* Clean up ImageIO and JAI. [w.r.t exceptions]
* Inverse to the above, get rid of some awkward checked exceptions [...]
No opinion on those
* Dead code in a method should be a warning, not an error.
agree! It came up already a couple of times in this group.
* Hiding a local variable with a nested-scope local variable should be a
warning, not an error.
also agree, but without extra exclamation mark :)
* Provide a better way to deal with OutOfMemoryError or low memory in
general, as well as a JVM mode in which a program can use as much
memory as it needs, but the VM will also not greedily take everything
the OS will give it.
long overdue... (i.e.: agree! )
no value throws OOME unless the OS won't give the Java process memory
it needs.

It is still good to *be able to* limit a process' memory footprint.
It just shouldn't be limited by default and then also too low (as it is now)
I guess, you meant it that way, too.
Add System.addLowMemoryListener() or similarly. Listeners are notified
if free memory dips below some threshold, running on a temporary
worker thread and perhaps doing things like flush caches.
That's the wrong approach. Rather let the application use
SoftReferences:
* Provide a nicer way to deal with resource release.
Hmm, beats me.
I think that this lack of hookability into the GC's actual
results is mostly by design. I do not entirely understand
that design, either. I looked at the implementation of
WeakHashMap, and while it gets the list of Objects on request
(which is done in size(), isEmpty(), and a couple of other
accessor methods), but there indeed is no way to be notified
instantly upon GC (whenever that runs).
I can only guess, that they don't want the little kids to drop
cookie-crumbs *instantly* after having hoovered the room :)
* Especially given the above: a shortcut for new Runnable() { public
void run () { ... }}. Let a brace block appearing where an expression
is expected be equivalent to the above, with the contents of the
brace block in place of the ellipsis (...). Then you can do e.g.
SwingUtilities.invokeLater({foo.setVisible(true);});

That appears to touch the "closures" topic, even though it's
just suggested as syntactic sugar for certain anonymous classes.
Also allow this short form to throw checked exceptions, which it
will be assumed the calling code might throw. (So
SwingUtilities.invokeLater({myOutputStream.write("foo");});
would be treated by the compiler as able to throw IOException,
though in fact it would arise in another thread entirely;

There is no sense for "SwingUtilities.invokeLater" to declare to throw
any checked exceptions. Unlike C's "fork", the SwingUtilities.invokeLater
doesn't "return twice": all the created threads don't know nuts about
SwingUtilities.invokeLater. They just exist, and run run() as their
toplevel method.
on other hand, using Runnables as custom control blocks like
the Releasable.do() suggested above would result in the
exception being thrown out of do() and into the code that
physically contains the block.

This is an entirely different situation, and yes, that one does
make sense. Such a custom block structure would most likely not
take a Runnable, but rather a
HaroldsRunnable said:
* Allow array literals in expressions other than assignment RHS.
I think there are a big lot of caveats that need to be dealt
with. It starts, where the Compiler needs to know, just what
is the Element-type. It can infer it in the "assignement-RHS"
case, but not safely elsewhere.
* Have array constructors added to the collection classes:
If the previous item has a solution, then this one can
easily be done by appending .toList() to the array-literal.
(leaving out the HashMap here, which is a different beast)
* Add java.lang.Pair<K, V>. Make some existing classes Pair
implementations, e.g. Dimension extends Pair<Integer, Integer>,
possibly also Rectangle extends Pair<Dimension, Dimension>,
Map.Entry<K,V> extends Pair<K,V>, etc.
Two-element array literals allowed where Pair is expected and
produce Pair literals.
The Rectangle makes me feel uneasy about it. As a Pair of pairs,
it probably could no longer directly access its own data, but
would have to maintain two pointers to separate Dimension instances.
But then again, I may be wrong...
Is it possible to extend a class with two references, but implement
it all inside the subclass, avoiding even the space wasted for
the inherited fields? I don't think so.
* [int x]; defines a final box containing an int, an instance of a
Box<T> with T == Integer, which has methods T get() and void set(T).
One can then do e.g.
[JFrame foo = new JFrame()];
...
SwingUtilities.invokeLater({foo.get().setVisible(true);});
given the above runnable-literal suggestion.
Add a : operator that expands to ".get()." and we have:
SwingUtilities.invokeLater({foo:setVisible(true);});
Almost a closure, there!
But much yuckier syntax ... I don't see the gain at all.
* In many more cases it might be useful to have a shortcut to
if (x == null) value = this else value = that
so how about more generally allowing x.foo?ifNull -- the ? clause
is executed whenever x is null and the method call when it's not.
Or just allow x?expression1:expression2 for non-Booleans testing
for null.
How would this behave with Boolean x= new Boolean(false); ? :)
The object is not null, but means false (after auto-unboxing).
* Another source of boilerplate code is:
try {
Type t = someExpressionThatMayThrow();
} continue {
t.doSomething();
} catch (FooException e) {
...
}
I saw this discussed also in another language's group.
(using different keywords, but to the same semantics)

I do not see the usecase as all that common, myself.
I wouldn't oppose it, either.

Another entirely different approach could be an
"exemptfromtry { ... }" block inside the try-block.
That would allow for mixing catching and non-catching
blocks inside the try, and thus have all non-exempted
blocks inside the try guarded by the same catch-clauses.
The Compiler would create several ranges to the exception-
table, one for each part between two exemptfromtry's, all
pointing to the same handler-bytecode address.
Just a thought.
* Full closures.
Quite a controversial topic.
* Object.identityHashCode().
I could have sworn that I saw some static method of some
utility class that returned the original hashCode for any
instance. Probably some reflection thing. Anyway, wasn't
able to find it now. Even if it doesn't exist, I think
a static method in a reflection-related class would be a
better approach, than adding it to Object.
* Equalizer to go with Comparator, provides equals and hashCode by
proxy, can be used with HashSet and HashMap to provide substitute
key equality and hash functions the way Comparator can provide a
substitute compareTo for TreeSet and TreeMap.
Never so far found a need for that. Is there any which
using a wrapper for the Key object cannot solve?
Comparator mostly exists because not all classes are
per se Comparable, but all classes are "Equalizable".
* WeakValueHashMap, LinkedWeakHashMap, and LinkedWeakValueHashMap.
These would all be useful implementing caches where you want the
mapping to go away if the value is no longer in use,
So far it looks like WeakHashMap<Key,WeakReference<Value>>
wrapped such as to transparently map the case of a nullified
WeakRef to a "not found" condition.
WeakValueHashMap already sort-of exists in one under-the-hood bit
of non-user-reusable Java: the implementation of string interning,
starting whenever they finally got it to GC unused interned strings.

Maybe they even do it with Soft- or WeakRefs.... Actually I wasn't
really sure, that interned Strings really had a chance of being collected.
* ReferenceQueue.addListener(Reference r)
Hooking into the GC has come up quite frequently here, and most likely
it's a bad idea in the first place.
* Allow subclassing an enum with the subclasses able to REMOVE (not
add!) values. An enum that can be any of X, Y, or Z is a subtype,
rather than a supertype, of one that can be any of X, Y, Z, A, or B
because it is substitutable for the latter but not vice-versa;
ok so far.
actual created classes would be Super with subclasses Sub, Super.A,
Super.B, Super.X, Super.Y, and Super.Z and subclasses of Sub Sub.X,
Sub.Y, and Sub.Z, with some change to the underlying code to not treat
Sub itself as an enum value for Super and to treat Sub.X, Sub.Y, and
Sub.Z as convertible to their Super counterparts.

I don't get that at all. What Subclasses are you now talking about?
Each instance of a given enum can be really one of an anonymous subclass
of the enum, but needs not. In
enum Foo { X, Y, Z}
There is only one class-file: Foo.class. no Foo$X.class, ...

The case I could imagine was a SubEnum, that allowed a free
selection of a subset of BaseEnum's instances, and otherwise
behaves like a wrapper based on my own class-wrapper proposal
(messageid given in my comment to your second item).

E.g.:
enum Base { X, Y, Z { ... }; ... }
enum Sub wrapspartsof Base {
Y,Z;
Sub foo() { return Z; } // ok, implicitly castable to Sub
//Sub bar() { return X; } // would fail: X is not a Sub
//private int count; // would fail: no extra fields allowed.
}
//Base.X.foo(); // fail: no such method.
//Base.Y.foo(); // fail: no such method. (Compiler doesn't know
implicitly, which of Base's possibly countless
wrappers is meant here)
Sub.Y.foo(); // ok, named as Sub.Y, it's of type Sub ...
((Sub)Base.Y).foo(); // ok, Compiler knows compatibility to Sub,
so method foo() is known to be Sub.foo()
Sub.Y.foo(); // ok,
Base.X instanceof Sub // false
Base.Y instanceof Sub // true!
Sub.Y instanceof Sub // trivially true
Sub.Y == Base.Y // true; it's still the same instance afterall.
(all ditto with Z for Y)
Sub sub=...; switch (sub) { case Y: ... case Z: ... } // ok, all cases handled.

* Now finally, I add one more idea to the list:

Distinguish between "using" and "implementing" an interface with
respect to accessibility.
The point being to allow to publish an (internal) interface
for return values (cookies), that foreign code may use as type
for variables, but not in "implements"-lists for classes.

One use would be for a library to return "handle" objects
from some of its methods, and accept these handles as parameters
to other methods, allowing user-code to do well-defined
tasks on these handles outside the library, but preventing
foreign code from implementing own classes for that interface
(and especially: possibly feeding those back to the library)
There are of course other ways to achieve that, like keeping
a WeakHashMap of valid handles, but that's far less elegant.
 
J

Joshua Cranmer

Harold said:
* Provide a better way to deal with OutOfMemoryError or low memory in
general, as well as a JVM mode in which a program can use as much
memory as it needs, but the VM will also not greedily take everything
the OS will give it. In this, it may maintain a "load factor" similar
to a HashMap for the entire heap, trying to keep it near 75% full, and
a JVM option to tweak this may exist. Higher gives poorer GC
performance but leaves more RAM for the OS; lower gives better GC
performance but uses more memory; no value throws OOME unless the OS
won't give the Java process memory it needs.
Add System.addLowMemoryListener() or similarly. Listeners are notified
if free memory dips below some threshold, running on a temporary
worker thread and perhaps doing things like flush caches.

On this topic in specific:

The JVM has years of experience with tuning GC; the JVM's garbage
collector (all 3 of them?) is one of the best out there. One lesson of
the past few decades is that manual memory management is extremely
difficult to get right; a garbage collector which has been worked on for
over a decade is probably going to be managing its resources better than
any custom scheme you come up with for your application.

SoftReferences in particular are means of this: if you hold a
SoftReference to an object, you are telling the garbage collector that
you are willing to give up the reference if memory resources are getting
low. Since it directly interfaces with the garbage collector, it is
likely to be far more performant than listening for low memory and then
flushing caches.

Consider the case where some resource is consuming memory at a fast
rate, e.g., downloading a large image over a fast connection.

Under a SoftReference scheme, as the garbage collector notices that
memory is getting tight, it will start finding and freeing the soft
references when trying to allocate new memory.

Under a listener scheme, these have to happen, in order:
1. The GC will have to notice that memory is getting tight.
2. The GC will have to tell the event dispatcher that memory is tight.
3. The event dispatcher will have to callback the event listeners.
4. The event listeners will have to free the caches.

These are not happening on the same thread; in the right conditions, the
GC will run out of memory before the event listener has the chance to
free it.

The memory usage of the JVM, etc., can be controlled from the command
line with appropriate -X options; I don't know the degree of
specificity, but I'm sure you can at least somewhat control the
aggressiveness of reclaiming memory before requesting from the OS.

In short: I'm sure the people who worked on the JVM GC are much more
knowledgeable in the topic than you or I. Trying to outwit them will
almost definitely result in failure.
 
M

Mike Schilling

Joshua said:
I smell a lot of unexpected bugs coming from this. Note that if you
already have the right method signatures, you could just take the
interface onto the implements list.

I see it as a maintenance nightmare. If methods are added to an
interface, I'd like to be told about it when its implementors fail to
compile, not when code which tries to use some other class as that
interface fails to compile. The may be appropriate for Ruby, but not
for Java.
 
M

Mark Thornton

Harold said:
* Allow extending final classes, subject to the constraint that new
instance fields cannot be defined and none of the final class's methods
can be overriden regardless of whether the method is explicitly "final".
Essentially allows wrapping final classes.
As you wouldn't be able to override hashCode and equals the contract of
these methods would be broken.
* Add some way to specify that something should never be null. Perhaps a
! or a * before or after the variable name or type name.
An annotation is being proposed to mark parameters etc as non null.

Mark Thornton
 
M

Mike Schilling

Andreas said:
Indeed, except it is in the same package as the wrapped class :)

Then you'd have the source code for the original class, and could
comment out "final". :)
 
A

Andreas Leitgeb

Mark Thornton said:
As you wouldn't be able to override hashCode and equals the contract of
these methods would be broken.

No it wouldn't. Just because the following things would be
forbidden in such a wrapper class:

* overriding of any methods (overloading still ok)
* implementing any interfaces
* adding non-static fields
* accessing any members of the class, that any other
class in the same package of the wrapper couldn't
also access.

(That should cover all things that could change the
personality of an instance. I.e. things which could
make a baseclass instance be distinguishable from a
wrapper instance, (except for .getClass() and
"instanceof wrapper") if wrapper were a normal subclass
and both instances would be accessed from a baseclass
typed reference.)

The expression (new Wrapper()).getClass() would return
the baseclass!

Wrapper instances are exactly like baseclass instances, so
baseclass instances can be treated like wrapper instances
(and therefore be assigned to wrapper typed references).

If the wrapped baseclass was not final, then you can even
derive from a wrapper class, and that may override all
methods of the wrapper and of the baseclass. That subclasses'
instances are then implicitly castable to the direct wrapper
and to the base class but not backwards. They are even
implicitly castable to other wrappers and wrapper-wrappers
of any class up the hierarchy tree! That's the transitivity
of implicit castability.

Instances of wrappersub would be different from instances
of some plain subclass of baseclass, just like two sibling
classes are per se different.

e.g.: (quoted words are meta names used in for easier referral)
HashMap<K,V> // "baseclass"
class MyTypeMap<T> wraps HashMap<T,MyType> { // "wrapper"
public synchronized MyType getAndSet(T key,MyType val) {
gets and sets...
}
}
class SubMap extends MyTypeMap<Integer> { // "wrappersub"
public MyType getAndSet(Integer key,MyType val) {
do some extra checks
return super.getAndSet(key,val);
}
public MyType put(Integer k, MyType v) {
do some checks
return super.put(k,v);
}
}

Wrappers can also be wrapped, but then neither the methods of
baseclass nor of first wrapper may be overridden in the second
wrapper.

An annotation is being proposed to mark parameters etc as non null.
Good news. Lets see how that works out.
 
A

Andreas Leitgeb

Mark Space said:
Feels yicky. Consider composition instead of inheritance.

The way I proposed it a week or so back, the wrapper's instances
would fulfill the "is a" relation even more strictly than a
subclass' instance does.
Does this require a runtime check on each assignment? Could be a lot of
overhead...
I dislike the proposed syntax, but I'd expect it to work like
generic types: The compiler knows them, and tkes care of them,
such that casting a normal type to a non-null type would only
work by branching away the null case:
e.g. (with yucky syntax)
Integer* nnIntRef=null; // fails to compile
Integer intRef=...; Integer* nnIntRef=intRef; // fails

Integer intRef=...;
Integer* nnIntRef;
if (intRef != null) { nnIntRef=intRef; } // ok.
nnIntRef= (intRef==null)? 42 : intRef; // also ok.
if (intRef == null) break; nnIntRef=intRef; // also ok.
This does require some dataflow analysis by the compiler...
super();?
That's equally ok with public and with protected, anyway.
 
M

Mark Space

Andreas said:
Integer* nnIntRef=null; // fails to compile
Integer intRef=...; Integer* nnIntRef=intRef; // fails
This does require some dataflow analysis by the compiler...

What about:

Map<String,Integer> map = new HashMap<String,Integer>();
nnIntRef = map.get("Blarg");

That's equally ok with public and with protected, anyway.

Right. I was thinking package-private instead of protected, for some
reason. Carry on.
 
A

Andreas Leitgeb

Mark Space said:
Map<String,Integer> map = new HashMap<String,Integer>();
nnIntRef = map.get("Blarg");

It would fail of course. get returns a normal nullable Integer.
If there were a throwing variant of get(), and if the valuetype was
non-null Integer, then the returntype of that get() would be non-null
integer und thus could be assigned to such a variable. Easy, innit?
 
R

Roedy Green

* When a type has a one-argument plus() method, + can be used when the
left hand operand is of that type and the right hand operand is of an
argument type for which the former has a one-argument plus() method.
This + binds with the usual precedence for binary + and x + y is
simply an alternate way of saying x.plus(y


Please NO. How about circle plus or some other additive symbol. You
NEED to know if a plus is primitive or user defined.
 
R

Roedy Green

* Dead code in a method should be a warning, not an error.

similarly a throws in a method that does not throw. It is part of the
signature for future reference or to leave the option open in an
override.
 
M

Mike Schilling

Roedy said:
similarly a throws in a method that does not throw. It is part of
the
signature for future reference or to leave the option open in an
override.

That works fine now.

import java.io.*;

class Throws
{
void method() throws IOException
{
}
}

compiles with no errors (or even warnings) in 1.4. Perhaps you're
thinking of trying to catch an impossible exception, e.g.

import java.io.*;

class Throws
{
void method() throws IOException
{
try
{
int i = 12;
}
catch (IOException ex)
{
}
}
}

This does fail with

Throws.java:11: exception java.io.IOException is never thrown in body
of corresponding try statement
catch (IOException ex)
^
1 error
 
H

Harold Yarmouth

Joshua said:
I smell a lot of unexpected bugs coming from this.

How so?
Note that if you already have the right method signatures, you could
just take the interface onto the implements list.

Not if the class is not under your control for whatever reason.
No, essentially makes final classes worthless.

Not true. It won't be possible, under that proposal, to break e.g.
String by either changing the behavior for clients working with just
"String", or Integer by e.g. creating a super-bloated subclass that will
gum up the works and get stuck in the intertubes because it's so fat. :)

I should add that nonpublic fields and methods would not be visible to
the wrapper, unlike what's normally the case. (I mentioned that later in
my post, but it seems to be missing from the above, oddly enough.)
How about adding a @NotNull annotation and then running your own static
checker?

Awkward and clunky. More typing than a single punctuation mark, by a
factor of eight -- nearly an order of magnitude. Doesn't "just work"
like existing type-checking, but requires manually linting with some
special tool that you'd first have to find someplace, install, and learn
to use. And so forth.

At minimum it would have to be checked by straight javac, as @Override
is now. But even then, nearly an order of magnitude more typing? This
would be used much more frequently than e.g. @Override, probably on a
large minority of all field, variable, and parameter declarations, if
not an actual majority.
* When a type has a one-argument plus() method, + can be used when the
left hand operand is of that type and the right hand operand is of an
argument type for which the former has a one-argument plus() method.

[ ... ]

A poor way

No, it is not, and I will thank you to stop gratuitously insulting me.
You, sir, have an attitude problem.

If you have nothing pleasant or constructive to say, might I suggest
that you keep your mouth shut in the future?
Except many other languages use == as equivalent to the equals method
and === as equivalent to Java.

Other languages are irrelevant.

You aren't posting to discuss this, are you? You're just posting to shit
all over it and generally be boorish. Shame on you.
Also note that you'll fall down with nulls here.

That might require a special case, treating x === y as (x == null)?y ==
null:x.equals(y) than just x.equals(y) perhaps.

All the more reason for collapsing it to just a few characters, if you
ask me.
Judicious use of WeakReference and SoftReference helps, and there are
also suitable APIs in java.lang.management that already provide much of
this functinoality.

Java.lang.management is not covered by any of the tutorial or similar
documentation that's out there, and is just one package buried in a list
of literally hundreds in the API docs, so you'll forgive me for not
being familiar with it.
* Especially given the above: a shortcut for new Runnable() { public
void run () { ... }}.

[ ... ]

I take it you haven't heard of closures.

Sure I have. Did you even bother to read my entire post before clicking
"Take A Crap All Over It And Send" in your news reader?
* Allow array literals in expressions other than assignment RHS.
Why the devil is foo(1, "string literal", 3) allowed but
foo(1, {array, literal}, 3) is not, even when foo's second
parameter type is Object?

new Object[] {array, literal} ?

Works, but if the array doesn't need to be modifiable, creates a
wasteful duplicate every time.

If you're worried that letting immutable arrays get used in such
contexts could somehow cause problems, keep in mind that this is already
possible:

int[] foo = {1, 2, 3};
....
fooMethod(1, foo, 3);
new HashSet(Arrays.asList(2, 3, 5, 7, 11, 13));

So much cleaner IMO.

You're joking, right? It makes an unnecessary temporary collection. In
fact, all the collections really ought to have constructors that take an
Iterable and just iterate over it. In many cases, they can be
implemented in all of two lines of code:

super();
addAll(iterable);

given that addAll gets broadened to allow any iterable. Or at least

super()
addAll(collection);
There's also this for the last one:
new HashMap() {{
this.put("key1", "value1");
this.put("key2", "value2");
}};

Now you're making a whole extra class. How efficient.
x == null ? expr1 : expr2 is not at all verbose and much easier to
distinguish on scanning.

It's slightly more verbose and no easier to scan for.
Someone beat you to this.

Now you've gone from "nonconstructive" to "just plain bloody-minded".
Very ugly.

In your humble opinion.
Most of your features have little chance of being added

In your humble opinion.
many of them would require making deep changes for what I see as
little value.

Perhaps you should make an appointment with your optometrist, then. Many
small wins add up to eventually equal some big ones.

Please don't bother to write back until you have something genuinely
constructive and useful to say. Slagging something without suggesting
improvements (or slagging people, at all) is pointless and a waste of
everybody's time.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,744
Messages
2,569,484
Members
44,903
Latest member
orderPeak8CBDGummies

Latest Threads

Top