【Java基础】10章、单例模式、final关键字的使用技巧和使用细节、单例模式-懒汉式、单例模式-饿汉式【3】

跟着一位很厉害的老师学完了java基础,现开始进行javaSE复盘总结知识点,希望可以给java基础薄弱的友友提供一点参考,一起学习Java初级知识,共同进步,打好底层逻辑基础,爱上Java编程❤️❤️❤️

(本文章中知识点如有不同的见解,欢迎评论区留言)


文章目录

1、单例模式

11、基本介绍

1.1.1、什么是设计模式

  • 什么是单例模式

单例(单个的实例)

  1. 所谓类的单例设计模式,就是采取一定的方法保证在整个软件系统中,对某个类只能存在一个对象实例,并且该类只提供一个取得对象实例的方法。
  2. 单例模式有两种方式:(1)饿汉式 (2)懒汉式

1.1.2、应用实例

1.1.2.1、单例模式-饿汉式
java 复制代码
package com.fhsedu.single_;

//有一个类,GirFriend
//只能有一个女朋友
class GirlFriend {
    private String name;
    //为了能够在静态方法中,返回gf对象,需要将其修饰为static
    private static GirlFriend  gf = new GirlFriend("小红红");

    //如何保障我们只能创建一个GirlFriend对象
    //步骤【单例模式-饿汉式】
    //1、将构造器私有化
    //2、在类的内部直接创建
    //3、提供一个公共static方法,返回gf对象
    private GirlFriend(String name) {
        this.name = name;
    }

    public static GirlFriend getInstance() {
        return gf;
    }

    @Override
    public String toString() {
        return "GirlFriend{" +
        "name='" + name + '\'' +
        '}';
    }
}

public class SingleTon01 {
    public static void main(String[] args) {
        //通过方法可以获取对象
        GirlFriend instance1 = GirlFriend.getInstance();
        System.out.println(instance1);
        GirlFriend instance2 = GirlFriend.getInstance();
        System.out.println(instance2);
        System.out.println(instance1.hashCode() + "  " + instance2.hashCode());//相同
    }
}
  • 饿汉式解决有可能造成创建了对象,但是没有使用,带来的弊端
1.1.2.2、单例模式-懒汉式

不管是懒汉式还是饿汉式都是在类中都是创建一个具体的实例

代码演示

java 复制代码
package com.fhsedu.single_;
//演示懒汉模式的单例

//希望在程序运行过程中,只能创建一个Cat对象
class Cat {
    private String name;
    public static int n1 = 999;
    private static Cat cat;
    //步骤
    //1、仍然让构造器私有化
    //2、定义一个static静态属性对象
    //3、提供一个public的static方法,可以返回一个Cat对象
    //4、懒汉式,只有当用户使用getInstance时,才返回cat对象,后面再次调用时会返回上次创建的cat对象
    //      从而保证了单例
    private  Cat (String name) {
    	this.name = name;
    }
    public static Cat getInstance() {
        System.out.println("构造器被调用...");
        if (cat == null){//如果没有创建cat对象
            cat = new Cat("小可爱");
            n1++;
        }
        return cat;
    }

    @Override
    public String toString() {
        return "Cat{" +
        "name='" + name + '\'' +
        '}';
    }
}

public class SingleTon02 {
    public static void main(String[] args) {
        //此时初始化为 999
        System.out.println(Cat.n1);

        //Cat为null 执行 new Cat  和  n++
        Cat cat1 = Cat.getInstance();
        //此时  n == 1000
        System.out.println(cat1);//默认是null
        System.out.println(cat1 + "" + cat1.hashCode());

        //再次调用getInstance,此时还是之前的那只猫吗?
        //初始化第2只猫,但是指向的还是之前的那只
        Cat cat2 = Cat.getInstance();
        //n1 == 1000
        System.out.println(Cat.n1);
        System.out.println(cat2 + "" + cat2.hashCode());

        Cat cat3 = Cat.getInstance();
        System.out.println(cat3 + "" + cat3.hashCode());
        //n1 == 1000
        System.out.println(Cat.n1);
    }
}

饿汉式细节:

此时没有创建对象


(Runtime中的单例模式-饿汉式)

1.1.2.3、区别

饿汉式存在问题:在类加载时候就创建,可能存在资源浪费问题

懒汉式存在问题:线程安全问题


4.1.2.4、小结
  1. 单例模式的两种首先方式1)饿汉式 2)懒汉式
  2. 饿汉/懒汉式创建的过程
  3. 要求,可以自己独立写出单例模式

2、final关键字

演示:假如我们认为这个类很重要不希望被继承和重写

代码演示:

  • 拒接继承本类
  • 拒接重写父类方法
  • 拒绝修改本类中的属性
java 复制代码
package com.fhsedu.final_;

public class Final01 {
    public static void main(String[] args) {

        E e = new E();
        //        e.TAX_RATE = 200;//
    }
}
//如果我们要求A类不能被其他类继承
//可以使用final修饰 A类
final class A {}

//class B extends A{}
class C{
    //如果我们要求hi不能被子类重写
    //可以使用final修饰 hi方法
    public final void hi() {

    }
}
class D extends C{
    /*@Override
    public void hi() {
        System.out.println("重写了C类的hi方法..");
    }*/

}
//当不希望类的某个属性的值被修改
class E{
    public final double TAX_RATE = 0.08;
}
//当不希望某个局部变量被修改,可以使用final
class F{
    public void cry() {
        //这时,NUM 也称为局部常量
        final double NUM = .01;
        //        NUM = .9;
        System.out.println("NUM=" + NUM);
    }
}

2.1、final细节

final修饰的常量一般为大写

final修饰常量时,必须初始化属性

final可以实例化但不能继承(类)

2.1.1、细节一

(掌握)

2.1.2、细节二

  • 不要画蛇添足
java 复制代码
final class AAA{
    //一般来说,如果一个类已经是final类了,就没有必要将方法设置为final方法了
    //public final void hi(){}//多此一举,已经不能继承该类了,可定不能重写该方法
}

有无final做对比:

看此时没有加载static静态代码块的内容,底层进行了优化:

  • 没有加上final:

(输出n1 和 static中的内容)

  • 加上final后

(没有了static的内容)

原因:

类加载的五个阶段:载入、验证、准备、解析 和 初始化 阶段

静态属性和静态代码块是按照顺序执行的;此时静态属性先加载

又因为静态属性之前有final,所以在类加载的准备阶段就被赋予了定义的值,而不执行解析和初始化的阶段。

因此静态代码块不再执行(本来在初始化阶段执行)

  • detail 02

//包装类,String 是final类,不能继承类

2.2、finalExercise

java 复制代码
package com.fhsedu.final_;

public class FinalExercise01 {
    public static void main(String[] args) {
        Circle circle = new Circle(5.0);
        System.out.println( "面积=" + circle.calArea());
    }
}
class Circle{
    private double radius;
    private final double PI;//= 3.14


    //构造器
    public Circle(double radius) {
        //        PI = 3.14;//可以在这三个位置初始化,但是只能初始化一次
        this.radius = radius;
    }
    {
        PI = 3.14;
    };
    public double calArea() {
        return PI * radius * radius;
    }
}
  • 题二
相关推荐
橘猫云计算机设计几秒前
基于springboot微信小程序的旅游攻略系统(源码+lw+部署文档+讲解),源码可白嫖!
java·spring boot·后端·微信小程序·毕业设计·旅游
落榜程序员2 分钟前
Java 基础-30-单例设计模式:懒汉式与饿汉式
java·开发语言
顾林海2 分钟前
深度解析ArrayList工作原理
android·java·面试
雷渊4 分钟前
spring-IoC容器启动流程源码分析
java·后端·面试
用户3315489111079 分钟前
一招搞定Java线程池炸弹,系统吞吐量暴增10倍!
java·后端
下辈子再也不写代码了9 分钟前
分片下载、断点续传与实时速度显示的实现方法
前端·后端·github
卡戎-caryon13 分钟前
【Linux网络与网络编程】03.UDP Socket编程
linux·服务器·网络·笔记·单例模式·udp·网络通信
正经摸鱼13 分钟前
classpath与classpath*实现逻辑
后端·spring
努力的搬砖人.13 分钟前
maven如何使用
java·后端·面试·maven
小码编匠17 分钟前
.NET 验证码生成神器基于 SkiaSharp 的高性能方案
后端·c#·.net