深入理解Java中static关键字的用途与静态方法、变量的调用方式
[id_9249[id_1750477238]772]

在类里面,用 static 进行声明的成员变量属于静态成员变量,同时也被称作类变量。类变量的生命周期与类是一样的,在整个应用程序执行的整个过程中都是有效的。
这里要强调一下:
static关键字的用途
可以这样描述:能够在未创建对象的情形下进行调用,包括方法和变量。
显然,被 static 关键字修饰的变量不需要依赖对象来访问。只要类被加载了,就可以通过类名去访问该变量。
另外,还可以编写 static 代码块以优化程序性能。
static方法
静态方法也叫做静态方法。因为静态方法不依靠任何对象就能直接访问,所以对于静态方法而言,不存在 this。既然不依附于任何对象,那就谈不上 this 了。并且由于这个特性,在静态方法中不能访问类的非静态成员变量和非静态方法,因为非静态成员变量和非静态方法都必须依赖于具体的对象才能被调用。
而非静态成员方法能够访问静态成员方法和静态成员变量。
代码示例:
从上面代码里看出:
如果想要在不创建对象的情况下调用某个方法,那么就可以把这个方法设置为 static。main 方法是最常见的静态方法,这能让人清楚地明白为什么 main 方法是静态方法,因为在程序执行 main 方法时没有创建任何对象,只能通过类名来进行访问。
特别说明:静态方法属于类,而非实例对象。在 JVM 加载类的时候,它就已经存在于内存中了,并且不会被虚拟机的垃圾回收机制回收掉,这会导致内存负荷较大。然而,非静态方法在运行完毕后会被虚拟机的垃圾回收机制回收掉,从而减轻内存压力。
static变量
静态变量也叫做静态变量。静态变量与非静态变量存在区别,具体区别如下:
static成员变量初始化顺序按照定义的顺序来进行初始化
static块
构造方法的作用是对对象进行初始化。静态初始化块的作用是对类进行初始化操作。
在静态初始化块中不能直接访问非staic成员。
static块的作用
静态初始化块的作用就是:提升程序性能。
为什么说静态初始化块能提升程序性能,代码示例如下:
class Person{
private Date birthDate;
public Person(Date birthDate) {
this.birthDate = birthDate;
}
boolean isBornBoomer() {
Date startDate = Date.valueOf("1946");
Date endDate = Date.valueOf("1964");
return如果 birthDate 与 startDate 进行比较,birthDate 大于或等于 startDate 时,返回 true;否则,返回 false。0birthDate 与 endDate 进行比较;birthDate 与 endDate 作比较;比较 birthDate 和 endDate ;对 birthDate 和 endDate 进行比较< 0;
}
}
isBornBoomer 用于判断这个人是否在 1946 年到 1964 年之间出生。每次调用 isBornBoomer 时,会生成 startDate 和 birthDate 这两个对象,这导致了空间的浪费。如果进行如下修改,效率会更好:
class Person{
private Date birthDate;
private static Date startDate,endDate;
static{
startDate = Date.valueOf("1946");
endDate = Date.valueOf("1964");
}
public Person(Date birthDate) {
this.birthDate = birthDate;
}
boolean isBornBoomer() {
return birthDate.compareTo(startDate)>=0 && birthDate.compareTo(endDate) < 0;
}
}
很多时候,会把一些只需进行一次的初始化操作放在 static 代码块里进行。
静态初始化块能放在类的任何位置,并且类中可以存在多个这样的块。
类初次被加载时,会按照静态初始化块的顺序去执行每个块,并且仅执行一次。
static关键字的误区
static关键字会改变类中成员的访问权限吗?
有些初学的朋友会把 java 里的 static 和 C/C++中的 static 关键字的功能弄混。在这里只需记住:Java 中的 static 关键字和 C/C++中的 static 不一样,它不会对变量或者方法的作用域产生影响。在 Java 中,能够对访问权限产生影响的仅有 private、public、protected(包含包访问权限)这几个关键字。以下面的例子便可理解:
public class Person {
public String name = "李四";
private static String address = "中国";
}
说明static关键字不能改变变量和方法的访问权限
能通过this访问静态成员变量吗?
public class Main {
static int value = 33;
public static void main在 (String[] args) 的情况下会抛出异常。
new Main().printValue();
}
private void printValue(){
int value = 3;
System.out.println(this.value);
}
}
这段代码输出结果为:33
this 所代表的是什么呢?this 代表的是当前对象。如果通过 new Main()来调用 printValue,那么此时的当前对象就是通过 new Main()生成的对象。由于 static 变量是被对象所享有的,所以在 printValue 中,this.value 的值必然是 33。printValue 方法内部的 value 为局部变量,其根本无法与 this 产生关联,故而输出结果是 33。在此需牢记一点:静态成员变量虽独立于对象,但这并不意味着不可以通过对象来进行访问,所有的静态方法和静态变量都能够通过对象进行访问(只要访问权限足够)。
static能作用于局部变量么?
静态(static)是不可以用来修饰局部变量的。不要询问其原因,这是 Java 语法所规定的。
static常见笔试面试题
1、下面这段代码的输出结果是什么?
public class Test extends Base{
static{
System.out.println("test static");
}
public Test(){
System.out.println("test constructor");
}
public static void main(String[] args) {
new Test();
}
}
class Base{
static{
System.out.println("base static");
}
public Base(){
System.out.println("base constructor");
}
}
输出结果为:
base static
test static
base constructor
test constructor
分析下这段代码的执行过程:
2、这段代码的输出结果是什么?
public class Test {
Person person = new Person("Test");
static{
System.out.println("test static");
}
public Test() {
System.out.println("test constructor");
}
public static void main(String[] args) {
new MyClass();
}
}
class Person{
static{
System.out.println("person static");
}
public Person(String str) {
System.out.println("person "+str);
}
}
class MyClass extends Test {
Person person = new Person("MyClass");
static{
System.out.println("myclass static");
}
public MyClass() {
System.out.println("myclass constructor");
}
}
输出结果为:
test static
myclass static
person static
person Test
test constructor
person MyClass
myclass constructor
为什么输出结果是这样的?我们来分析下这段代码的执行过程:
3、这段代码的输出结果是什么?
public class Test {
static{
System.out.println("test static 1");
}
public static void main(String[] args) {
}
static{
System.out.println("test static 2");
}
}
输出结果为:
test static 1
test static 2
在 main 方法中没有任何语句,然而依然会输出,其原因之前已经讲过了。并且,static 块能够出现在类中的任何位置,只要不是在方法内部就行,要记住,在任何方法内部都不可以。而且,static 块的执行是按照其出现的顺序来进行的。