参考答案
static关键字的四个主要作用:
1. 修饰代码块
类中用static关键字修饰的代码块称为静态代码,反之没有用static关键字修饰的代码块称为实例代码块。
实例代码块会随着对象的创建而执行,即每个对象都会有自己的实例代码块,表现出来就是实例代码块的运行结果会影响当前对象的内容,并随着对象的销毁而消失(内存回收);而静态代码块是当Java类加载到JVM内存中而执行的代码块,由于类的加载在JVM运行期间只会发生一次,所以,静态代码块也只会执行一次。
因为静态代码块的主要作用是用来进行一些复杂的初始化工作,所以,静态代码块跟随类存储在方法区的表现形式是静态代码块执行的结果存储在方法区,即初始化量存储在方法区并被线程共享。
2. 修饰成员变量
类中用static关键字修饰的成员变量称为静态成员变量,因为static不能修饰局部变量,因此,静态成员变量也称为静态变量。
静态变量跟代码块类似,在类加载到JVM内存中,JVM会把静态变量放入方法区并分配内存,也由线程共享。访问形式是:类名.静态成员名。
public class StaticTest { public static void main(String[] args) { System.out.println(D.i); System.out.println(new D().i); } } class D { static { i = 2; System.out.println("D : 静态代码块1"); } static int i; }
运行结果:
D : 静态代码块1 2 2
静态变量存储在类的信息中,且可以在线程间共享,那么它当然也属于该类的每个对象,因此可以通过对象访问静态变量,但编译器并不支持这么做,且会给出警告。
注意:
一个类的静态变量和该类的静态代码块的加载顺序。
类会优先加载静态变量,然后加载静态代码块。
但是,如果有多个静态变量和多个代码块时,会按照编写的顺序进行加载。
class D { static { i = 2; System.out.println("D : 静态代码块1"); } static { i = 6; System.out.println("D : 静态代码块2"); } static int i; }
试想下运行结果。
静态变量可以不用显式的初始化,JVM会默认给其相应的默认值。如基本数据类型的byte为0,short为0,char为\u0000,int为0,long为0L,float为0.0f,double为0.0d,boolean为false,引用类型统一为null。
静态变量是JVM内存中共享的,且可以改变,对它的访问会引起线程安全问题。所以,使用静态变量的同时要考虑多线程情况。如果能确保静态变量不可变,那么可以用final关键字一起使用避免线程安全问题;否则需要采用同步的方式避免线程安全问题,如与volatile关键字一起使用。
static关键不能修饰局部变量,包括实例方法和静态方法,不然就会与static关键字的初衷-共享相违背。
3. 修饰方法
用static关键字修饰的方法称为静态方法,否则称为实例方法。
通过类名、方法名调用,但是需要注意静态方法可以直接调用类的静态变量和其他静态方法,不能直接调用成员变量和实例方法,除非通过对象调用。
class D { static { i = 2; System.out.println("D : 静态代码块"); } static final int i; int j; static void method() { System.out.println(i); System.out.println(new D().j); method1(); new D().method2(); } static void method1() { System.out.println(i); } void method2() { System.out.println(i); } }
注意:既然类的实例方法需要对象调用才能访问,而静态方法直接通过类名就能访问,那么在不考虑部署服务器的情况下,一个类是如何开始执行的呢?
最大的可能就是通过“类名.静态方法”启动Java,而定义了那么多静态方法,JVM又是如何知道主入口呢?
是的,就是main方法被Java规范定义成Java类的主入口。
Java类的运行都由main方法开启:
public static void main(String[] args) { for (String arg : args) { // 参数由外部定义 System.out.println(arg); } }
注意:
- main并不是Java关键字,它只是一个规定的程序入口的方法名字;另外,main方法可以重载。
- static关键字虽然不能修饰普通类,但可用static关键字修饰内部类使其变成静态内部类。static关键字本身的含义就是共享,而Java类加载到JVM内存的方法区,也是线程共享的,所以没必要用static关键字修饰普通类。
4. 静态导入
在用import导入包或者类时,可以用static修饰包名或者类,表示静态导入。
静态导入与动态导入放在一起来比较以加深理解。
动态导入是当程序运行需要new一个不在此包中的类的对象时,才会根据全路径类名加载类;而静态导入则是随着类的加载而加载静态导入的类,它是提前导入的。
public class StaticTest { static void method1() { System.out.println("static method1"); } static void method2() { System.out.println("static method2"); } }
静态导入:
import static com.starry.staticImport.StaticTest.method1; public class Client { public static void main(String[] args) { method1(); // StaticTest.method2(); } }
注意method1()是静态导入,不需要通过类名访问;而method2()没有导入,则需要通过类名调用。
那么什么时候需要静态导入呢?
静态导入常用于静态方法以及含有静态方法的类,枚举类等的导入,可在编译阶段确定导入类的信息或者方法信息。
以上,是Java面试题【static关键字有什么用】的参考答案。
输出,是最好的学习方法。
立即行动,在评论区记录下你的问题、笔记或补充~
—end—