“static”关键字在类中做什么?

bvpmtnay  于 2021-07-11  发布在  Java
关注(0)|答案(21)|浏览(291)

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

package hello;

public class Hello {

    Clock clock = new Clock();

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

但它给出了错误
无法访问静态方法main中的非静态字段
所以我改变了 clock 对此:

static Clock clock = new Clock();

而且成功了。在声明前加上关键字是什么意思?它究竟会对该对象做什么和/或限制什么?

y1aodyip

y1aodyip1#

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] :根据运行时特征,它可以是每个类加载器、appdomain或线程一个,但这不是重点。

sz81bmfz

sz81bmfz2#

这意味着hello中只有一个“clock”示例,而不是每个单独的“hello”类示例都有一个,或者更多,这意味着在“hello”类的所有示例中都有一个共同共享的“clock”引用。
因此,如果您在代码中的任何位置执行“new hello”:a-在第一个场景中(在更改之前,不使用“static”),每次调用“new hello”时,它都会生成一个新的时钟,但是b-在第二个场景中(更改之后,使用“static”),每个“new hello”示例仍将共享和使用最初创建的初始和相同的“clock”引用。
除非你需要在main之外的某个地方使用“时钟”,否则这同样适用:

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

yhuiod9q3#

这个 static 关键字意味着某些内容(字段、方法或嵌套类)与类型相关,而不是与该类型的任何特定示例相关。例如,一个 Math.sin(...) 没有任何 Math 类,实际上您不能创建 Math 班级。
有关更多信息,请参阅oracle java教程的相关部分。
旁注
不幸的是,java允许您像访问示例成员一样访问静态成员。

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

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

// Clearer
Thread.sleep(5000);
d7v8vwbk

d7v8vwbk4#

这个 static java中的关键字表示变量或函数在该类的所有示例之间共享,因为它属于该类型,而不是实际对象本身。
如果你有一个变量: private static int i = 0; 然后你增加它( i++ )在一个示例中,更改将反映在所有示例中。 i 现在在所有情况下都是1。
静态方法可以在不示例化对象的情况下使用。

frebpwbc

frebpwbc5#

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

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";
jckbn6z7

jckbn6z76#

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

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类的每个示例都有不同的值/引用,因此您无法从类的静态部分访问它。

qoefvg9y

qoefvg9y7#

java中的静态:
static是非访问修饰符。static关键字属于类而不是类的示例。可用于将变量或方法附加到类。
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的变量有时称为常量。接口的所有字段都称为常量,因为默认情况下它们是最终的和静态的。

图片资源:最终静态

sshcrbum

sshcrbum8#

为了补充现有的答案,让我试着用一张图片:
所有储蓄账户都适用2%的利率。因此它是静态的。
平衡应该是个体的,所以它不是静态的。

jpfvwuh4

jpfvwuh49#

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

bnl4lu3b

bnl4lu3b10#

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

vyu0f0g1

vyu0f0g111#

关键字 static 用于表示字段或方法属于类本身而不是示例。如果对象 Clock 是静态的,所有 Hello 班级将分享这个 Clock 公共数据成员(字段)。如果使其非静态,则 Hello 可以有一个独特的 Clock 现场。
问题是您向类中添加了一个main方法 Hello 这样你就可以运行代码了。这里的问题是main方法是静态的,因此它不能引用其中的非静态字段或方法。您可以通过两种方式解决此问题:
使所有字段和方法 Hello 类static,以便可以在main方法中引用它们。这真的不是一件好事(或者是一个错误的理由不能使一个字段和/或一个方法成为静态的)
创建的示例 Hello 在main方法中初始化,并以最初的方式访问它的所有字段和方法。
对您来说,这意味着对代码进行以下更改:

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

mkshixfv12#

在java中 static 关键字可以简单地视为表示以下内容:
“不考虑或不涉及任何特定示例”
如果你想到 static 这样,在遇到它的各种上下文中就更容易理解它的用法:
static 字段是属于类而不是任何特定示例的字段
static 方法是一种没有概念的方法 this ; 它是在类上定义的,并且不知道该类的任何特定示例,除非向它传递引用
static 成员类是一个嵌套类,不知道其封闭类的示例的任何概念或知识(除非向其传递对封闭类示例的引用)

xhv8bpkk

xhv8bpkk13#

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

Hello hello = new Hello();
hello.clock.sayTime();
yyyllmsg

yyyllmsg14#

静态方法不使用它们所定义的类的任何示例变量。在这一页可以找到一个很好的解释

xxe27gdn

xxe27gdn15#

我喜欢“helper”类中的静态方法(只有在可能的情况下)。
调用类不需要创建helper类的另一个成员(示例)变量。只需调用helper类的方法。此外,helper类也得到了改进,因为您不再需要构造函数,也不需要成员(示例)变量。
可能还有其他优势。

相关问题