一、静态(static)属性
Java中的静态变量和普通变量的主要区别在于它们的生命周期、存储位置、初始化时机以及访问方式。
-
生命周期和存储位置:
静态变量属于类级别,在内存中只有一个副本,由类所有对象共享。它们在类加载时初始化,并且在程序运行期间一直存在,直到程序结束时才被销毁。静态变量存储在方法区,而普通变量(实例变量)是对象的一部分,每个对象都有自己的实例变量副本,存储在堆上。 -
初始化时机:
静态变量在类加载时完成初始化,而非静态变量(实例变量)是在创建对象时进行初始化。静态变量的初始化顺序按照定义的顺序进行,而非静态变量的初始化则跟随对象的创建。 -
访问方式:
静态变量可以通过类名直接访问,也可以通过对象访问。而普通变量(实例变量)只能通过对象来访问,不能通过类名直接访问。这是因为普通变量是对象的一部分,需要具体的对象实例才能访问其属性。 -
用途:
静态变量通常用于存储与类本身相关的信息,这些信息不随对象的创建而改变。例如,配置参数、常量等。普通变量则用于存储与特定对象状态相关的信息,每个对象都有自己的实例变量副本,保证了对象之间的独立性。
例如,以上代码中变量age是静态变量,score是普通变量(实例变量);最明显的区别就是我们可以通过类名或者对象直接访问age,但我们只能用对象名访问普通变量(实例变量);
二、静态(static)方法
Java中的静态方法和普通方法的主要区别在于它们的调用方式、访问权限、内存分配以及生命周期。
-
调用方式:
静态方法可以通过类名直接调用,而普通方法必须通过对象引用调用。这意味着,静态方法不需要创建对象即可使用,而普通方法必须依赖于类的实例(对象)来调用。 -
访问权限: 静态方法只能访问静态成员变量和其他静态方法,不能访问非静态成员变量和非静态方法。普通方法可以访问所有成员变量和方法,包括静态和非静态的。
- 内存分配: 静态方法和静态成员变量在类加载时被分配内存,而非静态方法和实例变量在每次创建对象时分配内存。这表明静态方法在程序开始时就已存在,而非静态方法则依赖于对象的创建。
-
生命周期:
静态方法的生命周期与类的生命周期相同,即只要类被加载到内存中,静态方法就存在。非静态方法的生命周期与类的实例化对象相同,只有当对象被创建时,非静态方法才会被创建,当对象被销毁时,非静态方法也随之销毁。
例如,上图代码中run()方法是普通方法、go()方法是静态方法;静态方法跟随类一起加载,所以可以被其他方法直接调用,但是非静态方法run()就不能被直接调用,必须使用实例化的对象调用;
三、静态(static)代码块
java中匿名代码块和静态代码块的区别
在Java中,匿名代码块和静态代码块的主要区别在于它们的执行时机和上下文不同。
-
静态代码块(static block): 用static修饰的代码块,主要用于初始化类,在加载类时执行一次,且在构造函数之前执行。
public class MyClass { static { // 静态代码块内容 System.out.println("静态代码块被执行"); } }
-
匿名代码块(instance initializer): 它是局部的,不能用access modifier(如public、private等)和static修饰,它位于类的定义体中,每次创建对象时都会被执行一次。
public class MyClass { { // 匿名代码块内容 System.out.println("匿名代码块被执行"); } }
区别概括:
-
静态代码块在类加载时执行一次,且在构造函数之前执行;
-
匿名代码块在每次创建对象时执行,且在构造函数体之前执行。
注意:静态代码块只能访问静态变量,不能直接访问实例变量;匿名代码块可以访问实例变量,也可以访问静态变量。
以上代码可以看出,静态代码块和匿名代码块的加载时机是不一样的。
四、静态(static)导入包
在java中,使用静态导入包可以直接使用包中的静态成员,而不需要使用完整的包名来访问这些成员。静态导入包可以通过在代码中使用import static
语句来实现。
例如,假设有一个名为MathUtils
的工具类,在该类中有一个静态方法add(int a, int b)
,我们可以通过静态导入包来直接使用这个方法,而不需要使用完整的包名。
import static com.example.MathUtils.add;
public class MyCalculator {
public static void main(String[] args) {
int result = add(3, 5);
System.out.println(result); // 输出 8
}
}
需要注意的是,静态导入包可能会导致代码的可读性降低,因此应该谨慎使用。