什么是“静态”关键字在类中做什么?

具体来说,我试着这个代码:

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

但它给了错误

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

所以我改变了这个clock的声明:

 static Clock clock = new Clock(); 

它的工作。 在声明之前放置关键字是什么意思? 这个对象会做什么和/或限制什么?

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

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

由于static方法也不属于特定的实例,所以它们不能引用实例成员(你怎么知道你想引用哪个实例Hello类?)。 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或线程的一个,但这并不重要。

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

所以如果你要在你的代码中的任何地方做一个“新的Hello”:A-在第一个场景(在改变之前,不使用“static”),每次调用“new Hello”时都会产生一个新的时钟,但是B-在第二种情况下(更改之后,使用“静态”),每个“新的Hello”实例仍将共享并使用首次创build的初始和相同的“时钟”引用。

除非你需要在主要以外的某个地方使用“时钟”,否则这也是一样的:

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

static关键字意味着某些东西(一个字段,方法或嵌套类)与types相关,而不是types的任何特定实例 。 因此,例如,在没有任何Math类实例的情况下调用Math.sin(...) ,实际上不能创buildMath类的实例。

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


边注

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

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

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

 // Clearer Thread.sleep(5000); 

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

所以如果你有一个variables: private static int i = 0; 并且在一个实例中增加它( i++ ),所有变化都会反映在所有实例中。 i现在在所有情况下都是1。

静态方法可以在不实例化对象的情况下使用。

这意味着你不需要有一个类的实例来使用该方法。 所以在你的例子中,你可以调用:

 Hello.main(new String[]()) 

直接,而不是:

 Hello h = new Hello(); h.main(new String[]()); 

编辑

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

静态成员的基本用法…

 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。 而惠特静态你不需要创build类实例。

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

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

 Hello.staticValue = "abc"; 

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

Java中的静态:

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

静态关键字可用于:

方法

variables

嵌套在另一个类中的类

初始化块

不能用于:

类(不嵌套)

构造函数

接口

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

内部类的方法

实例variables

局部variables

例:

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

 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

由于实例variables在创build对象时会获取内存,因此每个对象都将具有实例variables的副本,如果增加,则不会反映到其他对象。

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

 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

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

静态与最终:

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

在这里输入图像描述

图片资源: 最终静态

可以将字段分配给类或类的实例。 默认情况下字段是实例variables。 通过使用static字段变成一个类variables,因此只有一个clock 。 如果你在一个地方做出改变,那么它在任何地方都是可见的。 实例可变参数相互独立地更改。

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

“不考虑或与任何特定事件的关系”

如果以这种方式来思考static的话,就会更容易理解它在遇到的各种情况下的使用:

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

  • static方法是一个没有this概念的方法; 它是在类上定义的,除非传递引用,否则不知道该类的任何特定实例

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

静态方法不使用它们定义的类的任何实例variables。在这个页面上可以find一个很好的解释

我开发了一个喜欢静态方法(只在可能的情况下)在“助手”类。

调用类不需要创buildhelper类的另一个成员(实例)variables。 你只需要调用helper类的方法。 此外,助手类得到了改进,因为您不再需要构造函数,并且不需要成员(实例)variables。

可能还有其他的好处。

关键字static用来表示一个字段或方法属于类本身而不是实例。 使用你的代码,如果对象Clock是静态的,那么Hello类的所有实例将共享这个Clock数据成员(field)。 如果你使它是非静态的,每个Hello实例可以有一个唯一的Clock域。

问题是,你添加了一个主要的方法到你的类,你可以运行代码。 这里的问题是主要的方法是静态的,因此它不能引用非静态的字段或方法。 你可以通过两种方式解决这个问题:

  1. 使Hello类的所有字段和方法都是静态的,以便它们可以在main方法内引用。 这真的不是一件好事(或者错误的理由使得一个字段和/或方法是静态的)
  2. 在main方法中创build一个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(); } } 

静态使时钟成员成为类成员,而不是实例成员。 没有static关键字,你需要创build一个Hello类的实例(它有一个时钟成员variables) – 例如

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

也可以认为没有“this”指针的静态成员。 它们在所有实例中共享。

这里Main是静态方法,静态方法有两个主要限制:

  1. 静态方法不能使用非静态数据成员或直接调用非静态方法。
  2. 这个和super不能用在静态的上下文中。

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

输出:编译时间错误

为了增加现有的答案,让我试试一下:

在这里输入图像描述

了解静态概念

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

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

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

以下是静态variablesGetters和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; } } 

当运行某个项目时首先加载静态的东西(variables,方法,块)。

运行这个项目的主要方法首先加载。 因为它的static method 。 然后它看起来是对象"a" object 。但是对象a还没有定义。 因为它是非静态的。 然后来这个错误。