字节面试题之-static&final
在Java编程中,static
和final
是两个非常重要的关键字,它们可以帮助我们更好地组织代码和管理数据。下面整理了这两个关键字的原理、常见用法、区别。
目录嘻嘻
static
关键字
static
关键字用于表示一个静态属性或方法,它们的值在类加载时被初始化,并且在整个程序运行期间都是可见的。静态变量是属于类的,不属于任何实例,而静态方法是属于类的,可以通过类名直接调用,不需要创建实例对象。
static
关键字的常见用法
- 单例模式
单例模式是一种常见的设计模式,它保证一个类只有一个实例,并提供一个全局访问点。这通常通过将类的构造函数设为私有,并提供一个静态方法来创建实例来实现。
public class Singleton {
private static Singleton instance;
private Singleton() {}
public static Singleton getInstance() {
if (instance == null) {
instance = new Singleton();
}
return instance;
}
}//简单版本 并没有用doubleCheck
在这个例子中,将instance
属性设为静态属性,它在类加载时被初始化,所以无论创建多少个实例对象,它们都会共享同一个instance
对象。
- 工具类
工具类通常包含一组静态方法,用于提供一些常用的工具函数,比如字符串处理、日期处理等。
public class StringUtil {
public static boolean isEmpty(String str) {
return str == null || str.trim().isEmpty();
}
public static boolean isNotEmpty(String str) {
return !isEmpty(str);
}
}
在这个例子中,定义了一个工具类StringUtil
,其中包含了两个静态方法isEmpty
和isNotEmpty
,它们可以通过类名直接调用。
static
关键字的原理
static
关键字可以修饰类的属性和方法,它的主要作用是将属性和方法与类的实例分离。在Java虚拟机中,每个对象都有一个对象头(Object Header),其中包含了对象的运行时类型信息、锁状态等信息,而静态属性和方法不属于对象本身,它们被存储在类的静态区域(Class Area)中,所有实例共享该区域的数据。当一个类被加载时,Java虚拟机会为它分配一块内存空间,用来存储该类的静态变量和方法。在这个过程中,对于静态变量,Java虚拟机会为它们分配一块内存空间,这些变量的值在类加载时被初始化,并且在整个程序运行期间都是可见的。
final
关键字
final
关键字用于表示一个常量,它们的值在声明时被初始化,并且在整个程序运行期间不可修改。常量可以是基本数据类型,也可以是引用类型,但是一旦被赋值,就不能再改变其引用指向的对象。
final
关键字的常见用法
- 常量
常量通常用于表示程序中不会改变的值,比如圆周率、常数等。
public class MathUtil {
public static final double PI = 3.14159265358979323846;
}
在这个例子中,定义了一个常量PI
,它被声明为静态和不可变的,所以可以通过类名直接访问。
- 方法锁定
当需要确保一个方法不能被子类重写时,可以将该方法声明为final
。
public class BaseClass {
public final void do() {
// ...
}
}
public class SubClass extends BaseClass {
// 编译错误,不能重写 final 方法
// public void do() { ... }
}
在这个例子中,将do
方法声明为final
,这意味着它不能被子类重写。
final
关键字的原理
在Java虚拟机中,常量通常被放在常量池(Constant Pool)中。常量池是一块预先分配的内存区域,用于存储常量和符号引用。当程序需要访问一个常量时,它会从常量池中取出该常量的值。对于基本数据类型的常量,它们的值就是直接存储在常量池中的,对于引用类型的常量,它们的引用地址也是存储在常量池中的。
在Java中,我们可以使用final
关键字来声明一个常量。当我们声明一个final
变量时,它的值必须在声明时被初始化,并且在整个程序运行期间都不能被修改。这是因为,Java编译器会将所有的final
变量直接替换为其值,这样可以避免在运行期间对其进行运算或赋值操作。
static
和final
的区别
尽管static
和final
都可以用来表示常量,但它们在实现方式和作用域上还是有很大的区别的。
实现方式
static
关键字:在类加载时被初始化,并且在整个程序运行期间都是可见的。final
关键字:在声明时被初始化,并且在整个程序运行期间都不能被修改。
作用域
static
关键字:属于类的,不属于任何实例。final
关键字:属于实例的,每个实例都有自己的值。
其他注意事项
static
方法不能访问非静态成员,而``final方法可以访问非
final`成员。static
变量可以被继承,且所有的子类共享同一份变量。final
变量不能被继承,每个子类都需要重新定义自己的常量。static
变量可以在类加载时被初始化,也可以在静态代码块中被初始化。final
变量只能在声明时或构造函数中被初始化,且只能被赋值一次。
other
static
关键字的其他用法
static
代码块:在类加载时被执行,用于初始化静态变量或执行一些静态方法。static
内部类:用于表示嵌套在另一个类中的静态类。static
导入:用于导入类中的静态方法或静态成员。
final
关键字的其他用法
final
类:用于表示不能被继承的类。final
参数:用于表示在方法内部不能被修改的参数。final
局部变量:用于表示在方法内部不能被修改的局部变量。
总结
static
关键字和final
关键字都可以用来表示常量,但它们的实现方式和作用域有很大的不同。static
关键字属于类,被所有的实例共享,而final
关键字属于实例,每个实例都有自己的常量值。在使用这两个关键字时,我们需要根据实际情况来选择适合的关键字。