具体来说,我正在尝试这段代码:
package hello;
public class Hello {
Clock clock = new Clock();
public static void main(String args[]) {
clock.sayTime();
}
}
但它给出了错误
无法访问静态方法main中的非静态字段
所以我将clock
的声明更改为:
static Clock clock = new Clock();
它有效。在声明之前放置该关键字是什么意思?它究竟会对该对象可以做什么和/或限制什么?
答案 0 :(得分:602)
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或线程一个,但这不是重点。
答案 1 :(得分:129)
这意味着Hello中只有一个“clock”实例,而不是“Hello”类的每个单独实例中的一个实例,或者更多 - 这意味着将有一个共同的“时钟”引用“Hello”类的所有实例。
因此,如果您要在代码中的任何位置执行“new Hello”: A-在第一个场景中(在更改之前,不使用“静态”),每次调用“新Hello”时它会生成一个新时钟,但是 B-在第二个场景中(在更改之后,使用“static”),每个“new Hello”实例仍将共享并使用首次创建的初始和相同的“时钟”引用。
除非你需要在主要之外的某个地方使用“时钟”,否则这也会起作用:
package hello;
public class Hello
{
public static void main(String args[])
{
Clock clock=new Clock();
clock.sayTime();
}
}
答案 2 :(得分:96)
static
关键字表示某些内容(字段,方法或嵌套类)与类型相关,而不是与该类型的任何特定实例相关。例如,一个调用Math.sin(...)
而没有任何Math
类的实例,实际上你不能创建Math
类的实例。
有关详细信息,请参阅relevant bit of Oracle's Java Tutorial。
<强>旁注强>
遗憾的是, 允许您访问静态成员,就好像它们是实例成员一样,例如// Bad code!
Thread.currentThread().sleep(5000);
someOtherThread.sleep(5000);
这使看起来好像sleep
是一个实例方法,但它实际上是一个静态方法 - 总是使当前线程休眠。最好在调用代码中明确这一点:
// Clearer
Thread.sleep(5000);
答案 3 :(得分:40)
Java中的static
关键字表示变量或函数在该类的所有实例之间共享,因为它属于类型,而不是实际的对象本身。
因此,如果您有一个变量:private static int i = 0;
并在一个实例中递增它(i++
),则更改将反映在所有实例中。 <{1}}现在在所有情况下都是1。
可以在不实例化对象的情况下使用静态方法。
答案 4 :(得分:24)
静态成员的基本用法......
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";
答案 5 :(得分:20)
Java中的静态:
Static是非访问修饰符。 static关键字属于类而不是类的实例。 可用于将变量或方法附加到类。
静态关键字可用于:
方法
可变
嵌套在另一个类
中的类初始化块
CAN&C用于:
类(非嵌套)
构造
接口
方法本地内部类(差异然后是嵌套类)
内部类方法
实例变量
本地变量
示例:强>
想象一下以下示例,其中有一个名为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
由于实例变量在创建对象时获取内存,因此每个对象都将具有实例变量的副本,如果增加,则不会反映到其他对象。
现在,如果我们将实例变量计数更改为静态,那么程序将生成不同的输出:
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和static的变量有时称为常量。接口的所有字段都称为常量,因为默认情况下它们是final和static。
图片资源:Final Static
答案 6 :(得分:19)
静态意味着您不必创建类的实例来使用与该类关联的方法或变量。在您的示例中,您可以调用:
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类的每个实例都有不同的值/引用,因此您无法从类的静态部分访问它。
答案 7 :(得分:13)
此讨论到目前为止忽略了类加载器注意事项。严格地说,Java静态字段在给定类加载器的类的所有实例之间共享。
答案 8 :(得分:13)
答案 9 :(得分:7)
可以将字段分配给类或类的实例。默认情况下,字段是实例变量。通过使用static
,该字段成为一个类变量,因此只有一个clock
。如果您在一个地方进行更改,它随处可见。实例可变数据彼此独立地更改。
答案 10 :(得分:6)
关键字static
用于将字段或方法表示为属于类本身而不是实例。使用您的代码,如果对象Clock
是静态的,Hello
类的所有实例将共享此Clock
数据成员(字段)。如果您将其设为非静态,则Hello
的每个单独实例都可以包含唯一的Clock
字段。
问题是您向类Hello
添加了 main 方法,以便您可以运行代码。这里的问题是 main 方法是静态的,因此,它不能引用其中的非静态字段或方法。您可以通过两种方式解决此问题:
Hello
类的所有字段和方法都是静态的,以便可以在 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();
}
}
答案 11 :(得分:6)
在Java中,static
关键字可以简单地视为表示以下内容:
&#34;不考虑或与任何特定实例的关系&#34;
如果以这种方式考虑static
,就会更容易理解它在遇到它的各种环境中的使用:
static
字段是属于该类的字段,而不是属于任何特定实例的字段
static
方法是一种没有this
概念的方法;它是在类上定义的,并且不知道该类的任何特定实例,除非将引用传递给它
static
成员类是一个嵌套类,没有任何概念或知道其封闭类的实例(除非对封闭类实例的引用传递给它)
答案 12 :(得分:5)
我已经开始喜欢“helper”类中的静态方法(如果可能的话)。
调用类不需要创建辅助类的另一个成员(实例)变量。您只需调用辅助类的方法即可。辅助类也得到了改进,因为你不再需要构造函数,也不需要成员(实例)变量。
可能还有其他优点。
答案 13 :(得分:5)
静态方法不使用它们所定义的类的任何实例变量。可以在this page上找到对差异的非常好的解释
答案 14 :(得分:5)
Static使clock成员成为类成员而不是实例成员。如果没有static关键字,则需要创建Hello类的实例(具有时钟成员变量) - 例如。
Hello hello = new Hello();
hello.clock.sayTime();
答案 15 :(得分:3)
也可以认为静态成员没有“this”指针。它们在所有实例之间共享。
答案 16 :(得分: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");
}
}
答案 17 :(得分:2)
main()
是一种静态方法,它有两个基本限制:
this()
和super()
不能在静态环境中使用。
class A {
int a = 40; //non static
public static void main(String args[]) {
System.out.println(a);
}
}
输出:编译时间错误
答案 18 :(得分:2)
//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
}
}
答案 19 :(得分:1)
静态变量只能在静态方法中访问,所以当我们声明静态变量时,那些getter和setter方法将是静态方法
静态方法是我们可以使用类名
访问的类级别以下是静态变量Getters和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;
}
}
答案 20 :(得分:1)
here问了一个问题,即为此概念选择了“静态”一词。解决了这个问题,但是我认为词源没有明确解决。所以...
这是因为关键字重用,从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()实例。这与我们为数据讨论的情况平行,因此再次使用“静态”是一个明智的选择,尤其是如果您不想在语言中添加更多的保留关键字。
答案 21 :(得分:0)
当运行某个项目时,首先加载静态事物(变量,方法,块......)。
运行此项目时,首先加载主方法。因为它是static method
。然后它看起来是对象"a" object
。但是对象尚未定义。因为它非静电。然后就像这个错误。