How to use member variables with interfaces and anonymous implementations

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 can see, I created the 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 the correct values,

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

I don’t understand how this code works, can someone explain this to me?

+8
java interface anonymous-class
source share
4 answers

The variable s declared in the interface is completely separate from the variable s that you specified in your anonymous inner class.

Interface variables are actually just designed for constants - they are not part of the API that every implementation should provide. In particular, they are implicitly static and final.

From the JLS 9.3 section:

Each field declaration in the body of the interface is implicit public, static, and final. It is allowed to over-specify any or all of these modifiers for such fields.

The fact that you accessed the field through an implementation instance does not matter - this code:

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

effective:

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

I would strongly recommend that you avoid using variables in interfaces other than real constants ... and even then, only where it really makes sense. It is not clear what you are trying to achieve, but declaring a field in an interface is not a good way to promote IMO.

+7
source share

In java there is nothing like variable-overriding like method overriding . Name the new type for subclass , then you will get "String Implementation" when accessing the link type of the subclass.

Access to the protected privilege means that we can access the variable in a subclass, but not that it can be redefined.

Even if you use a regular class instead of an interface , this will not work. When you refer to the type of the super class, you only get instance variables from the 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"; } 
+3
source share
 When i access a interface variable directly 

You have a link to the type of interface, so it accesses the interface directly, and you get the "Old value"

 Accessing getVal() method, showing proper values 

When you call the getVal () method, you refer to the actual implementation of this method and why getVal is called from the actual implementation. This means the current instance with the following value:

 public String s = "String Implementation"; 
+1
source share

Fields declared in the interface are constants.

So when writing

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

You declare a constant s. Therefore t.meth().s prints Old value

t.meth().getVal() prints the contents of the s field of your anonymous class.

+1
source share

All Articles