什么是“静态”关键字在类中做什么?
具体来说,我试着这个代码:
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
域。
问题是,你添加了一个主要的方法到你的类,你可以运行代码。 这里的问题是主要的方法是静态的,因此它不能引用非静态的字段或方法。 你可以通过两种方式解决这个问题:
- 使
Hello
类的所有字段和方法都是静态的,以便它们可以在main方法内引用。 这真的不是一件好事(或者错误的理由使得一个字段和/或方法是静态的) - 在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是静态方法,静态方法有两个主要限制:
- 静态方法不能使用非静态数据成员或直接调用非静态方法。
-
这个和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还没有定义。 因为它是非静态的。 然后来这个错误。