class A
{
int a = 2, b = 3;
public void display()
{
int c = a + b;
System.out.println(c);
}
}
class B extends A
{
int a = 5, b = 6;
}
class Tester
{
public static void main(String arr[])
{
A x = new A();
B y = new B();
x.display();
y.display();
}
}
Run Code Online (Sandbox Code Playgroud)
为什么输出为5,5?而不是5,11?.该y.display()
方法如何工作?
Jon*_*eet 109
为什么输出为5,5?
因为A.display()
只知道领域A.a
和A.b
.这些是任何代码所A
知道的唯一字段.看起来您希望声明B
"覆盖"现有的字段声明.他们没有.他们宣布新的字段隐藏的现有字段.变量实际上不像方法那样表现 - 覆盖变量的概念根本就不存在.从JLS第8.3节:
如果类声明了具有特定名称的字段,那么该字段的声明将被称为隐藏超类中具有相同名称的字段的任何和所有可访问声明,以及该类的超接口.
您可以通过更改来获得所需的效果,B
以便其构造函数更改其继承的现有字段的值A
:
class B extends A {
B() {
a = 5;
b = 6;
}
}
Run Code Online (Sandbox Code Playgroud)
请注意,这些不是变量声明.他们只是作业.当然在大多数代码中(好吧,我见过的大多数代码)中的字段A
都是私有的,因此无法访问B
,但这仅仅是为了解释语言行为的示例.
fab*_*ian 16
在课堂上A
你宣布领域a
和b
.该方法display
使用这些字段.在课堂上,B
您声明了同名的新字段.你实际上是在隐藏旧字段而不是"覆盖"它们.要为相同的字段分配不同的值,请使用构造函数:
class A {
A(int a, int b) {
this.a = a;
this.b = b;
}
A() {
this(2, 3);
}
int a,b;
public void display() {
int c=a+b;
System.out.println(c);
}
}
class B extends A {
B() {
super(5, 6);
}
}
Run Code Online (Sandbox Code Playgroud)
And*_*ndy 13
这样做时:
class B extends A
{
int a = 5, b = 6;
}
Run Code Online (Sandbox Code Playgroud)
你是不是重新定义 a
和b
,你创建具有相同名称的新变量.所以,你最终用四个变量(A.a
,A.b
,B.a
,B.b
).
当你调用display()
和计算的值c
,A.a
并A.b
会使用,不B.a
和B.b
小智 6
原因是Java使用词法范围的概念来实现可变分辨率.
从根本上说,有两种方法可以解决函数中的自由变量('free'表示不是局部的,不是绑定到函数参数):
1)针对声明函数的环境
2)针对执行函数的环境(调用)
Java是第一种方式,因此方法中的自由变量[ 静态地,在编译期间 ]针对它们的词法范围(环境)进行解析,其中包括:
您会在大多数编程语言中看到这种行为,因为它对开发人员是透明的,有助于防止变量阴影出错.
这与方法在Java中的工作方式相反:
class A {
public void foo() {
boo();
}
public void boo() {
System.out.println("A");
}
}
class B extends A {
@Override
public void boo() {
System.out.println("B");
}
}
class Main {
public static void main(String[] args) {
B b = new B();
b.foo(); // outputs "B"
}
}
Run Code Online (Sandbox Code Playgroud)
这称为动态调度:方法调用在运行时针对调用它的实际对象动态解析.
编译代码时,它几乎变成了:
class A extends java.lang.Object
{
int a=2,b=3;
public void display()
{
int c=a+b;
System.out.println(c);
}
}
class B extends A
{
int a = 5, b = 6;
public void display()
{
super(); //When you call y.display() then this statement executes.
}
}
class Tester
{
public static void main(String arr[])
{
A x = new A();
B y = new B();
x.display();
y.display();
}
}
Run Code Online (Sandbox Code Playgroud)
因此,当超级调用时,class A
正在调用方法.
现在去方法吧class A
.这int c = a + b;
意味着
c = this.a + this.b;
哪个是2 + 3.
结果是5.
归档时间: |
|
查看次数: |
3366 次 |
最近记录: |