Java中的静态与非静态
在Java中,static
是一个关键字(用于内存管理),用于修饰类的成员,包括变量、方法和代码块。下面是关于 static
的一些重要用法和特性:
-
静态变量:使用
static
关键字来声明静态变量,它们属于类,而不属于类的实例。静态变量在类加载时初始化,并在整个应用程序运行期间保持不变。可以通过类名直接访问静态变量,无需创建类的实例。它的优点是:能使程序存储器高效(既节省内存)。 -
静态方法:使用
static
关键字来声明静态方法,它们也属于类,而不属于类的实例。静态方法可以直接通过类名调用,无需创建类的实例。静态方法只能访问静态变量和调用其他静态方法,不能使用this和super关键字。 -
静态代码块:使用
static
关键字来声明静态代码块,它们在类加载时执行,并且只执行一次。静态代码块用于初始化静态变量或执行其他静态操作。 -
静态内部类:使用
static
关键字来声明静态内部类,静态内部类可以在没有外部类实例的情况下被实例化。静态内部类可以访问外部类的静态变量和方法,而不需要访问外部类的实例。
示例:(静态变量)
package jing;
public class Tuxing {
double toplength;// 实例变量
static double downlength; //静态变量
void settoplength(double a){ //设置上底
toplength = a;
}
void setdowmlength(double b){ //设置下底
downlength = b;
}
double gettoplength(){ //获取上底
return toplength;
}
double getdownlength(){ //获取下底
return downlength;
}
}
``
package jing;
public class Demo1 {
public static void main(String[] args) {
Tuxing.downlength = 100; //通过类名直接操作静态变量
Tuxing tuxingOne = new Tuxing();
Tuxing tuxingTwo = new Tuxing();
tuxingOne.settoplength(28);
tuxingTwo.settoplength(67);
System.out.println("tuxingOne的上底:"+tuxingOne.gettoplength());
System.out.println("tuxingOne的下底:"+tuxingOne.getdownlength());
System.out.println("tuxingTwo的上底:"+tuxingTwo.gettoplength());
System.out.println("tuxingTwo的下底:"+tuxingTwo.getdownlength());
}
}
运行结果:
可以看到Tuxing类创建的梯形对象是共享一个下底(downlength)的
原因是当示例代码执行
Tuxing.downlength = 100;
时,Java虚拟机首先将Tuxing的字节码加载到内存,同时为静态变量“下底”分配了内存空间,并赋值100后面执行到
Tuxing tuxingOne = new Tuxing();
Tuxing tuxingTwo = new Tuxing();
时,实例变量“上底(toplength)”和“高(height)”都被两次分配内存空间,分别被对象TuxingOne和TuxingTwo所引用,而变量“下底(downlength)”不再分配内存,直接被对象TuxingOne和TuxingTwo引用、共享(如图所示)
一些使用 static
的常见场景包括:
- 全局共享数据:使用静态变量来存储全局共享的数据,可以被所有类的实例访问和修改。 - 工具类:使用静态方法来提供通用的工具方法,可以直接通过类名调用,无需创建实例。 - 常量:使用 static final
来声明静态常量,它们的值在初始化后不能修改。 - 单例模式:使用静态方法提供一个访问单例实例的接口。
需要注意的是,静态成员在内存中只有一份副本,可能会导致并发访问的问题,因此在多线程环境下要谨慎使用。此外,过度使用静态成员可能会导致代码的可测试性和可维护性降低,因此要根据具体情况合理使用 static
关键字。