Java static 关键字

一、static关键字的用途

static可以用来修饰类的成员方法、类的成员变量,也可以编写static代码块来优化程序性能。

注意:

1、被static关键字修饰的方法或者变量不需要依赖于对象来进行访问,只要类被加载了,就可以通过类名去进行访问

2、禁止在静态成员方法中访问非静态成员方法,但非静态成员方法访问静态成员/方法是无限制的

3、构造器是否是static方法?
从Java语言规范中给出的“静态方法”的定义来看,Java中的实例构造器不可以是“静态方法”。Java语言中,实例构造器只能在new表达式或别的构造器中被调用,不能通过方法调用表达式来调用。new表达式作为一个整体保证了对象的创建与初始化是打包在一起的,不能分开进行。实例构造器只负责对象初始化部分,创建对象的部分是由new表达式本身保证的。
实例构造器无法被隐藏或覆写,不参与多态,因而可以做静态绑定。从这个意义上可以认为实例构造器是“静态”的,但这种用法与Java语言定义的“静态方法”是两码事。

4、静态代码块可以置于类中的任何地方,类中可以有多个static块。在类初次被加载的时候,会按照static块的顺序来执行每个static块,并且只会执行一次。很多时候会将一些只需要进行一次的初始化操作都放在static代码块中进行,例如静态成员变量的初始化。

二、static关键字的误区

1、static关键字不会改变类中成员的访问权限

2、可以通过this访问静态成员,静态成员虽然独立于对象,但是所有的静态成员都可以通过对象进行访问
(只要访问权限足够)

3、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

分析:
在执行开始,先要找到main()方法,因为main()方法是程序的入口,但是在执行main()方法之前,必须先加载Test类,而在加载Test类的时候发现Test类继承自Base类,因此会转去先加载Base类,在加载Base类的时候,发现有static块,便执行了static块(Base类)。加载完Base类后继续加载Test类,发现static块,执行static块(Test类)。

在加载完所需的类后,便开始执行main()方法。在main()方法中执行new Test()的时候会先调用父类的构造器,然后再调用自身的构造器。

因此,便出现了上面的输出结果。

(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

分析:
在执行开始,先要找到main()方法,因为main()方法是程序的入口,但是在执行main()方法之前,必须先加载Test类,在加载Test类的时候,发现static块,执行static块(Test类)。

加载完Test类后,执行new MyClass(),而MyClass类还没有被加载,因此需要加载MyClass类。加载MyClass类时,发现MyClass类继承自Test类,但Test类已经被加载了,所以只需要加载MyClass类,发现有static块,执行static块(MyClass类)。在加载完MyClass类之后,通过构造器来生成对象。

在初始化对象的时候,必须先初始化父类的成员变量,然后初始化父类实例。因此会执行Test类中的Person person = new Person(”Test"); 然而Person类还没有被加载过,因此会先加载Person类并执行Person类中的static块,继续执行new Person("Test"),完成父类的成员变量的初始化,接着执行Test类的构造器,完成Test类对象的实例化。

父类实例化完成后,初始化自身的成员变量,因此会接着执行MyClass中的 Person person = new Person("MyClass"); 然后再执行MyClass的构造函数,至此,运行结束。

(3)、示例三

public class testConstructor3 {
    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块,并且只会执行一次。

posted @ 2022-03-27 11:53  紫薇哥哥  阅读(54)  评论(0编辑  收藏  举报