代码块和final关键字

代码块

package com.chenxiii.codeblock;

public class CodeBlockDemo01 {
    public static void main(String[] args) {
        Person person1 = new Person();
        Person person2 = new Person();
    }
}

class Person {
    {
        System.out.println("非静态代码块被调用");
    }
    public int height = getHeight();

    public static int age = getAge();

    static {
        System.out.println("静态代码块被调用");
    }


    public int getHeight() {
        System.out.println("非静态属性初始化");
        return 180;
    }

    public static int getAge() {
        System.out.println("静态属性初始化");
        return 18;
    }

}
  1. 静态代码块会在类被加载的时候调用 且只会被调用一次
  2. 非静态代码块会在对象被创建的时候调用 且创建一次对象会被调用一次

在创建一个类的时候 执行顺序

  1. 静态代码块和静态属性初始 如果同时存在静态代码块和静态属性初始化 则按顺序执行
  2. 非静态代码块和非静态属性初始化 如果同时存在非静态代码块和非静态属性初始化 则按顺序执行

image-20210913164647657

package com.chenxiii.codeblock;

public class CodeBlockDemo02 {
    public static void main(String[] args) {
        new B();
    }
}

class A {
    public int n1 = getN1();
    public static int n2 = getN2();

    static {
        System.out.println("A的静态代码块执行");
    }

    {
        System.out.println("A的非静态代码块执行");
    }


    public int getN1() {
        System.out.println("A的非静态属性初始化");
        return 100;
    }
    public static int getN2() {
        System.out.println("A的静态属性初始化");
        return 200;
    }

    public A() {
        // 隐藏语句
        // super();
        // 非静态代码块调用和非静态属性初始化
        System.out.println("A的构造器");
    }
}

class B extends A{
    public int n3 = getN3();
    public static int n4 = getN4();

    static {
        System.out.println("B的静态代码块执行");
    }

    {
        System.out.println("B的非静态代码块执行");
    }

    public int getN3() {
        System.out.println("B的非静态属性初始化");
        return 300;
    }
    public static int getN4() {
        System.out.println("B的静态属性初始化");
        return 400;
    }

    public B() {
        // 隐藏语句
        // super();
        // 非静态代码块调用和非静态属性初始化
        System.out.println("B的构造器");
    }
}

创建对象时,代码块和构造器的执行顺序

  1. 父类的静态代码块和静态属性初始化
  2. 子类的静态代码块和静态属性初始化
  3. 父类的普通代码块和普通属性初始化
  4. 父类的构造器
  5. 子类的普通代码块和普通属性初始化
  6. 子类的构造器

image-20210913164817088

单例模式

所谓的单例设计模式 就是采取一定的方法保证在整个软件系统中 对某个类只能存在一个对象实例 并且该类只提供一个取得其对象实例的方法

饿汉式

对象随着类的加载而初始化 有可能会创建了但却没有用到 造成资源浪费

  1. 构造器私有化
  2. 类的内部创建对象并初始化
  3. 向外暴露一个静态的公共方法
package com.chenxiii.single_;

public class SingleDemo01 {
    public static void main(String[] args) {
        GirlFriend instance = GirlFriend.getInstance();
        GirlFriend instance1 = GirlFriend.getInstance();
        System.out.println(instance == instance1); //true
    }
}

class GirlFriend {
    private String name;

    // 2.内部创建一个对象 为了能够在静态方法中返回gf对象 所以要用static修饰
    private static GirlFriend gf = new GirlFriend("小红");
    // 使用public则可以在main中创建多个对象
    // 1. 修改为private则其他类中无法创建GirlFriend对象 私有化构造器
    private GirlFriend(String name) {
        this.name = name;
    }
    // 3.提供一个公共的static方法 返回gf对象
    public static GirlFriend getInstance() {
        return gf;
    }
}

懒汉式

只有当用户调用 getInstance()时 才会返回Cat对象 后面调用时 会返回上次创建的Cat对象

  1. 构造器私有化
  2. 类的内部创建对象但不初始化
  3. 向外暴露一个静态的公共方法
package com.chenxiii.single_;

public class SingleDemo02 {
    public static void main(String[] args) {
        Cat instance = Cat.getInstance();
        Cat instance1 = Cat.getInstance();
        System.out.println(instance == instance1); //true
    }
}


class Cat {
    private String name;
    // 2.定义一个static静态属性对象
    private static Cat cat;

    // 1.构造器私有化
    private Cat(String name) {
        this.name = name;
    }

    // 3.提供一个public的static方法 可以返回一个Cat对象
    public static Cat getInstance() {
        if (cat == null) cat = new Cat("阿花");
        return cat;
    }
}

不同:

  1. 创建对象的时机不同 饿汉式是在类加载的时候创建了对象 懒汉式是在使用时创建
  2. 饿汉式不存在线程安全问题 懒汉式存在线程安全问题
  3. 饿汉式存在浪费资源部的可能

final

使用场景:

  1. 不希望类被继承时
  2. 不希望父类的某个方法被子类重写
  3. 当不希望类的某个属性被修改
  4. 当不希望某个局部变量被修改

final定义非静态变量时:

  1. public final double A = 0; 定义时直接赋值
  2. 在构造器中赋值
  3. 在代码块中赋值
class Cat {
    public final int AGE = 18;
    public final double WEIGHT;
    public final double HEIGHT;
    public Cat() {
        WEIGHT = 100;
    }
    {
        HEIGHT = 50;
    }
}

final修饰静态属性:

  1. 定义时
  2. 在静态代码块中赋值 不能再构造器中赋值
class Dog {
    public static final int AGE = 18;
    public static final double WEIGHT;
    static {
        WEIGHT = 100;
    }
}

final类不能继承 但是可以实例化对象

如果类不是final类 但是含有final方法 则该方法虽然不能被重写 但是可以被继承

final 和 static 搭配使用 不会导致类加载 底层编译器做了优化处理

class Dog {
    public static final int AGE = 18;
    public static final double WEIGHT;
    static {
        WEIGHT = 100;
        System.out.println("调用静态代码块");
    }
}
public static void main(String[] args) {
    System.out.println(Dog.AGE);
}

image-20210913192947321

ic static final int AGE = 18;
public static final double WEIGHT;
static {
WEIGHT = 100;
System.out.println(“调用静态代码块”);
}
}
public static void main(String[] args) {
System.out.println(Dog.AGE);
}


[外链图片转存中...(img-tMXr0bfJ-1631615447007)]

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值