Laird Nelson
Laird Nelson

Reputation: 16238

Should a parameterized type's direct supertype set contain it?

In the Java Language Specification, version 11, section 4.10.2, it reads, in part, while talking about direct supertypes of class and interface types:

Given a generic class or interface C with type parameters F1,...,Fn (n > 0), the direct supertypes of the parameterized type C<T1,...,Tn>, where each of Ti (1 ≤ i ≤ n) is a type, are all of the following:

[…]

C<S1,...,Sn> where Si contains Ti (1 ≤ i ≤ n) (§4.5.1).

"contains" means:

A type argument T1 is said to contain another type argument T2, written T2 <= T1, if the set of types denoted by T2 is provably a subset of the set of types denoted by T1 under the reflexive and transitive closure of the following rules (where <: denotes subtyping (§4.10)):

[…]

T <= T

Note that T <= T means both that T contains itself and is contained by itself.

Following the rules, if I have a parameterized type, C<T1>, then one of its direct supertypes will be a parameterized type C<S1> where S1 contains T1 (where T1 is contained by S1). One of T1s containing classes is T1 itself (T <= T), so C<S1> in this case is equal to C<T1>, and since C<S1> is, by these rules, a direct supertype of C<T1>, then it follows that C<T1> is its own direct supertype.

Is this intentional? I ask the question because my reading of the specification is that there is no other rule describing the direct supertype relation that permits a type to be its own direct supertype, so this one gave me pause.

Upvotes: 0

Views: 86

Answers (1)

rzwitserloot
rzwitserloot

Reputation: 103638

That's right. There's nothing in the java language spec that is interested specifically in the distinction; there are no constructions in java-the-language (or for that matter, java-the-VM, as specced in the JVMS) where a proper supertype (as in, actually different) is acceptable, but the type itself would not be.

X foo = exprOfTypeY;

Here X must be a supertype of Y to make this valid. Naturally, if X and Y are the same, the above code is valid.

The same applies everywhere. Even when binding typevars or wildcards of the <? super Foo> kind. Foo, itself, would be valid there, and is considered a fitting type for the requirement <? super Foo>.

As user16320675 pointed out, there are some places in the spec only where it's somewhat useful to make that distinction. Where it comes up, the term proper supertype is used:

§4.10 of the JLS:

S is a proper supertype of T, written S > T, if S :> T and S ≠ T.

That last bit sort of gives away that S :> T holds when S and T are identical, hence the need to explicitly call out that they are also NOT identical in order to qualify for the definition of 'proper supertype'.

Somewhat weirdly, nothing in all of chapter 4 (which I gave a quick skim, so I may have missed it) seems to explicitly spell out that any type is its own supertype / any type 'contains' itself. The 'well, if they didnt, the wording of that bit I quoted in §4.10 is redundant' is the only way. Perhaps an oversight in the JLS specs. It's been known to happen. I'd say from both the common sense that java-the-language never cares about proper supertypes, only about actual supertypes (i.e. type itself is always just as good if supertypes are needed), and from that S ≠ T rider in §4.10, it's clearly intended.

Upvotes: 1

Related Questions