Java static与final使用陷阱

       static是静态修饰关键字,可以修饰变量和程序块以及类方法:

       当定义一个static的变量的时候jvm会将将其分配在内存堆上,所有程序对它的引用都会指向这一个地址而不会重新分配内存;

       当修饰一个程序块的时候(也就是直接将代码写在static{...}中)时候,虚拟机就会优先加载静态块中代码,这主要用于系统初始化;

       当修饰一个类方法时候你就可以直接通过类来调用而不需要新建对象。

            1、static修饰属性:无论一个类生成了多少个对象,所有这个对象共用唯一一份静态的成员变量;一个对象对该静态成员变量进行了修改,其他对象的该静态成员变量的值也会随之发生变化。如果一个成员变量是static的,那么我们可以通过类名.成员变量名的方式来使用它(推荐使用这种方式)。

             2、static修饰方法:static修饰的方法叫做静态方法。对于静态方法来说,可以使用类名.方法名的方式来访问。

public class StaticTest {
    public static void main(String[] args) {
        MyStatic.output();
    }
}
class MyStatic{
    public static void output(){
        System.out.println("output");
    }
}

             3、静态方法只能继承,不能重写(Override)。


输出结果:父类

             4、final关键字:final可以修饰属性、方法、类。

             5、final修饰类:当一个类被final所修饰时,表示该类是一个终态类,即不能被继承。


             6、final修饰方法:当一个方法被final所修饰的时,表示该方法是一个终态方法,即不能被重写(Override)。


             7、 final修饰属性:当一个属性被final所修饰时,表示该属性不能被改写。

             8、当final修饰一个原生数据类型时,表示该原生数据类型的值不能发生变化(比如说不能从10变为20);如果final修饰一个引用类型时,表示该引用类型不能再指向其他对象了,但该引用所指向的对象的内容是可以发生变化的。

            原生数据类型案例:

  

            图中的错误是无法为最终变量age分配值

            引用类型案例:


             图中错误是无法为最终变量address分配值

             该引用所指向的对象的内容是可以发生变化的


               9、对于final类型成员变量,一般来说有两种赋值方式:

                     a) 在声明final类型的成员变量时就赋初值

                     b) 在声明final类型的成员变量时不赋初值,但在类的所有构造方法中都为其赋上初值。

public class FinalTest {
    final int a;

    public FinalTest() {
        a = 0;
    }

    public FinalTest(int a) {
        this.a = a;
    }
}

               10、static静态代码块。静态代码块的作用也是完成一些初始化工作。首先执行静态块,然后执行构造方法。静态代码块在类被加载的时候执行,而构造方法是在生成对象的时候执行;要调用某个类来生成对象,首先需要将类加载到Java虚拟机上(JVM),然后由JVM加载这个类来生成对象。

                11、类的静态代码块只会执行一次,是在类被加载的时候执行的,因为每个类只会加载一个,所以静态代码块也只会被执行一次;而构造方法则不然,每次生成一个对象的时候都会调用类的构造方法,所以new一次就会调用构造方法一次。

                 12、如果继承体系既有构造方法,又有静态代码块,那么首先执行最顶层的类的静态代码块,一直执行到最底层类的静态代码块,然后再去执行最顶层类的构造方法,一直执行到最底层的构造方法,注意:静态代码块只会执行一次。

public class StaticTest5 {
    public static void main(String[] args) {
        new R();
        new R();
    }
}
class P{
    //static静态代码块
    static {
        System.out.println("static block");
    }
    public P(){
        System.out.println("P constructor");
    }
}
class Q extends P{
    static {
        System.out.println("static block");
    }
    public Q(){
        System.out.println("Q constructor");
    }
}
class R extends Q{
    static {
        System.out.println("static block");
    }
    public R(){
        System.out.println("R constructor");
    }
}

                输出结果:

static block
static block
static block
P constructor
Q constructor
R constructor
P constructor
Q constructor
R constructor

                 13、不能在静态方法中访问非静态的成员变量:可以在静态方法中访问静态的成员变量。可以在非静态方法中访问静态的成员变量。


                 14、总结:静态的只能访问静态的;非静态的访问一切。   

                 15、不能在静态方法中使用this关键字。

猜你喜欢

转载自blog.csdn.net/weixin_37404604/article/details/80424562