java学习补漏 02 Super、静态变量、访问修饰符

1.静态变量

静态变量是类中所有对象共享的,使用时会修改值。

使用方法:

类名.变量名

注意:静态方法能调用同类的静态成员,不能调用非静态成员和方法

静态初始块用法:

Static{

只能初始化静态变量

};

常考面试基础 代码块与代码加载顺序 static

简介

本文主要介绍了三种代码块的特性和使用方法。

代码块:用{}包围的代码

java中的代码块按其位置划分为四种:
局部代码块

位置:局部位置(方法内部)
作用:限定变量的生命周期,尽早释放,节约内存
调用:调用其所在的方法时执行

   

public class 局部代码块 {
    @Test
    public void test (){
        B b = new B();
        b.go();
    }
    }
    class B {
        B(){}
        public void go() {
            //方法中的局部代码块,一般进行一次性地调用,调用完立刻释放空间,避免在接下来的调用过程中占用栈空间
            //因为栈空间内存是有限的,方法调用可能会会生成很多局部变量导致栈内存不足。
            //使用局部代码块可以避免这样的情况发生。
            {
                int i = 1;
                ArrayList<Integer> list = new ArrayList<>();
                while (i < 10) {
                    list.add(i ++);
                }
                for (Integer j : list) {
                    System.out.println(j);
                }
                System.out.println("gogogo");
            }
            System.out.println("hello");
        }
    }

输出结果:


构造代码块

位置:类成员的位置,就是类中方法之外的位置
作用:把多个构造方法共同的部分提取出来,共用构造代码块
调用:每次调用构造方法时,都会优先于构造方法执行,也就是每次new一个对象时自动调用,对对象的初始化

对象一实例化就执行,每实例化一次执行一次;

   

 class A{
        int i = 1;
        int initValue;//成员变量的初始化交给代码块来完成
        {
            //代码块的作用体现于此:在调用构造方法之前,用某段代码对成员变量进行初始化。
            //而不是在构造方法调用时再进行。一般用于将构造方法的相同部分提取出来。
            //
            for (int i = 0;i < 100;i ++) {
                initValue += i;
            }
        }
        {
            System.out.println(initValue);
            System.out.println(i);//此时会打印1
            int i = 2;//代码块里的变量和成员变量不冲突,但会优先使用代码块的变量
            System.out.println(i);//此时打印2
            //System.out.println(j);//提示非法向后引用,因为此时j的的初始化还没开始。
            //
        }
        {
            System.out.println("代码块运行");
        }
        int j = 2;
        {
            System.out.println(j);
            System.out.println(i);//代码块中的变量运行后自动释放,不会影响代码块之外的代码
        }
        A(){
            System.out.println("构造方法运行");
        }
    }
    public class 构造代码块 {
        @Test
        public void test() {
            A a = new A();
        }
    }

 执行结果:


静态代码块

 位置:类成员位置,用static修饰的代码块

 作用:对类进行一些初始化  只加载一次,当new多个对象时,只有第一次会调用静态代码块,因为,静态代码块是属于类的,所有对象共享一份

 调用: new 一个对象时自动调用

   

public class 静态代码块 {
     
    @Test
    public void test() {
        C c1 = new C();
        C c2 = new C();
        //结果,静态代码块只会调用一次,类的所有对象共享该代码块
        //一般用于类的全局信息初始化
        //静态代码块调用
        //代码块调用
        //构造方法调用
        //代码块调用
        //构造方法调用
    }
     
    }
    class C{
        C(){
            System.out.println("构造方法调用");
        }
        {
            System.out.println("代码块调用");
        }
        static {
            System.out.println("静态代码块调用");
        }
    }

调用结果:

执行顺序 静态代码块 —–> 构造代码块 ——-> 构造方法
笔试题

实际面试题:

写出下列程序输出结果:

    public class HelloA {
        public HelloA(){
            System.out.println("HelloA");
        }
        {
            System.out.println("I'm A class");
        }
     
        static {
            System.out.println("static A");
        }
    }
     
    public class HelloB extends HelloA {
        public HelloB(){
            System.out.println("HelloB");
        }
        {
            System.out.println("I'm B class");
        }
     
        static {
            System.out.println("static B");
        }
     
        public static void main(String[] args) {
            new HelloB();
        }
    }

执行结果:

分析:首先要知道静态代码块是随着类的加载而加载,而构造代码块和构造方法都是随着对象的创建而加载

1,在编译HelloB.java时,由于HelloB 继承 HelloA,先加载了HelloA类,因此HelloA类的静态代码块首先执行,而后加载HelloB类,HelloB类的静态代码块执行,这没什么好说的

2,然后创建HelloB的对象,大家都知道构造代码块优先于构造方法执行,这时候问题来了,这时应该先看HelloB类的构造方法,HelloB类里的构造方法里有一句隐式的super()首先被执行,所以找到HelloA类的构造方法,而HelloA类的构造方法中也有一句隐式的super()执行(调用Object类的构造方法),并没有什么返回结果,接下来才是在执行HelloA类构造方法的方法体前先执行了HelloA类的构造代码块(I'm A class),再执行HelloA类构造方法的方法体(也就是Hello A),最后又回到HelloB类的构造方法中,这时HelloB类的super()已经执行完了,在执行HelloB类构造方法的方法体前先执行HelloB类的构造代码块(I'm B class),再执行Zi类构造方法的方法体(HellB).

无继承初始化顺序:

有继承初始化顺序:

 接下来看一道阿里笔试题:

  

  public class B
    {
        public static B t1 = new B();
        public static B t2 = new B();
        {
            System.out.println("构造块");
     
        }
        static
        {
            System.out.println("静态块");
     
        }
     
        public static void main(String[] args)
        {
     
            B t =new B();
     
        }
    }

执行结果是:

为什么不是:

静态块

构造块

构造块

构造块

原因是:

静态块:用静态申明,JVM加载类时执行,仅执行一次

构造块:类中直接用{}定义,每一次创建对象时执行

执行顺序优先级:静态块>主()>构造块>构造方法

因为静态声明缘故T1,T2也上升到静态位,与静态块处于同一优先级,同一优先级就先取按顺序来构造对象,构造对象,静态块
————————————————
版权声明:本文为CSDN博主「harryptter」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/harryptter/article/details/87875399

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值