[External] : Re: Can not call a private method, no idea why ?
Maurizio Cimadamore
maurizio.cimadamore at oracle.com
Thu Jan 21 12:18:32 UTC 2021
On 21/01/2021 11:48, forax at univ-mlv.fr wrote:
>
>
> ------------------------------------------------------------------------
>
> *De: *"Maurizio Cimadamore" <maurizio.cimadamore at oracle.com>
> *À: *"Anna Kozlova" <anna.kozlova at jetbrains.com>, "Remi Forax"
> <forax at univ-mlv.fr>
> *Cc: *"compiler-dev" <compiler-dev at openjdk.java.net>
> *Envoyé: *Jeudi 21 Janvier 2021 12:20:20
> *Objet: *Re: Can not call a private method, no idea why ?
>
> I agree with this analysis. This has nothing to do with default
> methods, and interfaces in general:
>
> $ cat Test.java
> import java.util.function.Function;
>
> class Test {
> private void greet() { System.out.println("hello"); }
>
> void test(Function<? super Object, ? extends Test> f) {
> f.apply(null).greet();
> }
> }
>
> This still fails. As Anna points out, the function returns `?
> extends Test`, so the compiler cannot assume that what will be
> returned by the function will be "exactly" a Test. If it's a
> subclass, then the method will be inaccessible, even for the VM.
>
>
> If you have a classical method, like the one below, test can also be a
> subclass, still you can access to the private method
> void test(Test test) {
> test.greet();
> }
>
> Here, because Function is a parametrized type, you need a wildcard to
> have subtyping, so in both cases you have subtyping,
> but the compiler doesn't behave the same way.
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.
Maurizio
>
>
> 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/bd4aed34/attachment.htm>
More information about the compiler-dev
mailing list