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

package hello;

public class Hello {

    Clock clock = new Clock();

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

但是它给出了错误

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

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

static Clock clock = new Clock();

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


当前回答

Java程序中的成员可以在其声明/定义之前使用关键字“static”声明为static。当成员声明为静态时,本质上意味着该成员由类的所有实例共享,而无需为每个实例复制。

因此static是Java中使用的非类修饰符,可以应用于以下成员:

变量 方法 块 类(更确切地说,嵌套类)

当成员被声明为静态时,可以不使用对象访问它。这意味着在实例化类之前,静态成员是活动的并且是可访问的。与其他非静态类成员不同的是,当类的对象超出作用域时,类成员就不再存在,而静态成员显然仍然是活动的。

Java中的静态变量

类中声明为静态的成员变量称为静态变量。它也被称为“类变量”。一旦变量声明为静态,内存只分配一次,而不是在类实例化时每次都分配。因此,您可以在不引用对象的情况下访问静态变量。

下面的Java程序描述了静态变量的用法:

class Main
{
// static variables a and b
static int a = 10;
static int b;

static void printStatic()
{
    a = a /2;
    b = a;

    System.out.println("printStatic::Value of a : "+a + " Value of b : 
 "+b);
}  

public static void main(String[] args)
{
   printStatic();
   b = a*5;
   a++;

System.out.println("main::Value of a : "+a + " Value of b : "+b);
   }
 }

输出:

printStatic::Value of a : Value of b : 5
main::Value of a : 6 Value of b : 25

在上面的程序中,我们有两个静态变量,即a和b。我们在函数“printStatic”和“main”中修改这些变量。请注意,即使函数的作用域结束,这些静态变量的值也会在函数之间保留。输出显示了两个函数中变量的值。

静态方法

在Java中,当一个方法前面带有关键字“static”时,该方法就是静态的。

关于静态方法,你需要记住的要点包括:

A static method belongs to the class as against other non-static methods that are invoked using the instance of a class. To invoke a static method, you don’t need a class object. The static data members of the class are accessible to the static method. The static method can even change the values of the static data member. A static method cannot have a reference to ‘this’ or ‘super’ members. Even if a static method tries to refer them, it will be a compiler error. Just like static data, the static method can also call other static methods. A static method cannot refer to non-static data members or variables and cannot call non-static methods too.

下面的程序显示了静态方法在Java中的实现:

class Main
{
  // static method
  static void static_method()
{
    System.out.println("Static method in Java...called without any 
object");
}

public static void main(String[] args)
{
    static_method();
   }
 }

输出:

Static method in Java...called without any object

Java中的静态块

就像在c++、c#等编程语言中有函数块一样,在Java中也有一个特殊的块,称为“静态”块,通常包括与静态数据相关的代码块。

这个静态块在创建类的第一个对象时(准确地说是在类加载时)或在块内的静态成员被使用时执行。

下面的程序展示了静态块的用法。

class Main
{
  static int sum = 0;
  static int val1 = 5;
  static int val2;

// static block
 static {
    sum = val1 + val2;
    System.out.println("In static block, val1: " + val1  + " val2: "+ 
val2 + " sum:" + sum);
    val2 = val1 * 3;
    sum = val1 + val2;
}

 public static void main(String[] args)
{
    System.out.println("In main function, val1: " + val1  + " val2: "+ val2 + " sum:" + sum);
  }
}

输出:

In static block, val1: 5 val2: 0 sum:5
In main function, val1: val2: 15 sum:20

静态类

在Java中,有静态块、静态方法,甚至静态变量。因此,很明显,您也可以拥有静态类。在Java中,可以将一个类放在另一个类中,这被称为嵌套类。包含嵌套类的类称为外层类。

在Java中,虽然可以将嵌套类声明为Static,但不能将外部类声明为Static。

现在让我们研究Java中的静态嵌套类。

静态嵌套类

如前所述,可以将Java中的嵌套类声明为静态类。静态嵌套类与非静态嵌套类(内部类)在某些方面有所不同,如下所示。

与非静态嵌套类不同,嵌套静态类不需要外部类引用。

静态嵌套类只能访问外部类的静态成员,而非静态类可以访问外部类的静态成员和非静态成员。

下面给出了一个静态嵌套类的示例。


class Main{
  private static String str = "SoftwareTestingHelp";

     //Static nested class
     static class NestedClass{
        //non-static method
            public void display() {

            System.out.println("Static string in OuterClass: " + str);
            }

    }
   public static void main(String args[])
   {
            Main.NestedClassobj = new Main.NestedClass();
            obj.display();
   }
}

输出

Static string in OuterClass: SoftwareTestingHelp

我认为这就是静态关键字在java中的工作方式。

其他回答

在Java中,static关键字可以简单地视为表示以下内容:

“不考虑或与任何特定情况有关”

如果你以这种方式思考static,就更容易理解它在各种上下文中的用法:

静态字段是属于类而不是任何特定实例的字段 静态方法是一种没有这种概念的方法;它在类上定义,并且不知道该类的任何特定实例,除非将引用传递给它 静态成员类是一个嵌套类,没有任何关于其外围类实例的概念或知识(除非将对外围类实例的引用传递给它)

这意味着在Hello中只有一个“clock”实例,而不是每个“Hello”类的单独实例都有一个,或者更多——因此,这意味着在“Hello”类的所有实例之间将有一个通用的共享“clock”引用。

因此,如果你在代码的任何地方做一个“new Hello”: A-在第一种情况下(在更改之前,不使用“static”),它会在每次调用“new Hello”时创建一个新的时钟,但是 B-在第二种情况下(在更改之后,使用“static”),每个“new Hello”实例仍然会共享和使用最初创建的初始和相同的“clock”引用。

除非你需要在main之外的某个地方使用“clock”,否则这样也可以:

package hello;
public class Hello
{
    public static void main(String args[])
    {
      Clock clock=new Clock();
      clock.sayTime();    
    }
}

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


这是由于关键字重用,从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'也是一个明智的选择,特别是如果你不想在你的语言中添加更多保留的关键字。

也可以考虑没有“this”指针的静态成员。它们在所有实例之间共享。

静态意味着您不必创建类的实例来使用与类关联的方法或变量。在你的例子中,你可以调用:

Hello.main(new String[]()) //main(...) is declared as a static function in the Hello class

直接,而不是:

Hello h = new Hello();
h.main(new String[]()); //main(...) is a non-static function linked with the "h" variable

在静态方法(属于类)内部,您不能访问任何非静态的成员,因为它们的值取决于类的实例化。非静态Clock对象是实例成员,对于Hello类的每个实例都有不同的值/引用,因此不能从类的静态部分访问它。