7.0 wishlist?

H

Harold Yarmouth

Andreas said:
You're right there. An application might e.g. save precious data to
a disk-file and only then drop it, rather than have it just irrecallably
eliminated by the gc through softrefs.

Sun either isn't aware of such situations (unlikely), or it's just too
difficult to implement the right thing (more likely) - involving
problems that we aren't yet aware of.

I'm not asking them to create some sort of auto-persistence that can
swap some data out to disk and back in. Heck, the OS page system should
already do that, and that in turn is an argument for infinite default -Xmx.

I was asking them to provide a callback to let the programmer do
something like that if they wanted to. Automatically saving and closing
the least recently touched open document, for example, is app-specific
behavior that could be done given such a callback. (The app could even
retain the document window appearance as a facade, retaining only a
pixel array, and load the real McCoy back in if the user touched the
document window. It would then not seem to have mysteriously closed
itself, but simply to have been slow to access. And the app can be
smarter than the OS pagefile OR the JVM about what makes a sensible
chunk to swap out.)
 
H

Harold Yarmouth

Andreas said:
Implementing an interface is a property that applies
to an instance. A given instance can be queried
about whether it implements a certain interface.

If you wrap a Foo, implementing an interface doesn't alter the wrapper's
semantics when treated as a vanilla Foo, EXCEPT for code that uses
casts, reflection, or instanceof. Code that does so is inherently more
fragile than code that is more type-safe and uses polymorphism. If your
wrapper breaks such code, you'd find out and avoid using it there. If
fragile code with security significance proved subvertible this way, it
would indicate a latent flaw in that code's design that had existed anyway.
Regarding the necessary restrictions for a wrapper class:
An instance is *not* supposed to know whether the
baseclass or the wrapper was used for its creation.
This detail is crucial to the safety of the "upcast"
from baseclass to the wrapper.

Upcasting from something that doesn't implement some interface to
something that does is already done and is safe.

I think you're worried that the Foo constructor will use instanceof to
decide if it's a wrapped Foo and then fool around somehow if it is, or
if it isn't, or just generally behave differently. Even then, the upcast
shouldn't do anything to change that later.

That would be a badly coded constructor. People sometimes write bad
code. You can't prevent it without stifling everything.

If you really want instanceof to "behave" when the wrapper is treated as
a Foo, instanceof semantics could be changed:

* For non-wraps, same behavior as now
* For wraps, treats as unwrapped type, EXCEPT when the compile-time type
of the reference is the wrapped type, or an interface it implements that
the unwrapped type doesn't.

The wrapped Foo implementing Bar looks exactly like a Foo to Foo users
it's passed to, and still looks like a Bar to Bar users it's passed to.
It's two-faced, but that's just another form of data-hiding. Similar
uses to private inheritance in C++.
Maybe you have a different design in mind. I tend to stick
to mine, until I find one superior to it in all the points I'm
interested in.

See above. Though you might not be comfortable with fiddling with
instanceof's semantics.
 
A

Andreas Leitgeb

Since I wrote that, I noticed a flaw in my design, so
I have to revise some of my statements. Nevertheless
that flaw doesn't have any impact on interfaces.
Upcasting from something that doesn't implement some interface to
something that does is already done and is safe.

So far only, if the instance was originally of a class
that implemented the interface.

What I wanted to achieve is, that an instance of some class
could be (safely) casted to any wrapper of that class.

If there was:
class Base implements Foo { ... }
class Wrap1 wraps Base { ... }
class Wrap2 wraps Base implements Bar { ... }
Object o = new Base();
then:
Foo f=(Foo)o;
is simple, because the instance at hand knows it is a "Base"
and as such implements "Foo".

otoh, what does it take to use the instance in "o" as a "Bar"?
At the very least, one would have to inform the object itself,
where to find the missing methods (namely in "Wrap2"). This
particular problem only occurs if we allowed the wrappers to
implement new interfaces.
If we left out the new interface aspect, then the only way to
access the new methods would be by a cast to the particular
wrapper and it would be clear where to find the methods.
The wrapped Foo implementing Bar looks exactly like a Foo to Foo users
it's passed to, and still looks like a Bar to Bar users it's passed to.
That's easily said..., but (I think) impossible to make work.

PS:
The design flaw I wrote about deals with wrapping generics.
It's not one that spoils it all, but impairs certain usecases
I had in mind for the feature..
 
H

Harold Yarmouth

Hendrik said:
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Harold Yarmouth schreef:

Please keep in mind that telling people what to do on Usenet generally
doesn’t work.

Please keep in mind that being rude to me without justification
generally doesn't work.
How so? Isn’t {array, literal} supposed to create one as well? The
method expects an array, after all. Oh, I see, it doesn’t. But even if
it expects an Object, there has to be an Object, so the array needs to
be created.

In the case that it can be immutable, there could be just the single
instance. As things stand, the only way to achieve that is to slap it in
a static final constant. In many cases this is the best practise anyway,
if the array makes sense to name and make easily changed by programmers.
But in some cases, it really doesn't. For instance if you have an array
of the hex digits used in only one place in your code, it's never going
to change and it's pretty obvious what it is (rather than being a "magic
value") if it occurs as a literal at point-of-use. It's just that
currently it can't really, without using the new syntax that will make a
copy every time.

Of course, some arrays (such as the hex digits) might pop up separately
in various classes. Some sort of "interning" of identical array literals
would also be potentially useful.
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);

I don’t get it, foo is mutable.

It shouldn't be, since it's a direct reference to a literal (rather than
to "new int[]{1, 2, 3}".
True, but ISTR that in Java, creating and abandoning a lot of small
classes if more efficient than clinging to one big class.

That's not the issue. The issue is that copying a collection is O(n) and
copying it twice thus can be significantly slower than copying it once
if n gets large enough.
How would this be less efficient? You’re creating a HashMap anyway.
Oh, you mean the extra class object. I doubt it will make a difference.

It works, but it's crude and has crummy and verbose syntax.
 
H

Harold Yarmouth

Joshua said:
How many interfaces are there in core Java code alone? With these
change, my class would effectively implement dozens of interfaces that I
didn't know exist and whose contracts I am probably violating.

I find that unlikely, since method names and signatures would have to
match "sufficiently well" (same name, contravariant argument types, and
covariant return and throws types).

Even if it did, it would be understood that only by putting "implements
Foo" on a class is its author making any claims about their code
adhering to Foo's contract. People use it as a Bar, if it has Bar's
methods but no "implements Bar", at their own risk.

Just as they make unchecked casts of generic collections at their own
risk right now, and prefer to avoid doing so whenever possible.
Then how do you propose to add such features as LHS-based operations,
like 2 * matrix?

For operations that are ... what is the term? Commutative? It can look
for the "plus" method in the RHS if the LHS lacks it. Alternatively the
programmer has to do matrix * 2 instead -- big whup.

For division and subtraction, it would have to either give up or look
for the RHS to have plus and negated, or times and invert. Then
RHS.negated().plus(LHS), or RHS.invert.times(LHS). Sometimes that might
be inefficient. Sometimes it might even throw exceptions -- 2/matrix
would probably try to invert the matrix, then double every cell. If the
matrix isn't invertible (and it may not even be square) the invert
method will presumably throw something, or return null, which would make
the .times throw NPE.

But we already have math operations capable of throwing
ArithmeticException, so...
I'm sorry. I assumed you had been a denizen of this newsgroup for a
while and therefore had seen my copious commentary of operator
overloading in the past year or two (which has come up in at least three
separate threads).

A quick Google Groups search should have disabused you of that notion.
:) Not that it matters. If you've previously expressed distaste here
for operator overloading, that really should not mean that everybody
else has to refrain from discussing the subject here on pain of being
personally insulted by you. We should remain free to discuss what we
please, even topics that you might dislike, so long as they pertain to
Java. Given that you are not in charge or otherwise elevated to some
special status here that gives you the right to set topic rules, anyway,
and I strongly suspect that that is the case.

In simpler language, if you don't like operator overloading being
discussed here, perhaps you should go start up
comp.lang.java.programmer.moderated, with yourself as moderator, and say
"No discussions of operator overloading allowed" in its charter?
They are relevant.

They are irrelevant. We are discussing Java. If languages were not
allowed (by who? nobody has this authority anyway) to be too different
from one another, we'd probably all be sitting here discussing Java 7's
implementation of cons, car, and cdr for Chrissake.

Anyway, if you have a better suggestion, go ahead. = is right out
because changing the assignment operator to say := would break pretty
much every piece of existing code out there.

~= perhaps, for equals()?
This is the first suggestion I've seen that would have a very strong
chance of making it in (although not the first worthwhile one, others
were also worthwhile).

A left-handed compliment, at best.
Doesn't require any changes to existing libraries, the JLS, and the JVM.

But it is awkward and verbose.
It's not something I'll belabor, but most people would probably prefer
the second form merely because it obviates that x is an Object and not a
boolean.

Usually that would be apparent from context. Quite often, the very
preceding line will have resembled "x = foo.get("string");".
I have many problems with closures, and so do many others in this
newsgroup. My (and others') complaints are well-documented on this
newsgroup. I cannot feel any sympathy for you if you did not look to
gauge our reactions to basic

?

Your sentence dead-ends in mid-air.

And once more with emphasis, if you do not like discussions of closures
you're free not to read them. Launching a rant sprinkled with personal
attacks against someone for mentioning them in your presence is not
appropriate, adult behavior.

In a weird way, you remind me of the religious prudes that freak out
over people kissing in public, or over television programming they can
avoid with the click of a button on their remote control.

I didn't look to "gauge your reactions" because I shouldn't have to. I
should be able to expect civility so long as I have been civil myself,
and so long as what I write here is on topic here, even if you disagree
with my opinion.

Unfortunately, apparently I should expect rudeness instead in those
circumstances, not even just from you but from several people here.

Courtesy is dead; long live courtesy.
Knowing how enums are implemented, you'd basically have to change nearly
every aspect of implementation. I don't see how you could make this
possible:

public enum SomeEnum {
A { void foo() { "Foo!"; } },
B { void foo() { "Bar!"; } },
C { void foo() { "Ugh!"; } };
abstract void foo();
}

public enum Enum2 extends SomeEnum {
A, B;
}

since SomeEnum$A, SomeEnum$B, and SomeEnum$C inherit SomeEnum.

That has been discussed elsewhere in this thread.
 
H

Harold Yarmouth

Andreas said:
There are more technical problems to solve before this could even
possibly become a feature, like the instances' .value(), if e.g.
not C, but A was omitted. I do think it could be solved.
E.g. SubEnums would not be required to have a continuous range of
values starting with 0.

Enum values having numeric values that form a continuous range starting
with 0 is overrated anyway. I rarely if ever use this. I'd suggest not
only letting subset-enums violate this, but letting ordinary enums do so
at the coder's behest, i.e. let them override value to return whatever:

public enum FooFlags {
FLAG_X_WHATEVER {
public int value () { return 0; }
}
FLAG_X_MUMBLE {
public int value () { return 1; }
}
FLAG_Y_WHATNOT {
public int value () { return 2; }
}
FLAG_Y_WHOSIT {
public int value () { return 4; }
}
/**
* <p>The error flag.</p>
*/
FLAG_Y_FIDDLESTICKS {
public int value () { return 8; }
}
}

Clearly especially useful (especially along with EnumSet) for
object-oriented typesafe bitmasks that can easily be converted into
integer ones for export to native code or binary files and that can
easily be converted back again.
 
H

Harold Yarmouth

Hendrik said:
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Harold Yarmouth schreef:

I think you don’t understand.

I think I'm beginning to find unprovoked personal insults quite
tiresome. If Emily Post ever stumbled across this newsgroup, she'd go
white as a sheet!
Well, they should be.

No; the needed gamut of collection classes should be (and mostly already
is) in java.util.
 
A

Andreas Leitgeb

Harold Yarmouth said:
I'm not asking them to create some sort of auto-persistence that can
swap some data out to disk and back in.

I didn't mean that. I just gave another example of what a user could
do beyond GC's possibilities that he cannot(*) do without some way of
being directly notified of impending shortage of memory.

I could imagine another TrackableReference type that will
just be notified of the GC's wish of its destruction, and at
this point still has all the possibilities of full access to
the object to save precious data, or even to tell the GC:
"no, not this one this time, but nag again next time."

If all the TrackableReferences have refused their deletion and
no further SoftReferences are there to dispose, *then* an OOM
Exception may be thrown.

*: short of busy-looping threads watching some reference queue.
I was asking them to provide a callback to let the programmer do
something like that if they wanted to.
Yes, I understood exactly that.
 
H

Harold Yarmouth

Andreas said:
-Xmx cannot be infinite, because it governs the size of some internal
structures.

Those structures would need to be "growable". They probably already
should be, so large -Xmx with a program that (*this* run, anyway) stays
small won't produce inefficiency.

(Have they been using arrays instead of ArrayList? Naughty, naughty Sun!)
You can of course set that variable as the last statement of the
try-block. It's highly unlikely that isOk=true; will ever throw an
exception itself.

I don't think it even can, save maybe VMError, which is a showstopper
anyway, and would signal a bug in the JVM to boot. It certainly
shouldn't throw OOME or any of the usual suspects, since it requires no
memory allocation, or NPE, since reference/primitive assignment can't.

What it is is clunky and verbose, my complaint against several idioms
that might be streamlined or eliminated with various of my suggestions.
I still don't see the advantage of a final Object-method
over an already existing static method of System.

Puts it where it belongs. It's a getter of Object properties, so it
logically belongs in Object as an instance method.
Anything you could do with the former but not with the latter?

Be tidy? :)
 
H

Harold Yarmouth

Hendrik said:
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Harold Yarmouth schreef:

I wouldn’t have been. Ok, Javadoc is unnecessary, but for maintenance
purposes some comment makes sence.

It's generally pretty clear what this does in GUI setup code:

FooButton.addActionListener(new ActionListener() {
public void actionPerformed (ActionEvent e) {
fooAction();
}
}

with

private void fooAction () {
...
}

somewhere else in the class.
You are stretching the intended semantics of ‘abstract’ here. It is
meant to mean: this class should be subclassed to fill in functionality.

It is meant to mean "this class cannot be instantiated". I can't think
of anything in Java much more "abstract" (in the English sense) than a
utilities class with no instances.
Mind elaborating how you get these numbers?

Copy array into list, copy list into some other collection, instead of
copy array into some other collection.
But feels more in line with the current syntax to me.

But uggg-leee!
 
H

Harold Yarmouth

Lew said:
Sorry about the accidental post - I fumble-fingered it.





This might or might not have occurred to you, "Harold", but others
beside you read this newsgroup.

Your rude and condescending tone is uncalled-for. There is also no
reason to be putting my first name in quotation marks. I can only
imagine that you mean some personal insult by that, "Lew".

This part:

"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")"

is quite clearly addressing me personally, and therefore implying that I
use Google for usenet. I was pointing out that that was false.
He was not talking only to you.

His phrasing and word choice suggest otherwise, "Lew".
 
A

Andreas Leitgeb

Harold Yarmouth said:
Enum values having numeric values that form a continuous range starting
with 0 is overrated anyway. I rarely if ever use this.

It is used internally a lot.
The value() is identical with the index of the instance in
the values() array, and some parts of Java rely on it.

values() must not have nulls in it for Enums, but for new
SubEnums, that might be possible.
 
J

Joshua Cranmer

Harold said:
Eh? I haven't said any "nasty things" about Joshua.

Read the archives of c.l.j.p of around 1.5-2 years ago, especially those
posts from someone whose first alias is Twisted. Then you'll understand.
 
J

Joshua Cranmer

Harold said:
Just as they make unchecked casts of generic collections at their own
risk right now, and prefer to avoid doing so whenever possible.

The primary purpose of unchecked conversions is to facilitate migration
to generics at disparate times.
For operations that are ... what is the term? Commutative? It can look
for the "plus" method in the RHS if the LHS lacks it. Alternatively the
programmer has to do matrix * 2 instead -- big whup.

See
<http://groups.google.com/group/comp...a94b1020c6/d1a9b67ddd23f8f9?#d1a9b67ddd23f8f9>
for the start of a thread in which I discussed this particular issue at
length, and why I feel that your response is inadequate. Other postings
on that thread reveal my opinions on operator overloading more clearly.

In particular:
* You cannot assume that any operation is commutative. Even for stuff
like multiplication (matrix multiplication is, in fact,
non-commutative), the LHS could be causing a mutation and therefore need
to be evaluated before the RHS.
* "Inverting" operations is often perilous. Dividing by a matrix is
conceptually equivalent to multiplying by its (pseudo)inverse, but
inversion is one of the worst things one can do where solving a matrix
equation is preferred.
A quick Google Groups search should have disabused you of that notion.

The main thread on which I discussed this was titled Java 7 Features.
You now have a link to said thread, so I need not repeat the several
dozen posts anymore.
They are irrelevant. We are discussing Java. If languages were not
allowed (by who? nobody has this authority anyway) to be too different
from one another, we'd probably all be sitting here discussing Java 7's
implementation of cons, car, and cdr for Chrissake.

The authority is by the people in charge of the languages--in Java's
case, the JSR expert groups. No language exists in a vacuum; note that
Java's generics feature is roughly based on C++'s templates, at least in
terms of syntax.

LISP is not close to Java (they have completely disparate influence
trees), but something like, say, PHP (which shares a moderate influence
with C, C++, and Java) is closer.
~= perhaps, for equals()?

o_O ... that makes no sense in terms of syntax.
But it is awkward and verbose.

To make it less verbose than my example requires several orthogonal steps:
1. A constructor that takes an array of pair objects.
2. A "neat" way to create pair objects.
3. Reduced verbosity in array creation expressions.

If either of the last two does not happen, the creation will end up
being more verbose.
Usually that would be apparent from context. Quite often, the very
preceding line will have resembled "x = foo.get("string");".

In my experience with languages such as C and C++, this does not happen
as often as you think.
Your sentence dead-ends in mid-air.

So it does. I think the original statement was supposed to be something
like this:

"... our reactions to basic proposals before repeating the proposal
without adding anything new to say."
And once more with emphasis, if you do not like discussions of closures
you're free not to read them. Launching a rant sprinkled with personal
attacks against someone for mentioning them in your presence is not
appropriate, adult behavior.

It's not that I don't like them, it's just that no one bothers to add
anything new, so it's the same bloody stuff being repeated once every
month or so. Operator overloading and closures in particular
I didn't look to "gauge your reactions" because I shouldn't have to. I
should be able to expect civility so long as I have been civil myself,
and so long as what I write here is on topic here, even if you disagree
with my opinion.

I would expect that someone should avoid repeating points belabored to
death before posting something. It doesn't take much effort to determine
if what you are about to add is something that has been recently
discussed in grand detail.
That has been discussed elsewhere in this thread.

Indeed, let us move it thither.
 
H

Harold Yarmouth

Andreas said:
So you do intend a special case for marker interfaces so
marker interfaces need to be explicitly "implemented", but all
others are auto-implemented if all it's method signatures exist.
explicitly implementing a non-marker interface then has only
one purpose: let the compiler make sure I didn't forget a method.

Two: you're also making a statement that you are implementing an
interface deliberately, by doing so, and thus making some sort of
commitment to observe its contract.

The "auto-implement" is intended mainly for the odd situation where an
existing class you can't edit fits some interface and you're willing to
take responsibility for it if it turns out not to actually adhere to the
contract, and try using it where that interface type is expected.
Perhaps it should require an explicit cast, to make it clear that it's
in the same general category of hack as some other cast-using code and
especially unchecked generics casts.
How would you judge the *runtime* penalty of checking the existence
of all necessary methods upon each attempted cast?

Oh, no, that checking would occur only once for each run-time type and
the results would get remembered somehow.
As Lew guessed right, it was intended for anyone who does read the
posting with google.

Then your phrasing was somewhat confused, since that paragraph,

appears to be addressing me specifically.
Btw., That doesn't need to be a gmail'er, but
could be anyone just using google's news-archive at a later time,
as I've frequently done myself in the past. There is no such thing
as a private conversation in a newsgroup.

An admirable goal, though I'm not sure why Google would distort a
message-ID in a non-Google posting.

However, putting "in case google distorts it" in a parenthetical aside
attached to "Not sure if you got that idea yourself, or from foo"
implies that either you are using Google and worried that it will mangle
your outbound post, or that you think the "you" who may have got that
idea himself (i.e. me) is using Google, and neither was the case.

Put it down to slightly confused grammar/word choice somewhere I guess.
If the bit about Google had explicitly had broader address, or had been
elsewhere in the post than right next to "you ... yourself", there would
have been no confusion.
Yes (furthermore leaving aside the "same-package" special case).
I'd even go further to do this regardless of final'ity
of the wrapped class. It doesn't seem right to me for a
class that *doesn't really* subclass a given class to still
access it's more-restricted bits.

My proposal overloaded the "extends" keyword for this -- it would
subclass a non-final class normally, as now, and wrap a final class. You
appear to want to be able to wrap without subclassing non-final classes.
For that a new syntax would be needed. Perhaps "implements" followed by
a class rather than an interface would do the job without adding new
reserved words to Java?
In some way you're right, but Joshua also made a good point
recently by quoting a sample of some new keyword-less syntax
of some "newer C++": just seeing the new syntax makes it
almost impossible to look it up in order to get to know
what it means.

I don't think this would be an issue with Object* object = foobar; or
Object! object = foobar;, somehow.

If things like that proliferated too much, sure. Or if a yucky enough
closure syntax got decided on, or people abused operator overloading.
But bad code will be written whatever tools are handed out, so the
latter isn't an argument against much of anything, and the former is an
argument against having a yucky closure syntax. Neither is an argument
in favor of a verbose non-null syntax.
As soon as some keyword or other constant verbiage is used,
it becomes possible to look it up.

If reference declarations started showing up with the odd asterisk,
bang, or other punctuation mark on it, but never primitive declarations,
people would probably be able to guess what was going on, on the basis
of "what other binary flag might be set on references but not primitives
and would be really useful besides can be/cannot be null?" I assume
there'd also be great fanfare and publicity within Java circles
attendant upon the release of such a long-awaited new feature. Someone
would have to have spent a year living under a rock, then crawled out
from under it and stumbled upon some fairly recent Java code, AND not be
especially intelligent or Java-savvy, to not either know OR manage to
guess what was up.
However, there are new problems I see with it (non-nullness) now:
Assume I wanted to use a HashMap<String,Integer*> I'd expect it
to only contain non-nulls, but get() would still produce nullable
values, as it returns null for unknown keys.

You'd have a guarantee that if you assigned the get() to a non-nullable
reference and got NPE it was because of a missing key, and you'd get an
NPE if you tried to put a null into the map with put, instead of this
causing errors later (or even silently failing in the case that get() is
expected to sometimes be null but it's assumed that null means key not
found -- the silent failure would be that you thought some key was being
inserted but later on it seemed like it hadn't, with no exception thrown).

Of course it's no magic bullet, but it would help to catch some
null-related errors closer to where the real bug was.
HashMap's implementation is ofcourse not aware of whether it's Value
type is nullable, so it has no clue as to how to declare it
still-nullable when it returns the Type parameter or null. There may
exist solutions, but I fear it's getting more and more complex,
rather than just the simple nonnull marker you started out with.

There'd need to be a way to declare a type parameter nullable, say

public V? get (K key) {
...
}

means that if it's a HashMap<String,Integer*> the get return type is
Integer rather than Integer* and can still be null. Reference and a few
other classes would need this too, but it would be rare.

We end up needing only two punctuation "warts" in declarations, and one
will only appear, infrequently, in generic classes. (So if two is one
too many, THAT one can be safely changed to something more verbose. "V
|| null" would be pretty clear to anyone who speaks fluent Java.)
String*[] noNullsArray = array; // Runtime check that no element
// is null gets generated here.
Huh!? I thought the whole point of it was to guarantee null-freeness
at compile time.

At the point where a nullable is assigned to a non-nullable, a run-time
check will be needed. Same as when casting is used; most type-safety is
verified at compile time but in a few spots it needs to have a runtime
check.
Compare it with ClassCastExceptions: they can only be thrown at explicit
casts (implicit casts are only possible where no runtime-check is necessary)

Requiring an explicit cast at a nullable->non-nullable assignment where
the compiler cannot prove by static analysis that the RHS isn't null
might be a good idea.

Object foo, bar;
Object* baz, quux, mumble;
....
if (foo == null) {
...
} else {
baz = foo; // OK; foo cannot be null here
mumble = quux; // OK
quux = bar; // Error
quux = (Object*)bar; // OK, but may throw if bar is null
}

The above is with local variables, and assumes foo, bar, and quux are
definitely assigned somewhere between the declarations and the if. With
non-local variables, the possibility of concurrent change to the
reference in another thread means the cast might be needed even on the
"baz = foo;". Allowing omission of the cast there would mean that NPEs
could pop up downstream where baz got used, but any such would indicate
a concurrency issue, so programmers could treat nulls coming OUT of
"non-null" references as prima facie evidence of a race condition in
their code. Race conditions are not something that can generally be made
easier to debug. In this case, they might be. I'd suggest letting "baz =
foo;" with no explicit cast stand, in the case foo is not local, but put
the runtime check in as if a cast were used. Then if a race condition
does cause foo to become null in between the test for null and the
assignment to baz, the NPE is thrown right then and there, inside one of
the blocks of code involved in the race. The programmer knows such an
NPE indicates the need to synchronize that area (and whatever area
nulled foo, if they can find it! But finding one of the areas easily
halves the size of the job).

(Of course, the bytecode has to be equivalent to that from present-Java

baz = foo;
if (baz == null) throw...

and also with the explicit cast

quux = bar;
if (bar == null) throw...

or it's possible for a race condition to get a null into the "non-null"
reference after the test. So, the possible-null has to go in first, then
an exception be thrown if the "non-null" reference isn't actually
non-null. Then if the exception is not thrown the reference always is
not null.)
Alternative: new method in java.utils.Arrays such that
noNullsArray=Arrays.nonNull(array);
will assign the instance only after a successful runtime nonnull check
(otherwise throw a NullPointerException immediately)

Yes, that is an alternative for arrays.
Of course we could get into hairiness with noting whether the array
reference itself can be null:
String*[]* -- which * means which?
That will need some more and better ideas, expecially also for
multidimensional arrays (i.e. arrays of arrays of arrays ...).
I like the principle, though.

MD arrays are best off wrapped in some data structure, which would
encapsulate the messy syntax out of general view. It would also tend to
localize bugs if only the elements were declared nonnull in some cases,
and method parameters and returns, but the guts allowed array references
to be null. NPEs from such nulls might occur separated in time from the
cause, but the error would definitely be in that class's implementation.

Even SD arrays are not usually preferable to ArrayList or similar.
catch (IOException _) {
... = new ...() { public void actionPerformed (ActionEvent _) {

These cases hardly ever accumulate, but if they do, there's still
"__" and "___" and ... as further dummy names.

The need for dummy names at all is rather perverse, in catch clauses and
in private nested classes of all stripes.

Also, some IDEs and compiler options produce warnings on unused
variables. My proposal would allow such warnings to be enabled and still
have warning-free code in these cases, without doing additional dummy
actions.
Sorry, my misunderstanding once again.
I think I've read that this particular syntax will indeed
be added in 7.0 (regardless of this discussion here).

Oh, goody.
I don't like that at all.
Why?

My point is that I see no relevant need to prevent anyone from
instantiating or subclassing a Utility class, e.g. like java.lang.Math.
What bad could one do with it, if it were possible?

Nothing much. It's just that that's not generally what those classes are
*for*.
Playing around I tried this ugly idiom:
class Test { static Math m; static { m.sin(m.PI); } }
interestingly the bytecode contains "getField m"
immediately followed by "pop".

Ugh.

Utility classes need a special declaration, then. Something like
"private null class Foobar" that means it can't be instantiated and it's
an error to have "Foobar x;", Foobar return values, Foobar parameters,
etc.; and of course Foobar cannot inherit from anything not declared
"null" in this way, or have non-static fields or methods. (This in turn
outlaws Foobar implementing a non-empty interface or throwing or
catching a Foobar.)
What did you mean should actually happen to checked exceptions
thrown within run() (and not caught there)?

Same as now. Thread dies and a stack dump goes to System.err.

Perhaps there would need to be a way to specify, in a method receiving a
closure parameter, whether it does or does not throw whatever the
closure throws. Closures might have a throws part of their type, and if
the closure is actually invoked in a method that method has to throw or
handle the checked exceptions the closure declares. This requires
full-blown closures, and though a closure literal could just be a
brace-delimited block of code, a closure reference declaration would be
fairly hairy, needing to specify parameter types, return type, and
throws, just like a method, in the general case.

But there's not really any way to avoid that if closures are
implemented, since all of that stuff IS part of the type.
Why not just least common denominator?
Because such an array may not be compatible with what I want to use it
for:
void foo(Number[] a) ...
foo({1,2,3,5,8,13}); // wouldn't work, because the auto-inferred
type would be Integer[] which is not castable to Number[].

When the literal is used as the RHS of an assignment (including as a
method parameter or return), the elements would have to be castable to
the type of the LHS of the assignment.

Actually, I think that's about the only time literals are used, so that
seems to eliminate the need for "least common denominator" or similar
type inference of array literals.

In this case, it's passed to a method that wants a Number[] so the
compiler figures out if all of the elements are convertible to Number
and allows it if so, generating a Number[] in the class constant pool
that is passed to the foo method in that method call.

Integer x = 8;
String y = "17";
....
foo({1, 2, 3, 5, x, 13}); // OK, x is an Integer which is a Number
foo({1, 2, 3, 5, x, 13, y}); // Error, y is a String

Actually, the last time I checked, you could assign an Integer[] to a
Number[], but would get a run-time exception if you tried to put a
Double into it via the Number[] reference. One little bit of array
type-unsafety avoided by using collections where possible.
It's a generalisation. it's about like
try { ... errors caught }
continue { ... errors not caught }
tryalso { ... errors caught again }
continue { ... errors not caught }
tryalso { ... errors caught again }
catch ...
finally ...

Uggg-leee!

I wasn't proposing to provide more than just try { } continue { } catch
{ } finally { }.
Someone else would have to find a better verbiage for it.

As a rule, the shorter the verbiage, the better, so long as it remains
readable, and modulo frequency of use.
Oh, and the finally block would still need to be executed
even if it was doSomething() that threw an exception.

No duh. Finally would retain the current semantics -- every transfer of
control out of the associated try block goes through the finally code.
That's a very very special and otherwise rare usecase (serialization helper).

Rare does not equal useless, particularly when it's difficult to add the
functionality if you're not Sun (say, because you'd have to rewrite half
the standard library to truly make use of it).
Sun did a few special tricks to prevent users from hooking in.

I do not exactly understand Sun's reasons for that, but it most
definitely hasn't just been forgotten - it has actively been
worked against by sun.

Providing a built-in ReferenceListener just strikes me as a whole lot
nicer than having to actually spawn a separate thread, calling the
blocking poll method and invoking a user-supplied Listener every time it
returned with an enqueued object.
There is no blocking poll for the ReferenceQueue, and also no way to
create one as derivative. The thread would have to run a busy loop
(yuck!).

The polling methods that block are actually named "remove" rather than
"poll", but they exist.

remove

public Reference<? extends T> remove()
throws InterruptedException

Removes the next reference object in this queue, blocking until one
becomes available.

Returns:
A reference object, blocking until one becomes available
Throws:
InterruptedException - If the wait is interrupted


is the one I'd use.
Strange. I utterly fail to see the reason behind that.

Well, I utterly fail to see the reason (if there is any) behind Sun
forcing people to make their own ReferenceQueue listener implementation
using threads, but there might (might) nonetheless be one. :)
But none of them (including even my WeakHashMap approach)
allow checking at compile time, as the proposed change would.

public final class Foo {
RealFoo delegate; // Package-private field. No subclassing.
public void method () {
delegate.method();
}
}

public final class Bar () {
private static final class RealFoo implements Interface {
void method () { ... }
void otherMethod () { ... }
}
...
aMethod (Foo foo) {
foo.delegate.otherMethod();
someThing.doWithInterface(foo.delegate);
}
}

works fine. It's not possible to pass a non-Foo to aMethod, because of
compile-time type checking. The delegate RealFoo can implement an
interface but users of Foo don't see it, because they don't see the
delegate field or have any real access to it. However aMethod can use
the interface by extracting the delegate. Finally, since Foo is final
the delegate cannot be exposed by somebody's subclassing of Foo. Only
playing tricks with reflection and serialization might grant access, so,
serious hoop-jumping.

Compiler checks:
* That aMethod is called with a genuine Foo.
* That nobody can mess with the RealFoo delegate outside of the package
with Foo and Bar.
* That RealFoo implements Interface.
* That someThing.doWithInterface is getting an implementation of Interface.

Pretty much everything is compiler-verified here.
 
H

Harold Yarmouth

Joshua said:
That said, Mr. Yarmouth was ...

I see no reason for you to publicly insult me, and not even in a
response to one of my own posts, but someone else's.

I did, of course, say that IF they were not appearing as FooEnum$1.class
or similarly THEN there had to be some magic going on under the hood.

Apparently they DO appear as FooEnum$1.class and the like, but only when
they have bodies.

"If X then Y" is not false if X is false. In fact, in formal logic
settings, "If X then Y" is considered to be TRUE if X is false, rather
than even indeterminate. :)
 
J

Joshua Cranmer

Harold said:
I see no reason for you to publicly insult me, and not even in a
response to one of my own posts, but someone else's.

How is saying your statement was incorrect an insult?

This was your statement:
Not on disk, no, but there are four classes in the system at runtime;
some ClassLoader magic sees to that.

That is not in the "If p, then q" statement that you said.
I did, of course, say that IF they were not appearing as
FooEnum$1.class or similarly THEN there had to be some magic going on
under the hood.

Apparently they DO appear as FooEnum$1.class and the like, but only
when they have bodies.

Technically, this is false, since they were not appearing as
FooEnum$*.class AND there was no magic going on under the hood. No need
to belabor, though.
 
L

Lew

Joshua said:
Read the archives of c.l.j.p of around 1.5-2 years ago, especially those
posts from someone whose first alias is Twisted. Then you'll understand.

No need to go back that far. I was referring to these remarks:....

All the sorts of comments that cause Paul to go into a bloody rage when said
to him, but of course, perfectly all right when said by him.

And not true. You were not insulting Paul, gratuitously or otherwise. You
have no attitude problem. You didn't click "take a crap...". And you were
never either "nonconstructive" nor "bloody-minded" (whatever *that* was
supposed to mean).
 
A

Andreas Leitgeb

Harold Yarmouth said:
Two: you're also making a statement that you are implementing an
interface deliberately, by doing so, and thus making some sort of
commitment to observe its contract.

At this point I'm fairly sure all misunderstandings are cleared up,
and I come to the conclusion: I, personally, do not like it.
appears to be addressing me specifically.
The question was directed at you, indeed, but it was intended
such, that other readers (even those with google) would also know
what post I referred to. Google does distort parts of postings,
that resemble email-addresses. Generally I'm even glad about this
feature, as it reduces spam from web-spiders hitting on google's
webinterface. Unfortunately, Message-Ids look structurally like
email addresses, and are therefore "protected", too.

I found the meta-discussion quite wearying. I'd wish we could
both just stick to discussing the ideas, and just ignore anything
meta.

Btw., if you ever actually answered that question, I must
have missed it.
My proposal overloaded the "extends" keyword for this -- it would
subclass a non-final class normally, as now, and wrap a final class. You
appear to want to be able to wrap without subclassing non-final classes.
For that a new syntax would be needed. Perhaps "implements" followed by
a class rather than an interface would do the job without adding new
reserved words to Java?

I now understand your proposal. Obviously (now) it is not the same as
mine. Compared with mine, you left out the class-equivalence part.
Without that, I don't see too much point in the whole thing.
How does a MyString with lots of custom useful methods help me
if I can't bend a literal String into it.

My approach of keeping them equivalent failed with generics erasure.
If I instead target instance-upgrade, that might help, but is an
even deeper paradigm-shift.
I don't think this would be an issue with Object* object = foobar; or
Object! object = foobar;, somehow.

As it seems we do disagree here.

This remark was based on my misunderstanding. I thought compile-time
coverage, you think runtime checks.
I accept, but undervalue the merits of runtime-checks.
Otoh., doing it at compile time runs into the problems shown.

I'll just withdraw myself from this topic, until some new ideas come
up. Looking forward to the @NonNull annotation, though.
Of course it's no magic bullet, but it would help to catch some
null-related errors closer to where the real bug was.
Yes. I strive for little more magic, though :)
There'd need to be a way to declare a type parameter nullable, say
public V? get (K key) {

The problem is compatibility: any already existing generic class
would not know about the necessity to thusly mark some of it's methods
and consequently make wrong promises as a result. The question mark
could be reversed, such that it would be necessary to hold the notnull-
info on return values. That would solve the compatibility problem
at the cost of being even more confusing.
In that case we could use "*" also within generics, and only if
both a type-parameter is "*"ed (public V* get() ...) AND the type
parameter was "*"ed (List<Integer*>), then the return value would be
known as statically not-null.
All fine, except that I dislike the asterisk as marker.
Requiring an explicit cast at a nullable->non-nullable assignment where
the compiler cannot prove by static analysis that the RHS isn't null
might be a good idea.
quux = (Object*)bar; // OK, but may throw if bar is null

I consider it a necessity. Except for the asterisk, I like your
example very much: either separate out the null with an "if"
(and deal with the null-case separately), or just cast and have
the NPE thrown eventually.

Concurrency is a beast. Unless we had special idioms that resulted
in: getField...,dup,isnull?,ifyes:NPE,else:putField (pseudo-bytecode),
we'd indeed still need the cast.
Yes, that is an alternative for arrays.
Anyway it would have to create a copy, or nulls could be sneaked
in later through arrray, and appear in noNullsArray.
The need for dummy names at all is rather perverse, in catch clauses and
in private nested classes of all stripes.
but rare and non-verbose enough to not matter all that much.
Also, some IDEs and compiler options produce warnings on unused
variables. My proposal would allow such warnings to be enabled and still
have warning-free code in these cases, without doing additional dummy
actions.
I don't use such IDEs but I'm fairly sure, they do never barf for
unused parameter names.
Mostly personal taste.
Same as now. Thread dies and a stack dump goes to System.err.
But that's not the point of checked exceptions.
void foo(Number[] a) ...
foo({1,2,3,5,8,13}); // wouldn't work, because the auto-inferred
type would be Integer[] which is not castable to Number[].
When the literal is used as the RHS of an assignment (including as a
method parameter or return), the elements would have to be castable to
the type of the LHS of the assignment.
That doesn't work. The compiler may need to choose among a couple
of overloaded methods, so it must know the types of the parameters
before even starting out to have a look at all available overloads.
generating a Number[] in the class constant pool
Actually there is no such thing as an array in the constant pool.
compile this class:
class Test { int[] ia={1,2,3,4}; }
and look at its bytecode.
Actually, the last time I checked, you could assign an Integer[] to a
Number[],
By casting it to an Object or Object[] inbetween, iirc.
I wasn't proposing to provide more than just try { } continue { } catch
{ } finally { }.
I see too little value in that. Therefore I tried to extend it
such that it pays :)
The polling methods that block are actually named "remove" rather than
"poll", but they exist.

I surrender. I don't know what made me miss it.
public final class Foo {
RealFoo delegate; // Package-private field. No subclassing.
Ah ok, dispersing a public final class's instance that keeps
all its sensitive parts in the delegate does indeed solve it.
But it's ugh-lee ;-)
 

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,755
Messages
2,569,536
Members
45,007
Latest member
obedient dusk

Latest Threads

Top