From: Tomas Mikula on
On Tue, 20 Oct 2009 18:28:45 -0400, Eric Sosman wrote:

> Daniel Pitts wrote:
>> Eric Sosman wrote:
>>> Tomas Mikula wrote:
>>>> [...]
>>>> 1. serialization frameworks. It is already required that a
>>>> Serializable class has a no-arg constructor. But this is not required
>>>> at compile time.
>>>
>>> You've said this a couple times, but are you sure it's true?
>>> This class (with no no-arg constructor) appears to serialize and
>>> deserialize just fine:
>>
>> Only the non-Serializable Base of a Serializable class requires a
>> no-args constructor: [...]

Ah, I was wrong with this. But this only means that the Java's
serialization doesn't use _any_ constructor to create an object. Which
means that it uses some tricks not available to the programmer (correct
me if I am wrong). In your own serialization framework you would need to
create the object being deserialized, so you would care about the
constructors available on your class, not the superclass.
From: Arved Sandstrom on
Eric Sosman wrote:
> Daniel Pitts wrote:
>> Eric Sosman wrote:
>>> Tomas Mikula wrote:
>>>> [...]
>>>> 1. serialization frameworks. It is already required that a
>>>> Serializable class has a no-arg constructor. But this is not
>>>> required at compile time.
>>>
>>> You've said this a couple times, but are you sure it's true?
>>> This class (with no no-arg constructor) appears to serialize and
>>> deserialize just fine:
>>
>> Only the non-Serializable Base of a Serializable class requires a
>> no-args constructor: [...]
>
> Right. Which means that if an interface could mandate a specific
> constructor for its implementing classes, this capability would not
> solve Serializable's problem at all: It's not the Serializable class
> that needs the special constructor, but a superclass that *doesn't*
> implement Serializable. If we get to the point where an interface
> can impose requirements on the classes that *don't* implement it, I
> think we've achieved absurdity ;-)
>
> There may yet be a reasonable use case for letting an interface
> or abstract class require specified constructor signatures of the
> implementing subclasses, but Serializable isn't it.

Maybe it's just me, but if I want an abstract class to require specific
constructor signatures of its subclasses, I give that abstract base
class that constructor. :-)

[ SNIP ]

AHS
From: Lew on
Tomas Mikula wrote:
> 2. For calling static methods on generics. My example was
> abstract class Vector<V extends Vector<V>>{
> /** returns a zero vector */
> public abstract static V zero();
> }

This would be an extreme change to the semantics of Java generics, most likely
very infeasible as stated. Type parameters are resolved per instance, and do
not apply class-wide.

How is it even possible for a class to know what type to use for 'V', when
every instance of that class could have a different type replacement for it?

--
Lew
From: Steven Simpson on
Tomas Mikula wrote:
> On Mon, 19 Oct 2009 19:26:41 +0100, Steven Simpson wrote:
>
>> class X implements static Runnable {
>> public static void run() { ... }
>> }
>>
>
> Now if you had
>
> class Y extends X {...}
>
> would the compiler enforce that Y provides its own implementation of
> static run() method? (My desirable answer would be YES.)
>

My initial answer is 'no'. Y$static would contain:

public void run() {
Y.run();
}

....which would just bind to X#run() if Y didn't provide its own #run().

However, I guess the compiler could enforce it, though I'm not sure if
one would want that in all situations. In its favour, while Y instances
might inherit behaviour available in X instances due to 'Y extends X',
there's no reason for the static aspect of Y to inherit the static
aspect of X, e.g. it does not necessarily follow that Y$static extends
X$static, or that (X implements static Runnable && Y extends X => Y
implements static Runnable). Hmm...

> If you had an abstract class
> abstract class X implements static Runnable {...},
> would the implementation of static method run() still be required? (My
> desirable answer would be NO.)
>

I would say 'yes', if only since 'abstract' has never affected static
methods.

In fact, since you expect (from the previous question) that any Y which
extends X must provide its own static run(), I don't see a point in
requiring X to 'implements static Runnable' if it's only going to leave
the implementation to a base class.

For instance methods, where Y extends X, it's clear that having an X
reference could mean invoking a Y object, i.e. you have a piece of code
which syntactically only refers to type X but semantically could invoke Y:

abstract class X { public abstract void doSomething(); }
class Y extends X { ... }

X ref = ...;
ref.doSomething(); // this piece

At run-time, you might be dealing with Y, but statically you have only
X. When do you have an analogous case for static methods?

In the dynamic-loading use-case, Y would be explicitly identified by
name (and passed to Class#forName(String)). You then check dynamically
that Y 'implements static Runnable' with a call to
Class#meetsContract(Runnable.class). Anything you say about X is
irrelevant.

In the reified-generics case, you might have a class that requires a
type parameter that 'implements static Runnable':

class Banana<T extends static Runnable> {
{
T.run();
}
}

(Aside: I don't see a point in distinguishing between 'extends' and
'implements' on a type parameter, as only one relationship needs to be
expressed, i.e. Class#isAssignableFrom(Class), which is the same whether
you're dealing with interfaces or classes.)

Then you write 'new Banana<Y>', and the compiler checks that Y
'implements static Runnable', and still X is not involved.

Can you write an example where some code statically uses X and that it
'implements static Runnable', but could actually end up invoking Y#run()?

>> It would work by the compiler generating an extra class when it saw
>> 'implements static'.
>>
>
> Somehow I feel that for consistency any class should support X.static,
> not just when it 'implements static' some interface.

Yes. For classes without any 'implements static', the proxy object that
X.static ultimately evaluates to (and which Class#getContractor()
returns) can just be an instance of Object, as there are no interfaces
that it has to conform to.

> But I'm curious what was the motivation for having X.static?

If nothing else, just to ensure that there is a static, type-safe,
compile-time way to obtain the proxy object. If you happen to know X
statically, and that 'X implements static Z', and something accepted a
Z, you could write doSomething(X.static).

> I only see usability if it was
> allowed to use it on type parameters:
>
> class MyClass<T static implements Runnable> {
> ...
> T.static.run();
> ...
> }
>

As you noted before, this sort of thing seems to require reification,
though it's pretty similar to something in Stefan's last topical blog
entry, where he felt that something could be done without reification.

>> An expression such as:
>>
>> X.static
>>
>> ...would expand to:
>>
>> (X$static) X.class.getContractor()
>>
>> Class#getContractor() would create the proxy or recover a cached one.
>>
>
> Or maybe X.static could just expand to X._static where the line
>
> public static final X$static _static = new X$static();
>
> would be added to class X.
>

Good idea, though I don't think '_static' is an especially reserved name
(is it?). 'static' would never clash with any real class member, and
we're past syntactic analysis by now, so it should be expressible in
bytecode.

One problem might be that Class#getContractor() would have to
reflectively look-up a static field on X, instead of just calling
Class.forName("X$static").newInstance().

Also, there was an objection to increased object count, so creating on
demand seemed worthwhile.

Cheers!

--
ss at comp dot lancs dot ac dot uk
From: Andreas Leitgeb on
Arved Sandstrom <dcest61(a)hotmail.com> wrote:
> Maybe it's just me, but if I want an abstract class to require specific
> constructor signatures of its subclasses, I give that abstract base
> class that constructor. :-)

You may of course do that, but that doesn't put any
constructor *requirements* upon the subclasses.