当我有 2 个同名静态变量时会发生什么?

问题描述 投票:0回答:1

我是一名 Java 初学者,无法理解代码中

System.out.println(((A)b).s)
的输出。

我的理解是,静态变量可以在类中的任何位置更改,因此我希望其值为 2。在研究代码后,我发现静态变量有两个值

s
...为什么这是这样发生这种情况,既然名称和类型相等,就不应该引用同一个变量吗?

import java.util.ArrayList;
import java.util.List;

class A {
    static int s;
    int o;
    A(int i) { o = i; s = i + 1; 
    System.out.println("A constructor called! String s is:" + s);
    }
    int m(int i) { return i; }
    @Override
    public String toString() { return String.format("A2S: %d %d" , o, s); }
}

class B extends A {
    int o;
    B(int i) { super(i); o = i; }
    @Override
    int m(int i) { return i + s; }
    @Override
    public String toString() { return String.format("B2S: %d %d", o, s); }
}

class C extends A {
    static int s;
    int o;
    C(int i) { super(i); o = i; s = i - 1; 
    System.out.println("C constructor called! String s is:" + s);}
    @Override
    int m(int i) { return i + s; }
    @Override
    public String toString() { return String.format("C2S: %d %d", o, s); }
}

class D extends C {
    int o;
    D(int i) { super(i); o = i; }
    @Override
    int m(int i) { return i + o + s; }
    @Override
    public String toString() { return String.format("D2S: %d %d", o, s); }
}

public class Question {
    public static void main(String[] args) {
        int o = 1;
        B b = new B(7);
        System.out.println(b);
        C c = new C(5);
        System.out.println(c);
        D d = new D(3);
        System.out.println(d);
        System.out.println(((C)d).o);
        System.out.println("This is the s: " + b.s);
        System.out.println("This is the s: " + c.s);
        System.out.println("This is the s: " + d.s);
        System.out.println(((A)b).s);
        System.out.println(((A)d).m(o));
    }
}
java variables static
1个回答
0
投票

s
中的声明
A
声明了与
s
中的
C
声明不同的变量。 是的,它们是具有相同(简单)名称的不同变量
s

当您使用名称

s
时,其含义取决于您在何处使用它。

  • A
    中,简单名称
    s
    A.s
    指的是同一事物。
  • B
    中,简单名称
    s
    指的是
    A.s
    。 该名称继承自
    A
    的命名空间。
  • C
    中,简单名称
    s
    现在指的是在
    s
    中声明的
    C
    ;即
    C.s
  • D
    中,简单名称
    s
    也指从
    C.s
    命名空间继承的
    C

从技术上讲,在

s
中声明的变量
A
s 中声明的
C
隐藏
。 这也适用于
D

这都是Java语言规范中规定的。

这就是为什么你的代码会有这样的行为。

为什么会发生这种情况,既然名称和类型相等,就不应该引用同一个变量吗?

不。 这是不正确的。 你的直觉不正确。 有两个不同的

static
变量称为
s
。 他们的全名是
A.s
C.s


请注意,您可以将

A.s
称为
B.s
,将
C.s
称为
D.s
。 但不要这样做。 这样做是“不好的风格”,因为它很容易误导读者认为(比如说)B.s
B
的静态变量。 事实并非如此。

在此:

System.out.println(((A)b).s);

您引用 
s

的语法使得

s
看起来是实例变量。 实际上这是指静态变量
A.s
。 事实上,以下所有内容都会打印该变量:
System.out.println(A.s);
System.out.println(B.s);
System.out.println(a.s);  // 其中 

a

是类型为

A
的变量 System.out.println(b.s); // 其中
b
是类型为
B
的变量 System.out.println(((A)b).s);
但只有第一个才是好的风格。  其他的都以某种方式产生误导,应该避免。

© www.soinside.com 2019 - 2024. All rights reserved.