17

The main method tries to access var, but results in ambiguous call. Why? Instance variable var in Base1 isn't accessible (visible?) from static context anyway.

  class Base1 {
      int var;
  }

  interface Base2 {
      public static final int var = 0;
  }

  class Test extends Base1 implements Base2 { 
      public static void main(String args[]) {
          System.out.println("var:" + var); 
      }
  }
user3613844
  • 273
  • 2
  • 8
  • @Pablo, package does not matter. Just put the code snippet into one file and see the result. – AlexR Jul 07 '14 at 14:13
  • 1
    @AlexR "Error - At least one public class is required in main file" – Unihedron Jul 07 '14 at 14:14
  • Well, make one of the classes public. Not this is the issue. – AlexR Jul 07 '14 at 14:15
  • The error message is self explanatory : *reference to var is ambiguous, both variable var in Bof.Base1 and variable var in Base2 match* – Serge Ballesta Jul 07 '14 at 14:15
  • @AlexR, you're right, I deleted the answer. I suspect the answer is more complex, I think this can't be a compiler problem. – mxb Jul 07 '14 at 14:20
  • seems like the compiler got outsmarted.. `var` of the interface should be considered because it is static.. – TheLostMind Jul 07 '14 at 14:23
  • I think that the compiler was playing safe, but the issue should be raised on the `Test` class as a whole, regardless of reference to var in the code. On non static context the issue is valid and nonetheless an indication that something was programmed wrong. – mxb Jul 07 '14 at 14:26
  • In your test case initially compiler will tell you that an ambiguity is there, because the of the hierarchy at which the problem is. If you remove ambiguity than I am sure you will get the reference to non static member error. – Darshan Lila Jul 07 '14 at 14:33

4 Answers4

17

The JLS rule for field access ambiguity is

If the identifier names several accessible (§6.6) member fields in type T, then the field access is ambiguous and a compile-time error occurs.

And on the subject of accessibility

A member (class, interface, field, or method) of a reference type, or a constructor of a class type, is accessible only if the type is accessible and the member or constructor is declared to permit access:

It doesn't make a distinction about whether the instance field access would cause a compile error in a static context.

Note that you could have had

public static void main(String args[]) {
    Test test = new Test();
    System.out.println("var:" + test.var); 
}

You'd still have the ambiguity.

Sotirios Delimanolis
  • 274,122
  • 60
  • 696
  • 724
3

To make it unambiguous put the interface name as qualifying prefix:

class Test extends Base1 implements Base2 { 

      public static void main(String args[]) {
          System.out.println("var:" + Base2.var); 
      }
 }
Jens Baitinger
  • 2,230
  • 14
  • 34
  • Sometimes the compiler does not behave ans intelligent as we expect it to do. It might happen that the autor of the code meant the nonstatic field `Base2.var` In this case it is ambiguous (and wrong). (on the other hand, it is better to write unumbiguous code as the human brain needs some capacity to understand that. Just write code an idiot understands, than the compiler understands it as well :) – Jens Baitinger Jul 07 '14 at 14:31
1

Inititally at step one compiler will look for variable var in the class which you extend and the interface you implement. Since it finds a variable at both places in step two, it shows ambiguity.

Darshan Lila
  • 5,772
  • 2
  • 24
  • 34
1

The static and non static contexts do not rule on how variables are permitted to be accessed

The access modifiers are the ones which actually rule this...

change the access modifier for var in the Base1 to private and the ambiguity disappears, though this might not be the way you want it to shape up but access modfiers actually dictate the reference to instance variables rather than the static no static contexts.

class Base1 {
    private int var;
    //static int var=5;
}

interface Base2 {
    public static final int var = 0;
}

class ambiguousNonStaticCall extends Base1 implements Base2 { 
    public static void main(String args[]) {
        System.out.println("var:" + var); 
    }
}

The above code compiles fine.

Anirudh
  • 2,286
  • 4
  • 38
  • 64