Java中的静态方法和静态字段在某种程度上表现得很奇怪

时间:2011-11-05 10:33:57

标签: java inheritance static

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

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


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

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());

使用超级类的对象以及使用类名 Sub 静态方法sum()。强>


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

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

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


为什么会发生这种情况?

5 个答案:

答案 0 :(得分:8)

基本上,它是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#纠正的缺陷之一......)

答案 1 :(得分:5)

那里没有问题。静态方法只能访问静态字段并调用其他静态方法。你的例子中没有任何其他内容。

非静态方法可以访问静态和非静态方法和字段。同样,你的例子都没有违反。

答案 2 :(得分:3)

Sub.temps.temp是等效的,您可以同时使用它们,它的含义相同。但是第一个更好,因为它表明它是一个静态场。

答案 3 :(得分:2)

  

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

或者它的超类。

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

答案 4 :(得分:2)

在哪里可以看到静态代码访问的非静态字段或方法?对我来说,一切似乎都很好。

或许令人困惑的是,静态字段和方法可以通过实例以及类名来访问?它肯定是一个很大的丑陋,许多人认为它设计不好,但就是这样。