Java 如何在接口和匿名实现中使用成员变量

Java 如何在接口和匿名实现中使用成员变量,java,interface,anonymous-class,Java,Interface,Anonymous Class,请检查下面的Java代码: 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 Imp

请检查下面的Java代码:

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();
}
如您所见,我已经匿名创建了一个接口。当我直接访问接口变量时,它将显示“旧值”

t、 meth().s=>“旧值”

通过getVal()方法访问它会返回正确的值

t、 meth().getVal()=>“字符串实现”


我不明白这段代码是怎么工作的,有人能给我解释一下吗?

在java中没有什么比
变量重写
更像
方法重写
。为
子类
命名一个新类型,然后在通过子类引用类型访问时,您将获得
的“字符串实现”

Access privilege
protected
只意味着我们可以访问子类中的变量,但不能覆盖它

即使您使用普通的
而不是
接口
,这也不会起作用。当您使用
super
类类型引用时,您只能从
super
类型等获取
实例
变量。。。。 此示例说明了第一种情况: 例如:

此示例说明了第二种情况: 它打印“字符串实现”

你有接口类型的引用,这就是为什么它直接引用接口,你得到“旧值”

当您调用方法getVal()时,您引用的是该方法的实际实现,这就是调用实际实现的getVal的原因。这表示具有以下值的当前实例:

public String s = "String Implementation";

接口中声明的
s
变量与您在匿名内部类中声明的
s
变量完全不同

接口变量实际上只是被设计成常量——它们不是每个实现需要提供的API的一部分。特别是,它们是隐式静态和最终的

从:

接口主体中的每个字段声明都是隐式公开、静态和最终的。允许为此类字段冗余指定任何或所有这些修饰符

您已经通过实现实例访问了该字段这一事实与此无关-以下代码:

System.out.println(t.meth().s);
实际上:

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

我强烈建议您避免在接口中使用除真正常量以外的变量。。。即使如此,也只有在真正有意义的地方。不清楚您想要实现什么,但是在接口中声明字段在我看来不是一个好办法。

在接口中声明的字段是常量

因此,在写作时

interface TestInter
{
  String s = "Old value";
  String getVal();
}
您正在声明一个常数s。 这就是为什么
t.meth().s
正在打印
旧值的原因


t.meth().getVal()
正在打印匿名类的
s
字段的内容。

您可能不鼓励使用或建议避免在接口中使用变量,对吧?@JonSkeet但即使他扩展了普通类而不是接口,他也会得到相同的结果。我测试过了。我说的对吗,这就是我在回答中提到的。。。如果我错了,请纠正我。。。谢谢:)@pinkpartner:是的,你得到了同样的结果,但原因略有不同。您完全正确,没有变量重写-仍然会有两个不同的变量-但对于接口版本,情况更糟,因为字段是隐式静态的。
public String s = "String Implementation";
System.out.println(t.meth().s);
t.meth();
System.out.println(TestInter.s);
interface TestInter
{
  String s = "Old value";
  String getVal();
}