Question

Please check the Java code below:

public class Test
{
  public static void main(String arg[]) throws Throwable
  {
      Test t = new Test();
      System.out.println(t.meth().s);           //OP: Old value
      System.out.println(t.meth().getVal());    //OP: String Implementation
  }
  private TestInter meth()
  {
    return new TestInter()
    {
      public String s = "String Implementation";
      public String getVal()
      {
        return this.s;
      }
    };
  }
}
interface TestInter
{
  String s = "Old value";
  String getVal();
}

As you see I have created an interface anonymously. When I access the interface variable directly, it will show "Old value".

t.meth().s => "Old value"

Accessing it through the getVal() method returns proper values,

t.meth().getVal() => "String Implementation"

I don't understand how this code works, can somebody explain it to me?

Was it helpful?

Solution

The s variable declared in the interface is entirely separate from the s variable you've declared in your anonymous inner class.

Interface variables are really just designed to be constants - they aren't part of the API each implementation needs to provide. In particular, they're implicitly static and final.

From the JLS section 9.3:

Every field declaration in the body of an interface is implicitly public, static, and final. It is permitted to redundantly specify any or all of these modifiers for such fields.

The fact that you've accessed the field via an implementation instance is irrelevant - this code:

System.out.println(t.meth().s);

is effectively:

t.meth();
System.out.println(TestInter.s);

I would strongly encourage you to avoid using variables in interfaces except for genuine constants... and even then, only where it really makes sense. It's not clear what you're trying to achieve, but declaring a field in an interface isn't a good way forward IMO.

OTHER TIPS

There is nothing like variable-overriding like method overriding in java. Name a new type for subclass, then you will get the "String Implementation", when you access through the subclass reference type.

Access privilege protected only means we can access the variable in a subclass but not that it can be override.

Even if you are using normal class instead of interface this won't work. When you refer using super class type, you only get the instance variables from super type and so on.... This example illustrates the first case: Example:

public class Tester
{
  public static void main(String arg[]) throws Throwable
  {
      Tester t = new Tester();
      System.out.println(t.meth().s); // it prints "Old value" because your type is TestInter           
  }
  private TestInter meth()
  {
    return new TestInter()
    {
       protected String s = "String Implementation";

    };
  }
}
class TestInter
{
  protected String s = "Old value";

}

This example illustrates the second case: It prints "String Implementation"

 public class Tester
{
  public static void main(String arg[]) throws Throwable
  {
      Tester t = new Tester();
      System.out.println(t.meth().s);           
  }
  private SubTestInter meth()
  {
    return new SubTestInter();
  }
}
class SubTestInter extends TestInter{
       protected String s = "String Implementation";
}
class TestInter
{
  protected String s = "Old value";

}
When i access a interface variable directly

You have the reference of Interface type, that's why it refers to interface directly and you get "Old value"

Accessing getVal() method, showing proper values

When you invoke method getVal() you refer to actual implementation of this method and that's why getVal of actual implementation is called. This means current instance with the following value:

public String s = "String Implementation";

Fields declared in an interface are constants.

Thus, when writing

interface TestInter
{
  String s = "Old value";
  String getVal();
}

You are declaring a constant s. That's why t.meth().s is printing Old value

t.meth().getVal() is printing the content of the field s of your anonymous class.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top