![On Java:中文版·基础卷](https://wfqqreader-1252317822.image.myqcloud.com/cover/337/53256337/b_53256337.jpg)
3.7.3 static关键字
创建一个类即描述了其对象的外观和行为。直到使用new关键字时,你才会真正创建一个对象,以及为该对象分配内存,并使得其方法可以被调用。
然而在两种情况下,这种方式会显得不合时宜。第一种情况是,有时候我们需要一小块共享空间来保存某个特定的字段,而并不关心创建多少个对象,甚至有没有创建对象。第二种情况是,你需要使用一个类的某个方法,而该方法和具体的对象无关;换句话说,你希望即便没有生成任何该类的对象,依然可以调用其方法。
static关键字(源自C++)为以上两个问题提供了解决方案。如果你使用了static关键字,则意味着使用static的字段或方法不依赖于任何对象。也就是说,即便你没有为一个类创建任何对象,依然可以调用该类的static方法或static字段。另外,由于非static的字段和方法必须基于指定的对象[6],因此对于非static的字段和方法来说,你必须创建一个对象才可以使用非static的字段或方法。
有些面向对象编程语言也会使用“类数据”(class data)和“类方法”(class method)来表示该数据或方法只服务于类,而非特定的对象。有时候,Java也会使用这两种称谓。
创建一个static字段或方法,只需要把static关键字放置于字段或方法定义的前面就可以了。以下是创建并初始化一个static字段的例子:
![](https://epubservercos.yuewen.com/F9F485/31727349203472506/epubprivate/OEBPS/Images/58501_72_02.jpg?sign=1739364452-dOP3iIonEGzZGhYdD76fM6V4mt6S0vyz-0-8c98b4d9a6ac7e11bdf48d3d2cc97e30)
即便你创建了两个StaticTest类的对象,StaticTest.i依然只会占用同一块内存空间。也就是说,字段i会被两个对象所共享。例如:
![](https://epubservercos.yuewen.com/F9F485/31727349203472506/epubprivate/OEBPS/Images/58501_73_01.jpg?sign=1739364452-Ig6tXoURRNY90AyMCA0YetrzfejT8zua-0-653b47dd451e057e753232cc55363139)
st1.i和st2.i的值都是47,这是因为两者使用的内存空间是相同的。
有两种方法可以调用static变量。其一是通过对象来调用,比如之前例子中的st2.i。此外,你也可以直接通过类名来调用(非static成员则不能这样使用):
![](https://epubservercos.yuewen.com/F9F485/31727349203472506/epubprivate/OEBPS/Images/58501_73_02.jpg?sign=1739364452-ptx5NhV1VUT6WlIYkAG4Pmg6PqNtrbb7-0-d0e93921b96499878cef8aafc0fc4a48)
这里出现的运算符的作用是将变量的值加1。结果就是,st1.i和st2.i的值都变成了48。
我们较为推荐通过类名调用static变量,因为这种方法突出了变量的static特质。[7]
类似的逻辑也适用于static方法。你既可以通过对象来调用static方法(和非static方法一样),也可以使用专用语法ClassName.method(),即类名加方法名。例如,你可以这样定义一个static方法:
![](https://epubservercos.yuewen.com/F9F485/31727349203472506/epubprivate/OEBPS/Images/58501_73_04.jpg?sign=1739364452-r7M3WSkn5jqROKLI3vkzFVscDyNbUM1z-0-a31df2e7dcb2f5e4a348f61da6f9113f)
increment()方法通过运算符将static整数i的值加1。你可以使用传统方式,即通过对象调用increment()方法:
![](https://epubservercos.yuewen.com/F9F485/31727349203472506/epubprivate/OEBPS/Images/58501_73_06.jpg?sign=1739364452-cD9v0FNgVfdTuQE9ppM9qinStRz0PSeM-0-3272729e7a60a48b2dcb3602e8a8a841)
不过,推荐的做法是直接通过类名来调用:
![](https://epubservercos.yuewen.com/F9F485/31727349203472506/epubprivate/OEBPS/Images/58501_73_07.jpg?sign=1739364452-JZH2TqSgRwMDpmTEHmvaCxxcpaAF2BgV-0-c97f9526d8f77852573148c9ddd338c0)
将static关键字应用于字段,毫无疑问会改变其数据生成的方式,即static字段是基于类创建的,非static字段则是基于对象创建的。而将static应用于方法时,即便你没有创建对象,也可以调用该方法。你之后会看到,作为运行应用程序的入口,我们在定义main()方法时,static关键字是必不可少的一部分。