请检查以下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()=> “字符串实现”
我不明白这段代码是如何工作的,有人可以向我解释一下吗?
答案 0 :(得分:7)
接口中声明的s
变量与您在匿名内部类中声明的s
变量完全分开。
接口变量实际上只是设计为常量 - 它们不是每个实现需要提供的API的一部分。特别是,它们是隐含的静态和最终的。
接口主体中的每个字段声明都是隐式的public,static和final。允许为这些字段冗余地指定任何或所有这些修饰符。
您通过实现实例访问该字段的事实无关紧要 - 此代码:
System.out.println(t.meth().s);
实际上是:
t.meth();
System.out.println(TestInter.s);
我强烈建议你避免在接口中使用变量,除了以获得真正的常量......即便如此,只有在它真正有意义的地方。目前尚不清楚你想要实现的目标,但在界面中声明一个字段并不是IMO的好方法。
答案 1 :(得分:3)
在java中没有像variable-overriding
这样的method overriding
。为subclass
命名一个新类型,当您通过子类引用类型访问时,您将获得"String Implementation"
。
访问权限protected
仅表示我们可以访问子类中的变量,但不能覆盖它。
即使您使用普通class
代替interface
,这也行不通。当您使用super
类类型引用时,您只能从instance
类型中获取super
变量等等....
这个例子说明了第一种情况:
例如:
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";
}
这个例子说明了第二种情况:
它会打印"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";
}
答案 2 :(得分:1)
When i access a interface variable directly
你有接口类型的引用,这就是为什么它直接引用接口而你得到“旧值”
Accessing getVal() method, showing proper values
当你调用方法getVal()时,你会引用这个方法的实际实现,这就是调用实际实现的getVal的原因。这意味着具有以下值的当前实例:
public String s = "String Implementation";
答案 3 :(得分:1)
在接口中声明的字段是常量。
因此,写作时
interface TestInter
{
String s = "Old value";
String getVal();
}
你宣布一个常数s。
这就是t.meth().s
打印Old value
t.meth().getVal()
正在打印匿名班级s
字段的内容。