具体来说,我正在尝试以下代码:

package hello;

public class Hello {

    Clock clock = new Clock();

    public static void main(String args[]) {
        clock.sayTime();
    }
}

但是它给出了错误

不能访问静态方法主中的非静态字段

所以我把时钟的声明改为这样:

static Clock clock = new Clock();

这招奏效了。将该关键字放在声明之前意味着什么?它究竟会做什么和/或限制可以对该对象做什么?


当前回答

Main()是一个静态方法,它有两个基本限制:

静态方法不能使用非静态数据成员,也不能直接调用非静态方法。 This()和super()不能在静态上下文中使用。 A类{ Int a = 40;/ /非静态 public static void main(String args[]) { System.out.println(一个); } }

输出:编译时错误

其他回答

只能在静态方法中访问静态变量,因此当我们声明静态变量时,那些getter和setter方法将是静态方法

静态方法是我们可以通过类名访问的类级别

下面是静态变量Getters和Setters的例子:

public class Static 
{

    private static String owner;
    private static int rent;
    private String car;
    public String getCar() {
        return car;
    }
    public void setCar(String car) {
        this.car = car;
    }
    public static int getRent() {
        return rent;
    }
    public static void setRent(int rent) {
        Static.rent = rent;
    }
    public static String getOwner() {
        return owner;
    }

    public static void setOwner(String owner) {
        Static.owner = owner;
    }

}

这里有一个问题是关于这个概念中“静态”一词的选择。这个问题已经解决了,但我认为词源问题还没有明确解决。所以…


这是由于关键字重用,从C开始。

考虑C语言中的数据声明(在函数体中):

    void f() {
        int foo = 1;
        static int bar = 2;
         :
    }

变量foo在输入函数时在堆栈上创建(并在函数终止时销毁)。相比之下,bar总是在那里,所以在普通英语中它是“静态的”——它不会去任何地方。

Java和类似的语言对数据有相同的概念。数据可以为类的每个实例(每个对象)分配,也可以为整个类分配一次。因为Java的目标是为C/ c++程序员提供熟悉的语法,所以这里使用“static”关键字是合适的。

    class C {
        int foo = 1;
        static int bar = 2;
         :
    }

最后,我们来谈谈方法。

    class C {
        int foo() { ... }
        static int bar() { ... }
         :
    }

从概念上讲,类c的每个实例都有一个foo()实例,整个类c只有一个bar()实例。这与我们讨论的数据的情况类似,因此使用'static'也是一个明智的选择,特别是如果你不想在你的语言中添加更多保留的关键字。

字段可以分配给类或类的实例。默认情况下,字段是实例变量。通过使用static,字段变成了类变量,因此有且只有一个时钟。如果你在一个地方做了改动,它就会随处可见。实例变量的改变是彼此独立的。

这个讨论到目前为止忽略了类加载器的注意事项。严格来说,对于给定的类加载器,Java静态字段在类的所有实例之间共享。

static关键字意味着某些东西(字段、方法或嵌套类)与类型相关,而不是与类型的任何特定实例相关。例如,在没有Math类实例的情况下调用Math.sin(…),实际上您无法创建Math类的实例。

有关更多信息,请参阅Oracle的Java教程的相关部分。


旁注

不幸的是,Java允许你像访问实例成员一样访问静态成员。

// Bad code!
Thread.currentThread().sleep(5000);
someOtherThread.sleep(5000);

这使它看起来好像sleep是一个实例方法,但实际上它是一个静态方法——它总是使当前线程休眠。更好的做法是在调用代码中清楚地说明这一点:

// Clearer
Thread.sleep(5000);