【问题标题】:Static methods and static fields in Java behave somewhat in a strange wayJava 中的静态方法和静态字段的行为有些奇怪
【发布时间】:2011-11-05 10:33:57
【问题描述】:

按照惯例,Java 中的静态方法只能访问静态字段或其他静态方法。然而,下面的简单代码 sn-p 似乎违反了约定。让我们考虑以下 Java 中的简单代码 sn-p。

class Super
{
    protected static int x;
    protected static int y;

    public Super(int x, int y)
    {
        Super.x=x;
        Super.y=y;
    }

    public static int sum()
    {
        return(x+y);
    }
}

final class Sub extends Super
{
    public static int temp=100;
    public Sub(int x, int y)
    {
        super(x, y);
    }

    public void concreateMethod()
    {
        System.out.println("\nInstance variable x = "+x);
        System.out.println("Instance variable y = "+y);
    }
}

final public class Main
{
    public static void main(String[] args)
    {
        Sub s=new Sub(10, 5);
        System.out.println("\nAssociating with object x = "+s.x);
        System.out.println("Associating with object   y = "+s.y);

        System.out.println("\nAssociating with class name x = "+Sub.x);
        System.out.println("Associating with class name   y = "+Sub.y);

        System.out.println("\nSummation (Associating with object)   = "+s.sum());
        System.out.println("Summation (Associating with class name) = "+Sub.sum());

        System.out.println("\nAssociating with class name temp = "+Sub.temp);
        System.out.println("Associating with object temp =    = "+s.temp);

        System.out.println("\nConcreate method called.");
        s.concreateMethod();
    }
}

上面的代码使用相应的语句产生以下输出。

与对象 x = 10 关联
关联对象 y = 5


与类名 x = 10 关联
关联类名 y = 5


求和(与对象关联)= 15
求和(与类名关联)= 15


与类名 temp = 100 关联
关联对象 temp = = 100


调用了 Concreate 方法。
实例变量 x = 10
实例变量 y = 5


静态字段 s 和 x 正在使用 Sub 类的对象通过 main() 方法中的以下语句访问,尽管它们被声明为 static在超类Super中。

Sub s=new Sub(10, 5); 
System.out.println("\nAssociating with object x = "+s.x);
System.out.println("Associating with object   y = "+s.y);

下面的说法当然不用怀疑。

System.out.println("\nAssociating with class name x = "+Sub.x);
System.out.println("Associating with class name   y = "+Sub.y);

由于 x 和 y 是静态的,所以当然可以通过这种方式访问​​它们。


同样是方法调用,注意以下语句。

Sub s=new Sub(10, 5);
System.out.println("\nSummation (Associating with object)   = "+s.sum());
System.out.println("Summation (Associating with class name) = "+Sub.sum());

两种方式,static 方法 sum() 都使用类 Super 的对象和类名 Sub强>。


Sub 类中声明的静态字段 temp 再次类似情况

System.out.println("\nAssociating with class name temp = "+Sub.temp);
System.out.println("Associating with object temp =    = "+s.temp);

静态字段 temp 正在以两种方式访问​​。


为什么会出现这种情况?

【问题讨论】:

  • 这里发生了什么?您没有足够仔细地阅读自己的代码。这里唯一的谜团是这个问题的原因。

标签: java inheritance static


【解决方案1】:

基本上这是 Java IMO 设计中的一个缺陷,它允许引用静态成员(方法和字段)就好像它们是实例成员一样。这在这样的代码中可能会非常混乱:

Thread newThread = new Thread(runnable);
newThread.start();
newThread.sleep(1000);

看起来就像它正在让新线程进入睡眠状态,但它实际上编译成这样的代码:

Thread newThread = new Thread(runnable);
newThread.start();
Thread.sleep(1000);

因为sleep 是一个静态方法,它只会让当前 线程休眠。

实际上,甚至没有检查该变量的非空值(不再检查;我相信它曾经是):

Thread t = null;
t.sleep(1000);

某些 IDE 可以配置为针对此类代码发出警告或错误 - 您不应该这样做,因为它会损害可读性。 (这是 C# 纠正的缺陷之一……)

【讨论】:

  • (w.r.t. 检查空值,IIRC javac 错误是,如果 .static 之前的表达式本身包含空解引用,那么在某些情况下不会导致 NPE。)
【解决方案2】:

那里没有问题。如您所述,静态方法只能访问静态字段并调用其他静态方法。您的示例中没有其他内容。

非静态方法可以访问静态和非静态方法和字段。同样,您的示例都没有违反这一点。

【讨论】:

    【解决方案3】:

    Sub.temps.temp 是等价的,你可以同时使用,意思是一样的。但是第一个更好,因为它表明它是一个静态字段。

    【讨论】:

      【解决方案4】:

      Java 中的静态方法只能访问静态字段或同一类中声明的其他静态方法

      或其超类。

      我在这里没有看到任何违规行为,您可以通过其具体对象或类名访问静态字段/方法。两者指的是同一个东西。

      【讨论】:

        【解决方案5】:

        您在哪里看到静态代码访问的非静态字段或方法?在我看来一切都很好。

        也许让您感到困惑的是静态字段和方法可以通过实例以及类名来访问?这当然是一个非常丑陋的设计,许多人认为它是糟糕的设计,但仅此而已。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2012-05-05
          • 1970-01-01
          • 1970-01-01
          • 2023-03-18
          • 2021-09-24
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多