[External] : Re: Can not call a private method, no idea why ?
Maurizio Cimadamore
maurizio.cimadamore at oracle.com
Thu Jan 21 13:03:50 UTC 2021
> I don't believe that's the right analogy; this is:
>
> ```
> import java.util.function.Function;
>
> class Test {
> private void greet() { System.out.println("hello"); }
>
> <X extends Test> void test(X x) {
> x.greet();
> }
> }
> ```
>
> Which also fails, no wildcards around this time.
>
> When you access a member on a `? extends T` you get back a
> captured variable, which is a fresh type variable with some
> bounds. As per JLS 4.4 the members of a type variable X extends A
> & I1 ... In are the members of the intersection type (A, I1 ..
> In). In the definition of intersection type in JLS 4.9 you will
> see that only public members are allowed.
>
> This decision comes from the fact that type-variables have a "for
> all" spirit to them - when you write something like x.e, and x is
> of type X (with X a type variable) the intent of the language is
> for x.e to either be valid _for all_ instantiations of X, or to be
> rejected. Without this rule, it would be very easy to write a
> generic class which can be instantiated in ways that make it break
> some (runtime) assumptions.
>
>
> Given that private method are not dynamically linked, i don't see how
> this is issue at runtime.
>
> Back to the first example, if you introduce a 'var' in the middle, it
> will compile
>
> class Test {
> private void greet() { System.out.println("hello"); }
>
> void test(Function<? super Object, ? extends Test> f) {
> f.apply(null).greet(); // nope
> var t = f.apply(null);
> t.greet(); // yes !
> }
> }
>
> so i don't think itcan break some runtime assumptions.
I think your example is subtly misleading - you are using `var` and
`var` has special normalization for avoiding captured variables - which
means that accessing apply(null).greet() and t.greet() have completely
different static types.
To back off form this specific example, think of this:
public class Box<X extends Foo> {
X x;
Box(X x) { this.x = x; }
void m() {
x. ???
}
}
What are the valid member access for "x" ?
Say that Box and Foo are in the same package - can I access all members
of "Foo" ? Note that this Box class can be used from a completely
different package, so there will be runtime issues if we bake in
assumptions on which members can be accessed from the type variable.
In other words - if Box<T> is a well-formed type, I want a guarantee
that no bad stuff can happen at runtime (yes, there can be unchecked
casts and all that - but let's assume that all the code compiled w/o
warnings). And if you allow access to anything other than public members
you have no such guarantee.
I sympathize with your argument: at the end of the day, when you have X
<: Foo, you can always widen (e.g. assign) X to Foo (w/o warnings) and
take it from there, and all restrictions are gone - so maybe this is
excessive hand-holding on the language-side - but I was trying to
explain the rationale behind the rules - it is pretty common when
dealing with parametric polymorphism to think of membership of a
type-variable X in a "for all" semantics - e.g. the intersection of
members that are available in all instantiations of X; so, for the
language (and the compiler) X <: Foo and Foo are two very different
types, with very different membership rules.
Maurizio
>
> Maurizio
>
>
> Rémi
>
>
>
>
>
> Maurizio
>
>
> Rémi
>
>
> On 21/01/2021 10:53, Anna Kozlova wrote:
>
> Hi Remi,
>
> type of `map.apply(null)` is capture of `? extends
> IOBug` and thus it has no access to private methods of
> IOBug. Do I miss something?
>
> Thanks,
> Anna
>
> On Thu, Jan 21, 2021 at 9:34 AM Remi Forax
> <forax at univ-mlv.fr <mailto:forax at univ-mlv.fr>> wrote:
>
> The following code doesn't compile.
> No idea why ?
>
> public interface IOBug {
> private IOBug foo() {
> return this;
> }
>
> default IOBug flatMap(Function<? super Object, ?
> extends IOBug> map) {
> return map.apply(null).foo();
> ^------
> }
> }
>
> It works if foo is declared as a default method
> instead of a private method.
>
> regards,
> Rémi
>
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://mail.openjdk.java.net/pipermail/compiler-dev/attachments/20210121/c4f38cfb/attachment.htm>
More information about the compiler-dev
mailing list