[External] : Re: Can not call a private method, no idea why ?

forax at univ-mlv.fr forax at univ-mlv.fr
Thu Jan 21 12:40:40 UTC 2021


> De: "Maurizio Cimadamore" <maurizio.cimadamore at oracle.com>
> À: "Remi Forax" <forax at univ-mlv.fr>
> Cc: "Anna Kozlova" <anna.kozlova at jetbrains.com>, "compiler-dev"
> <compiler-dev at openjdk.java.net>
> Envoyé: Jeudi 21 Janvier 2021 13:18:32
> Objet: Re: [External] : Re: Can not call a private method, no idea why ?

> On 21/01/2021 11:48, [ mailto:forax at univ-mlv.fr | forax at univ-mlv.fr ] wrote:

>>> De: "Maurizio Cimadamore" [ mailto:maurizio.cimadamore at oracle.com |
>>> <maurizio.cimadamore at oracle.com> ]
>>> À: "Anna Kozlova" [ mailto:anna.kozlova at jetbrains.com |
>>> <anna.kozlova at jetbrains.com> ] , "Remi Forax" [ mailto:forax at univ-mlv.fr |
>>> <forax at univ-mlv.fr> ]
>>> Cc: "compiler-dev" [ mailto:compiler-dev at openjdk.java.net |
>>> <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.
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. 

> 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 < [ mailto:forax at univ-mlv.fr |
>>>> 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/8e8582ba/attachment-0001.htm>


More information about the compiler-dev mailing list