And yet another generics question

C

Chris Uppal

Can anyone explain to me why:

class Test<X>
{
static X x() { return null; } // line 3
}

provokes the compiler to issue an error message:

Test.java:3: non-static class X cannot be referenced from a static context

Pointers to the JLS, to the bug parade, or a justification for what looks like
craziness to me, would be equally welcome...

-- chris
 
I

Ingo R. Homann

Hi,

Chris said:
Can anyone explain to me why:

class Test<X>
{
static X x() { return null; } // line 3
}

provokes the compiler to issue an error message:

Test.java:3: non-static class X cannot be referenced from a static context

Pointers to the JLS, to the bug parade, or a justification for what looks like
craziness to me, would be equally welcome...

-- chris


A static function does not belong to an instance. But the type-parameter
<X> is bound to an instance.

Perhaps you are looking for this:

class Test
{
static <X> X x() { return null; }
}

Hth,
Ingo
 
I

Ian Pilcher

Ingo said:
A static function does not belong to an instance. But the type-parameter
<X> is bound to an instance.

For example:

public static void main(String[] args)
{
Test<String> stringTest = new Test<String>();
Test<Integer> intTest = new Test<Integer>();

Test.x(); // What type is this supposed to return?
}
Perhaps you are looking for this:

class Test
{
static <X> X x() { return null; }
}

That won't work, because the compiler has no way to know what X is.
You need:

class Test
{
static <X> X x(Class<X> cls)
{
return null;
}
}
 
I

Ingo R. Homann

Hi,

Ian said:
That won't work, because the compiler has no way to know what X is.

Of course it works (Eclipse 3.1 compiles it). You can call it like this:
'Test.<String>x();' or this: 'String s=Test.x();' which infers String
as the proper type.

If you just call 'Test.x();' it just returns null and the result is
referenced nowhere. So there is no type to be inferred. It's like as if
you just wrote 'null' and ask which type it has. :)

Ciao,
Ingo
 
I

Ian Pilcher

Ingo said:
Of course it works (Eclipse 3.1 compiles it). You can call it like this:
'Test.<String>x();' or this: 'String s=Test.x();' which infers String
as the proper type.

If you just call 'Test.x();' it just returns null and the result is
referenced nowhere. So there is no type to be inferred. It's like as if
you just wrote 'null' and ask which type it has. :)

Serves me right for posting without trying it.
 
C

Chris Uppal

Ingo said:
A static function does not belong to an instance. But the type-parameter
<X> is bound to an instance.

But that's only repeating my question in different words. I'm looking for any
sort of justification for what appears (to me) to be an absurd restriction.

/Why/ is the type parameter only "available" to instance-side code ? What
possible advantage does that give, either to the semantics of the language, or
to the implementations ? /I/ cannot think of any at all, but maybe I'm missing
something.

-- chris
 
A

Andrea Desole

Chris said:
Pointers to the JLS, to the bug parade, or a justification for what looks like
craziness to me, would be equally welcome...

From

http://java.sun.com/docs/books/jls/third_edition/html/classes.html#8.1.2

<quote>
It is a compile-time error to refer to a type parameter of a class C
anywhere in the declaration of a static member of C or the declaration
of a static member of any type declaration nested within C. It is a
compile-time error to refer to a type parameter of a class C within a
static initializer of C or any class nested within C.
</quote>

For the justification, I'm not sure but maybe it can be because of
static members.
If I have

class MyClass<C>
{
private static Vector<C> myVector;
}

the vector can be once a vector of integers, once a vector of strings.
And we are talking always about the same vector
 
I

Ingo R. Homann

Hi,

Chris said:
But that's only repeating my question in different words. I'm looking for any
sort of justification for what appears (to me) to be an absurd restriction.

/Why/ is the type parameter only "available" to instance-side code ? What
possible advantage does that give, either to the semantics of the language, or
to the implementations ? /I/ cannot think of any at all, but maybe I'm missing
something.

There is no advantage, but there is simply no alternative!

OK, consider, you would have a class like this:

class Test<X> {
static X x;
}

Now, you can instantiate some classes:

Test<String> s=new Test<String>();
Test<Integer> i=new Test<Integer>();

Now, if you wrote "Test.x" somewhere else in your code (not necessarily
in class Test), what type would you expect it to be - String or Integer?

Or do you want Java to have multiple instances of the static variable x
(one of String, one of Integer, ...), so that you can write the following:

class Test<X> {
static X x;
void foo(X x2) {
x=x2;
}
}

Then, there is a problem with javas implementation of generics which
uses type erasure. I agree that type erasure is a non optimal
implementation, but if you want to have backward-compatibility to old
java-code, there is no better solution, I think.

Ciao,
Ingo
 
C

Chris Uppal

Ingo said:
class Test<X> {
static X x;
}

Ah yes. I'm with you now, thanks. I was thinking solely in terms of static
methods, forgetting entirely about static fields. Silly me...

<ponders>
Would it have been better to forbid only static fields, I wonder ? That would
certainly be more irregular that forbidding static members altogether, but
generics are so irregular anyway, that the incremental downside might have
been smaller than the gain.
</ponders>

Cheers.

-- chris
 
I

Ingo R. Homann

Hi,

Chris said:
Ah yes. I'm with you now, thanks. I was thinking solely in terms of static
methods, forgetting entirely about static fields. Silly me...

IMHO, the problem with static fundtions is the same as with static
methods! (But there is a solution for that, as I mentioned.)

Ciao,
Ingo
 
J

John C. Bollinger

But that's only repeating my question in different words. I'm looking for any
sort of justification for what appears (to me) to be an absurd restriction.

/Why/ is the type parameter only "available" to instance-side code ? What
possible advantage does that give, either to the semantics of the language, or
to the implementations ? /I/ cannot think of any at all, but maybe I'm missing
something.
<ponders>
Would it have been better to forbid only static fields, I wonder ? That would
certainly be more irregular that forbidding static members altogether, but
generics are so irregular anyway, that the incremental downside might have
been smaller than the gain.
</ponders>

I am a rank amateur when it comes to type theory, but in my limited
understanding of the subject I am going to suggest that you are
commingling the distinct concepts of a type /parameter/ and its
corresponding type /argument/, and perhaps overlooking the (now
stronger) differences between class and type. Type parameters are
properties of a generic class, just as static members are, but the
corresponding type arguments bound to those parameters are properties of
particular type instances (by which I am referring to types, not
objects). It is not the type parameters that are inaccessible to static
methods, but rather the type arguments.

Granted, that's a somewhat hand-waving argument. You could imagine
binding a type argument at the point of invocation, something like this:

Test<X>.x();

But if you need to do that, then it is no less work than Ingo's
suggestion to use a generic method instead, whose invocation would look
like this (without type inference):

Test.<X>x();

Furthermore, the first alternative (type parameter usable by static
methods) runs into all the normal confusion with invocation of static
methods on references, but compounded by the fact that the relevant type
argument is not that of the reference's type (to the extent that that
exists in the presence of type erasure), but rather that of the
expression's type.
 
C

Chris Uppal

John said:
I am a rank amateur when it comes to type theory, but in my limited
understanding of the subject I am going to suggest that you are
commingling the distinct concepts of a type /parameter/ and its
corresponding type /argument/, and perhaps overlooking the (now
stronger) differences between class and type. Type parameters are
properties of a generic class, just as static members are, but the
corresponding type arguments bound to those parameters are properties of
particular type instances (by which I am referring to types, not
objects). It is not the type parameters that are inaccessible to static
methods, but rather the type arguments.

That's nicely put. I'm not yet convinced, but I suspect I might become so as I
ponder the matter further...

Incidentally, this came up as a result of my trying to feed the compiler with
something roughly like:

class Thing<X>
{
static class Helper
implements Set<X>
{
...
}

private final Set<X> m_data = new Helper<X>();
}

and having the compiler spit it back at me.

-- chris
 

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

Forum statistics

Threads
473,755
Messages
2,569,536
Members
45,012
Latest member
RoxanneDzm

Latest Threads

Top