百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 编程网 > 正文

Java中Static关键字-Static定义代码块-单例设计模式

yuyutoo 2024-10-12 00:56 2 浏览 0 评论

文章目录

面向对象的进阶

面向对象进阶的第一篇, 主要讲解内容如下:

  • static关键字 : 开发中如何定义一个共享的信息,给所有对象共享访问,如在线人数信息等。
  • 单例设计模式 : 有些类只需要一个对象就可以了,如任务管理器对象,如何实现一个类只能对外产生同一个对象
  • 面向对象三大特征-继承 : 大量角色类的属性和行为存在重复代码,如果把一类的角色信息进行优化,提升代码复用,降低代码冗余

静态关键字:static

?static修饰成员变量

static是静态的意思,可以修饰成员变量和成员方法。

static修饰成员变量表示该成员变量只在内存中只存储一份,可以被共享访问、修改。

public class User {
 
		// 静态成员变量    
		public static int onlineNumber= 161;
  	// 实例成员变量
  	private String name;
		private int age;
    …
}

成员变量可以分为2类:

  1. 静态成员变量
  2. 实例成员变量

静态成员变量

静态成员变量 : 有static修饰,属于类,与类加载时一起加载一次

常表示如在线人数信息、等需要被共享的信息,可以被共享访问。

public class User {
 
    // 静态成员变量
		public static String onlineNumber= 161;
}

静态成员变量访问方式有两种:

通过类访问(推荐): 类名.静态成员变量

public static void main(String[] args) {
 
		// 类名.静态成员变量
		System.out.println(User.onLineNumber);
}

通过实例对象访问(能够访问但不推荐): 对象.静态成员变量

public static void main(String[] args) {
 
		// 对象.静态成员变量
		User u1 = new User();
		System.out.println(u1.onLineNumber);
}

实例成员变量

实例成员变量 : 无static修饰,存在于每个对象中, 属于每一个实例对象

常表示姓名name、年龄age、等属于每个对象的信息。

public class User {
 
		// 实例成员变量    
		private String name;
		private int age;
}

实例成员变量的访问方式只有一种, 访问格式: 对象.实例成员变量

public static void main(String[] args) {
 
		// 对象.实例成员变量
		User u1 = new User();
		u1.name = "chenyq";
		u1.age = 18;
		System.out.println(u1.name);
		System.out.println(u1.age);
}

?static修饰成员方法

刚刚我们学习了static修饰成员变量, 那修饰成员方法呢?

之前我们定义的方法有的有static修饰,有的是没有的,它们有什么不同

// 没有用static修饰
public void run(){
 
		System.out.println(name +"正在好好学习,天天向上~~");
}

// 有用static修饰
public static int getMax(int a , int b){
 
		return a > b ? a : b;
}

成员方法和成员变量相似, 也是分为两类:

  1. 静态成员方法
  2. 实例成员方法

实例成员方法 (有static修饰,属于类)

建议用类名访问(推荐),也可以用对象访问(同样不推荐)。

表示 对象自己的行为的 ,且方法中需要访问实例成员的,则该方法必须申明成实例方法。

public class Student {
 
    // 对象的成员变量
    private String name;
    private Number age;
  	// 定义有参构造器
    public Student (String name, Number age) {
 
        this.name = name;
        this.age = age;
    }

    // 定义实例成员方法
    public void study() {
 
        // 实例成员方法可以访问对象成员变量
        System.out.println(name + "正在学习");
    }

    public static void main(String[] args) {
 
        // 调用实例方法: 对象.实例方法
        Student stu = new Student("chenyq", 18);
        stu.study(); // chenyq正在学习
    }
}

静态成员方法 (无static修饰,属于对象)

只能用对象触发访问。

如果该方法是 以执行一个公用功能为目的 ,则可以申明成静态方法。

public class Student {
 
    // 对象的成员变量
    private String name;
    private Number age;

     // 定义静态成员方法
     public static int getMax(int a, int b) {
 
        if (a > b) return a;
        return b;
     }

    public static void main(String[] args) {
 
        // 调用静态方法: 类.静态方法
        // 同一个类中访问静态成员, 可以省略不写
        System.out.println(getMax(10, 20)); // 省略
        System.out.println(Student.getMax(10, 20));
    }
}

?静态方法定义工具类

工具类:

工具类中定义的都是一些静态方法,每个方法都是以完成一个共用的功能为目的。

现状问题分析:

在企业的管理系统中,通常需要在一个系统的很多业务处使用验证码进行防刷新等安全控制。

如果登录和注册等多处地方都存在验证码逻辑,就会导致同一个功能多处开发,会出现代码重复度过高。

工具类的好处:

一是 调用方便 ,二是 提高了代码复用 (一次编写,处处可用)

我们在工具类使用静态成员方法, 方便调用节约内存

实例方法需要创建对象调用,此时用对象只是为了调用方法,这样只会浪费内存。

工具类的定义注意:

建议将工具类的构造器进行私有,不允许创建对象。

里面都是静态方法,直接用类名访问即可, 工具类无需创建对象, 。

public class ArraysUtils {
 
    // 工具类构造器私有化处理
    private ArraysUtils() {
 
        
    }
}

我们来试着定义一个数组工具类, 需求如下:

需求:在实际开发中,经常会遇到一些数组使用的工具类。请按照如下要求编写一个数组的工具类:ArraysUtils

思路分析:

我们知道数组对象直接输出的时候是输出对象的地址的,而项目中很多地方都需要返回数组的内容,请在ArraysUtils中提供一个工具类方法toString,用于返回整数数组的内容,返回的字符串格式如:[10, 20, 50, 34, 100]( 只考虑整数数组,且只考虑一维数组

public class ArraysUtils {
 
    // 将构造器设为私有
    private ArraysUtils() {
 

    }

    public static String toString(int[] arr) {
 
        String showArr = "[";
        for (int i = 0; i < arr.length; i++) {
 
            showArr += arr[i];
            showArr += (i == arr.length -1 ? "]" : ", ");
        }
        return showArr;
    }
}

经常需要统计平均值,平均值为去掉最低分和最高分后的分值,请提供这样一个工具方法getAerage,用于返回平均分。( 只考虑浮点型数组,且只考虑一维数组

public class ArraysUtils {
 
    // 将构造器设为私有
    private ArraysUtils() {
 

    }

    public static String toString(int[] arr) {
 
        String showArr = "[";
        for (int i = 0; i < arr.length; i++) {
 
            showArr += arr[i];
            showArr += (i == arr.length -1 ? "]" : ", ");
        }
        return showArr;
    }

    public static double getAerage(double[] arr) {
 
        double max = arr[0];
        double min = arr[0];
        double sum = 0;
        for (int i = 0; i < arr.length; i++) {
 
            if (max < arr[i]) max = arr[i];
            if (min > arr[i]) min = arr[i];
            sum += arr[i];
        }
        return  (sum - max - min) / (arr.length - 2);
    }
}

定义一个测试类TestDemo,调用该工具类的工具方法,并返回结果。

定义好一个工具类, 在其他地方

public class TestDemo {
 
    public static void main(String[] args) {
 
        int[] nums = {
 10, 20, 30, 40};
        // 调用toString方法, 并对返回结果打印
        System.out.println(ArraysUtils.toString(nums)); // [10, 20, 30, 40]

        double[] score = {
 2.0, 1.8, 1.7, 1.9, 1.6};
        // 调用getAerage方法, 并对返回结果打印
        System.out.println(ArraysUtils.getAerage(score)); // 1.8
    }
}

static访问注意事项:

静态方法只能访问静态的成员,不可以直接访问实例成员。

实例方法可以访问静态的成员,也可以访问实例成员。

静态方法中是不可以出现this关键字的。

Static定义代码块

?静态代码块和构造代码块

代码块概述

代码块是类的5大成分之一(成员变量、构造器,方法,代码块,内部类),定义在类中方法外。

在Java类下,使用 { } 括起来的代码被称为代码块 。

代码块分为 :

  1. 静态代码块
  2. 动态代码块

静态代码块:

格式: static{}

特点:需要通过static关键字修饰,随着类的加载而加载,并且自动触发、只执行一次

使用场景:在类加载的时候做一些静态数据初始化的操作,以便后续使用。

public class TestDemo01 {
 
  	// 当类加载的时候, static中的代码块会自动执行一次
    static {
 
        System.out.println("静态代码块与类一起加载的代码块, 自动触发一次");
    }

    public static void main(String[] args) {
 

    }
}

构造代码块(了解,用的少):

格式: {}

特点:每次创建对象,调用构造器执行时,都会执行该代码块中的代码,并且在构造器执行前执行

使用场景:初始化实例资源。

public class TestDemo01 {
 
    {
 
        System.out.println("构造代码块与对象一起加载的代码块, 自动触发执行");
    }

    // 定义构造器
    public TestDemo01() {
 
        System.out.println("构造器执行了");
    }

    public static void main(String[] args) {
 
      	// 创建第一个对象
        new TestDemo01();
      	// 创建第二个对象
        new TestDemo01();
    }
}

打印结果如下:

我们发现, 构造代码块会比构造器先执行

由于构造代码块与对象一起加载, 索引每创建一个对象, 构造代码块中的内容都会执行一次

?静态代码块的小案例练习

相信大家都玩过斗地主游戏, 现在我们有如下一个需求

需求:

斗地主游戏在启动游戏房间的时候,应该提前准备好54张牌,后续才可以直接使用这些牌数据。

我们来完成这个提前准备好54张牌的功能

分析:

该房间只需要一副牌。

定义一个静态的ArrayList集合存储54张牌对象,静态的集合只会加载一份。

在启动游戏房间前,应该将54张牌初始化好

当系统启动的同时需要准备好54张牌数据,此时可以用静态代码块完成。

public class StaticCodeDemo {
 
    // 定义静态成员变量
    public static ArrayList<String> cards = new ArrayList<>();

    // 使用静态代码块对静态资源cards进行初始化
    static {
 
        String[] colors = {
 "?", "?", "?", "?"};
        String[] nums = {
 
        		"3", "4", "5", "6", "7", "8", "9", "10", "J", "Q", "K", "A", "2"
        };

        for (int i = 0; i < nums.length; i++) {
 
            for (int j = 0; j < colors.length; j++) {
 
                cards.add(colors[j] + nums[i]);
            }
        }

        // 添加大小王
        cards.add("大王");
        cards.add("小王");
    }

    public static void main(String[] args) {
 
      	// 打印静态代码块查看效果
        System.out.println(cards);
    }
}

Static单例设计模式

參单例模式介绍

介绍单例模式之前, 我们先说一说什么是设计模式

设计模式(Design pattern):

开发中经常遇到一些问题,一个问题通常有n种解法的,但其中肯定有一种解法是最优的

这个最优的解法被人总结出来了,称之为设计模式。

设计模式有20多种,对应20多种软件开发中会遇到的问题,学设计模式主要是学2点:

  • 第一:这种模式用来解决什么问题。
  • 第二:遇到这种问题了,该模式是怎么写的,他是如何解决这个问题的。

单例模式:

可以保证系统中,应用该模式的这个类永远只有一个实例,即 一个类永远只能创建一个对象

例如任务管理器对象我们只需要一个就可以解决问题了,这样可以节省内存空间。

单例的实现方式有很多, 这篇我主要讲解以下两种单例模式:

饿汉单例模式。

懒汉单例模式。

?饿汉单例模式

饿汉单例设计模式 : 在用类获取对象的时候,对象已经提前为你创建好了。

设计步骤:

1.定义一个类,把构造器私有, 让外界无法创建对象。
2.定义一个静态变量, 用于存储创建出来的对象
// 1.定义一个单例类
public class SingleInstance1 {
 
    // 3.定义一个静态成员变量, 用于储存一个对象
    public static SingleInstance1 instance1 = new SingleInstance1();
    // 2.将类的构造器设置为私有构造器
    private SingleInstance1() {
 
      
    }
}

我们在通过另一个类中, 多次通过 SingleInstance1.instance1 获取对象也只会获取一次对象

这是因为类和静态成员变量一起加载, 且只加载一次, 所以只会获取到一个对象

public class Test {
 
    public static void main(String[] args) {
 
        SingleInstance1 sin1 = SingleInstance1.instance1;
        SingleInstance1 sin2 = SingleInstance1.instance1;
      	// 获取两次得到的是同一个对象
        System.out.println(sin1 == sin2); // true
    }
}

讀懒汉单例模式

懒汉单例设计模式 : 在真正需要该对象的时候,才去创建一个对象(延迟加载对象)。

设计步骤:

1.定义一个类,把构造器私有。
2.定义一个静态变量存储一个对象。
3.提供一个返回单例对象的方法
public class SingleInstance2 {
 
    // 2.定义一个静态变量, 用于存储一个对象, 但是不初始化对象
    public static SingleInstance2 instance2;

    // 1.定义一个类, 把构造器私有
    public SingleInstance2() {
 

    }

    // 3.提供一个返回单例对象的方法
    public static SingleInstance2 getObject() {
 
        if (instance2 == null) return instance2 = new SingleInstance2();
        return instance2;
    }
}

我们测试一下, 在另一个类中, 多次通过 SingleInstance1.getObject 获取对象, 是否只会获取一次对象

public class Test {
 
    private static void main(String[] args) {
 
          SingleInstance2 sin1 =  SingleInstance2.getObject();
          SingleInstance2 sin2 =  SingleInstance2.getObject();
          System.out.println(sin1 == sin2); // true
    }
}

饿汉单例模式和懒汉单例模式区别对比:

饿汉单例模式和懒汉单例模式各有优缺点

  • 从第一次获取对象速度里来看: 饿汉单例模式的速度比懒汉单例模式快
  • 从内存资源来看: 饿汉单例模式有可能会浪费资源, 而懒汉单例模式不会。

原文链接:https://www.tuicool.com/articles/Qn2IBz3

相关推荐

jQuery VS AngularJS 你更钟爱哪个?

在这一次的Web开发教程中,我会尽力解答有关于jQuery和AngularJS的两个非常常见的问题,即jQuery和AngularJS之间的区别是什么?也就是说jQueryVSAngularJS?...

Jquery实时校验,指定长度的「负小数」,小数位未满末尾补0

在可以输入【负小数】的输入框获取到焦点时,移除千位分隔符,在输入数据时,实时校验输入内容是否正确,失去焦点后,添加千位分隔符格式化数字。同时小数位未满时末尾补0。HTML代码...

如何在pbootCMS前台调用自定义表单?pbootCMS自定义调用代码示例

要在pbootCMS前台调用自定义表单,您需要在后台创建表单并为其添加字段,然后在前台模板文件中添加相关代码,如提交按钮和表单验证代码。您还可以自定义表单数据的存储位置、添加文件上传字段、日期选择器、...

编程技巧:Jquery实时验证,指定长度的「负小数」

为了保障【负小数】的正确性,做成了通过Jquery,在用户端,实时验证指定长度的【负小数】的方法。HTML代码<inputtype="text"class="forc...

一篇文章带你用jquery mobile设计颜色拾取器

【一、项目背景】现实生活中,我们经常会遇到配色的问题,这个时候去百度一下RGB表。而RGB表只提供相对于的颜色的RGB值而没有可以验证的模块。我们可以通过jquerymobile去设计颜色的拾取器...

编程技巧:Jquery实时验证,指定长度的「正小数」

为了保障【正小数】的正确性,做成了通过Jquery,在用户端,实时验证指定长度的【正小数】的方法。HTML做成方法<inputtype="text"class="fo...

jquery.validate检查数组全部验证

问题:html中有多个name[],每个参数都要进行验证是否为空,这个时候直接用required:true话,不能全部验证,只要这个数组中有一个有值就可以通过的。解决方法使用addmethod...

Vue进阶(幺叁肆):npm查看包版本信息

第一种方式npmviewjqueryversions这种方式可以查看npm服务器上所有的...

layui中使用lay-verify进行条件校验

一、layui的校验很简单,主要有以下步骤:1.在form表单内加上class="layui-form"2.在提交按钮上加上lay-submit3.在想要校验的标签,加上lay-...

jQuery是什么?如何使用? jquery是什么功能组件

jQuery于2006年1月由JohnResig在BarCampNYC首次发布。它目前由TimmyWilson领导,并由一组开发人员维护。jQuery是一个JavaScript库,它简化了客户...

django框架的表单form的理解和用法-9

表单呈现...

jquery对上传文件的检测判断 jquery实现文件上传

总体思路:在前端使用jquery对上传文件做部分初步的判断,验证通过的文件利用ajaxFileUpload上传到服务器端,并将文件的存储路径保存到数据库。<asp:FileUploadI...

Nodejs之MEAN栈开发(四)-- form验证及图片上传

这一节增加推荐图书的提交和删除功能,来学习node的form提交以及node的图片上传功能。开始之前需要源码同学可以先在git上fork:https://github.com/stoneniqiu/R...

大数据开发基础之JAVA jquery 大数据java实战

上一篇我们讲解了JAVAscript的基础知识、特点及基本语法以及组成及基本用途,本期就给大家带来了JAVAweb的第二个知识点jquery,大数据开发基础之JAVAjquery,这是本篇文章的主要...

推荐四个开源的jQuery可视化表单设计器

jquery开源在线表单拖拉设计器formBuilder(推荐)jQueryformBuilder是一个开源的WEB在线html表单设计器,开发人员可以通过拖拉实现一个可视化的表单。支持表单常用控件...

取消回复欢迎 发表评论: