458

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

package hello;

public class Hello {

    Clock clock = new Clock();

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

但它给出了错误

无法访问静态方法 main 中的非静态字段

所以我将声明更改为clock

static Clock clock = new Clock();

它奏效了。将关键字放在声明之前是什么意思?就可以对该对象执行的操作而言,它究竟会做什么和/或限制什么?

4

22 回答 22

647

static成员属于类而不是特定实例。

这意味着只有一个static字段的实例存在[1],即使您创建了一百万个该类的实例或者您没有创建任何实例。它将由所有实例共享。

由于static方法也不属于特定实例,因此它们不能引用实例成员。在给出的示例中,main不知道应该引用Hello哪个类的实例(因此也不知道该类的哪个实例Clock)。static会员只能指static会员。实例成员当然可以访问static成员。

旁注:当然,static成员可以通过对象引用访问实例成员。

例子:

public class Example {
    private static boolean staticField;
    private boolean instanceField;
    public static void main(String[] args) {
        // a static method can access static fields
        staticField = true;

        // a static method can access instance fields through an object reference
        Example instance = new Example();
        instance.instanceField = true;
    }

[1]:根据运行时特性,它可以是每个 ClassLoader 或 AppDomain 或线程一个,但这不是重点。

于 2009-01-05T17:44:31.243 回答
131

这意味着 Hello 中只有一个“时钟”实例,而不是每个单独的“Hello”类实例一个,或者更多,这意味着在所有实例之间将有一个共同共享的“时钟”引用“你好”类。

因此,如果您要在代码中的任何位置执行“新 Hello”: A- 在第一个场景中(在更改之前,不使用“静态”),每次调用“新 Hello”时都会生成一个新时钟,但是 B- 在第二种情况下(更改后,使用“静态”),每个“新 Hello”实例仍将共享并使用最初创建的相同“时钟”引用。

除非您在 main 之外的某个地方需要“时钟”,否则这也可以:

package hello;
public class Hello
{
    public static void main(String args[])
    {
      Clock clock=new Clock();
      clock.sayTime();    
    }
}
于 2009-01-05T17:45:56.123 回答
97

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

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


边注

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

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

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

// Clearer
Thread.sleep(5000);
于 2009-07-04T06:35:47.447 回答
42

Java 中的static关键字意味着变量或函数在该类的所有实例之间共享,因为它属于type,而不是实际对象本身。

因此,如果您有一个变量:private static int i = 0;并且您在一个实例中递增它 ( i++),则该更改将反映在所有实例中。i现在在所有情况下都是 1。

无需实例化对象即可使用静态方法。

于 2009-07-04T06:26:07.993 回答
27

静态成员的基本用法...

public class Hello
{
    // value / method
    public static String staticValue;
    public String nonStaticValue;
}

class A
{
    Hello hello = new Hello();
    hello.staticValue = "abc";
    hello.nonStaticValue = "xyz";
}

class B
{
    Hello hello2 = new Hello(); // here staticValue = "abc"
    hello2.staticValue; // will have value of "abc"
    hello2.nonStaticValue; // will have value of null
}

这就是您可以在所有类成员中共享值的方式,而无需将类实例 Hello 发送到其他类。而且你不需要创建类实例。

Hello hello = new Hello();
hello.staticValue = "abc";

您可以通过类名调用静态值或方法:

Hello.staticValue = "abc";
于 2014-03-13T18:26:41.230 回答
22

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

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

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

于 2009-01-05T17:45:52.037 回答
21

Java中的静态:

静态是非访问修饰符。static 关键字属于类而不是类的实例。可用于将变量或方法附加到类。

静态关键字可用于:

方法

多变的

嵌套在另一个类中的类

初始化块

不能用于:

类(未嵌套)

构造函数

接口

方法局部内部类(差异然后嵌套类)

内部类方法

实例变量

局部变量

例子:

想象一下下面的例子,它有一个名为 count 的实例变量,它在构造函数中递增:

package pkg;

class StaticExample {
    int count = 0;// will get memory when instance is created

    StaticExample() {
        count++;
        System.out.println(count);
    }

    public static void main(String args[]) {

        StaticExample c1 = new StaticExample();
        StaticExample c2 = new StaticExample();
        StaticExample c3 = new StaticExample();

    }
}

输出:

1 1 1

由于实例变量在对象创建时就获得了内存,所以每个对象都会有实例变量的副本,如果递增,就不会反映到其他对象。

现在,如果我们将实例变量 count 更改为静态变量,那么程序将产生不同的输出:

package pkg;

class StaticExample {
    static int count = 0;// will get memory when instance is created

    StaticExample() {
        count++;
        System.out.println(count);
    }

    public static void main(String args[]) {

        StaticExample c1 = new StaticExample();
        StaticExample c2 = new StaticExample();
        StaticExample c3 = new StaticExample();

    }
}

输出:

1 2 3

在这种情况下,静态变量只会获得一次内存,如果任何对象更改了静态变量的值,它将保留其值。

静态与最终:

声明为final 和 static的全局变量在整个执行过程中保持不变。因为,静态成员存储在类内存中,并且在整个执行过程中只加载一次。它们对类的所有对象都是通用的。如果将静态变量声明为 final,则任何对象都无法更改其值,因为它是 final。因此,声明为 final 和 static 的变量有时称为常量。接口的所有字段都称为常量,因为默认情况下它们是最终的和静态的。

在此处输入图像描述

图片资源:最终静态

于 2016-08-14T13:03:23.113 回答
16

要添加到现有答案,让我尝试使用图片:

2% 的利率适用于所有储蓄账户。因此它是静态的。

平衡应该是个体的,所以它不是静态的。

在此处输入图像描述

于 2016-07-18T07:32:54.627 回答
13

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

于 2009-01-05T18:14:03.477 回答
7

可以将字段分配给类或类的实例。默认情况下,字段是实例变量。通过使用static该字段成为一个类变量,因此只有一个clock。如果您在一个地方进行更改,它在任何地方都可见。实例变量彼此独立地更改。

于 2009-01-05T17:48:41.860 回答
7

关键字static用于表示属于类本身而不是实例的字段或方法。使用您的代码,如果对象Clock是静态的,则该类的所有实例都Hello将共享此Clock数据成员(字段)。如果将其设为非静态,则每个单独的实例都Hello可以有一个唯一的Clock字段。

您向您的类添加了一个main方法,Hello以便您可以运行代码。问题在于main方法是静态的,因此它不能引用其中的非静态字段或方法。您可以通过两种方式解决此问题:

  1. 将类的所有字段和方法设为Hello静态,以便可以在方法中引用它们。这真的不是一件好事(或者使字段和/或方法静态的错误原因)
  2. 在 main 方法中创建类的一个实例,Hello并按照最初的预期方式访问它的所有字段和方法。

对您而言,这意味着对您的代码进行以下更改:

package hello;

public class Hello {

    private Clock clock = new Clock();

    public Clock getClock() {
        return clock;
    }

    public static void main(String args[]) {
        Hello hello = new Hello();
        hello.getClock().sayTime();
    }
}
于 2014-11-12T19:50:25.173 回答
6

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

“不考虑或与任何特定实例有关”

如果您static以这种方式思考,则更容易理解它在遇到的各种上下文中的使用:

  • static字段是属于类而不是任何特定实例的字段

  • 方法static是没有 ; 概念的方法this。它是在类上定义的,并且不知道该类的任何特定实例,除非将引用传递给它

  • 成员类是一个static嵌套类,对其封闭类的实例没有任何概念或知识(除非将对封闭类实例的引用传递给它)

于 2015-10-03T16:15:32.460 回答
5

静态使时钟成员成为类成员而不是实例成员。如果没有 static 关键字,您将需要创建 Hello 类的实例(它有一个时钟成员变量) - 例如

Hello hello = new Hello();
hello.clock.sayTime();
于 2009-01-05T17:45:58.323 回答
5

静态方法不使用定义它们的类的任何实例变量。可以在此页面上找到对差异的很好解释

于 2009-01-05T17:45:58.947 回答
5

我已经对“助手”类中的静态方法(仅在可能的情况下)产生了兴趣。

调用类不需要创建帮助类的另一个成员(实例)变量。您只需调用助手类的方法。辅助类也得到了改进,因为您不再需要构造函数,并且不需要成员(实例)变量。

可能还有其他优点。

于 2012-12-17T20:34:04.750 回答
4
//Here is an example 

public class StaticClass 
{
    static int version;
    public void printVersion() {
         System.out.println(version);
    }
}

public class MainClass 
{
    public static void main(String args[]) {  
        StaticClass staticVar1 = new StaticClass();
        staticVar1.version = 10;
        staticVar1.printVersion() // Output 10

        StaticClass staticVar2 = new StaticClass();
        staticVar2.printVersion() // Output 10
        staticVar2.version = 20;
        staticVar2.printVersion() // Output 20
        staticVar1.printVersion() // Output 20
    }
}
于 2018-09-18T12:59:33.830 回答
3

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

于 2009-01-05T19:36:22.890 回答
3

了解静态概念

public class StaticPractise1 {
    public static void main(String[] args) {
        StaticPractise2 staticPractise2 = new StaticPractise2();
        staticPractise2.printUddhav(); //true
        StaticPractise2.printUddhav(); /* false, because printUddhav() is although inside StaticPractise2, but it is where exactly depends on PC program counter on runtime. */

        StaticPractise2.printUddhavsStatic1(); //true
        staticPractise2.printUddhavsStatic1(); /*false, because, when staticPractise2 is blueprinted, it tracks everything other than static  things and it organizes in its own heap. So, class static methods, object can't reference */

    }
}

二等舱

public class StaticPractise2 {
    public static void printUddhavsStatic1() {
        System.out.println("Uddhav");
    }

    public void printUddhav() {
        System.out.println("Uddhav");
    }
}
于 2017-04-04T05:48:02.163 回答
2

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

  1. 静态方法不能使用非静态数据成员或直接调用非静态方法。
  2. this()并且super()不能在静态上下文中使用。

    class A {  
        int a = 40; //non static
        public static void main(String args[]) {  
            System.out.println(a);  
        }  
    }
    

输出:编译时错误

于 2015-05-13T13:36:36.073 回答
2

这里提出了一个关于为这个概念选择“静态”这个词的问题。这是对这个问题的欺骗,但我认为词源没有得到明确解决。所以...


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

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

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

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

Java 和类似的语言对数据有相同的概念。可以为每个类的实例(每个对象)分配数据,也可以为整个类分配一次。由于 Java 旨在为 C/C++ 程序员提供熟悉的语法,因此“静态”关键字在这里是合适的。

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

最后,我们来谈谈方法。

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

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

于 2020-03-21T14:18:02.413 回答
1

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

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

以下是静态变量 Getter 和 Setter 的示例:

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;
    }

}
于 2015-06-24T16:47:22.107 回答
0

Java 程序中的成员可以使用其声明/定义之前的关键字“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”时,它就是静态的。

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

  • 与使用类的实例调用的其他非静态方法相比,静态方法属于该类。
  • 要调用静态方法,您不需要类对象。
  • 静态方法可以访问类的静态数据成员。静态方法甚至可以更改静态数据成员的值。
  • 静态方法不能引用“this”或“super”成员。即使静态方法尝试引用它们,也会出现编译器错误。
  • 就像静态数据一样,静态方法也可以调用其他静态方法。静态方法不能引用非静态数据成员或变量,也不能调用非静态方法。

以下程序显示了 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中的静态块

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

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

以下程序显示了静态块的用法。

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 中,可以在另一个类中包含一个类,这称为嵌套类。包含嵌套类的类称为 Outer 类。

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

现在让我们探索 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

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

于 2021-10-09T14:43:01.220 回答