静态关键字:static

静态关键字:static

static关键字的作用:

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

static 修饰成员变量的方法:

成员变量可以分为两类

  • 静态成员变量(有static修饰,属于类,内存中加载一次):常表示如在线人数、等需要被共享的信息,可以被共享访问。

    • public class User{
          //静态成员变量
          public static String onlineNumber = 161;
      }
      
      • 类名.静态成员变量。(推荐)
      • 对象.静态成员变量。(不推荐)
  • 实例成员变量(无static修饰,存在于每个对象中):常表示姓名name、年龄age、等属于每个对象的信息。

    • public class User{
          public static String onlineNumber = 161;
          //实例成员变量
          private String name;
          private int age;
      }
      
      • 对象.实例成员变量
package com.csl.d1_static_filed;

public class User {
    //在线人数信息:静态成员变量
    public static int onlineNumber = 161;

    //实例成员变量
    private String name;
    private int age;

    public static void main(String[] args) {
        //1.类名.静态成员变量
        User.onlineNumber++;
        //注意:同一个类中访问静态成员变量,类名可以省略不写
        System.out.println(onlineNumber);
        System.out.println(User.onlineNumber);

        //2.对象.静态成员变量
        User u1 = new User();
        u1.name = "孙悟空";
        u1.age = 13;
        System.out.println(u1.name);
        System.out.println(u1.age);
        // 对象.静态成员变量  (不推荐)
        u1.onlineNumber++;

        User u2 = new User();
        u2.name = "猪八戒";
        u2.age = 23;
        System.out.println(u2.name);
        System.out.println(u2.age);
        // 对象.静态成员变量  (不推荐)
        u2.onlineNumber++;
        System.out.println(onlineNumber);
    }
}
output:
162
162
孙悟空
13
猪八戒
23
164

static修饰成员变量的内存原理

image-20220109193440669

static修饰成员方法的基本用法

成员方法的分类

  • 静态成员方法(有static修饰,属于类),可以用类名访问,也可以用对象名访问。
  • 实例成员方法(无static修饰,属于对象),只能用对象触发访问。

使用场景

  • 表示对象自己行为的,且方法中需要访问实例变量的,则该方法必须申明成实例方法。
  • 如果该方法是以执行一个通用功能为目的,或者需要方便访问,则可以申明成静态成员方法。
public class Student {
    private String name;
    private int age;
    /*
    实例方法:无static修饰,属于对象的,通常表示自己的行为,可以访问对象的成员变量
     */
    public void study(){
        System.out.println(name+"正在学习!");
    }

    /**
     * 静态方法:有static修饰的,隶属于类,可以被类和对象共同访问
     */
    public static void getMax(int a,int b){
        System.out.println(a > b ? a : b);
    }

    public static void main(String[] args) {
        //1.类名.静态方法
        Student.getMax(100,200);
        //注意:同一个类中访问静态成员,可以省略类名不写
        getMax(22,33);

        //2.对象.实例方法
        // study();//报错的
        Student s = new Student();
        s.name = "全蛋儿,";
        s.age = 3;
        s.study();

        //3.对象.静态方法(不推荐)
        s.getMax(111,333);
    }
}
output:
200
33
全蛋儿,正在学习!
333

static 修饰成员方法的内存原理

image-20220109200026906

static实例应用案例:使用静态方法定义工具类

工具类

  • 对于一些应用程序中多次需要用到的功能,可以将这些功能封装成静态方法,放在一个类中,这个类就是工具类
  • 工具类的作用:一是方便调用,二是提高了代码复用。
import java.util.Random;

public class Login {
    public static void main(String[] args) {
        //验证码
        //1.使用String开发一个验证码
        String chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
        //2.定义一个变量用作存储随机产生的5位字符
        String code = "";
        //3.循环
        Random r = new Random();
        for (int i = 0; i < 5; i++) {
            int index = r.nextInt(chars.length());
            //4.对应索引提取字符
            code += chars.charAt(index);
        }
        System.out.println("验证码为:"+code);
    }
}

单独写成工具类

import java.util.Random;

public class VerifyTool {
    public static String creatCode(int n){
        //使用String开发验证码
        String chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
        //定义一个变量用于储存验证码
        String code = "";
        Random r = new Random();
        for (int i = 0; i < n; i++) {
            int index = r.nextInt(chars.length());
            code += chars.charAt(index);
        }
        return code;
    }
}
----------------------------
    public class Register {
    public static void main(String[] args) {
        System.out.println(VerifyTool.creatCode(5));
    }
}

工具类原理和延伸

  • 一次编写,处处可用
  • 建议将工具类的构造器私有,不让工具类对外产生对象。
import java.util.Random;

public class VerifyTool {
    
    private VerifyTool(){
        
    }
    
    public static String creatCode(int n){
        //使用String开发验证码
        String chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
        //定义一个变量用于储存验证码
        String code = "";
        Random r = new Random();
        for (int i = 0; i < n; i++) {
            int index = r.nextInt(chars.length());
            code += chars.charAt(index);
        }
        return code;
    }
}

为什么工具类中的方法不用实例方法来写呢?

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

工具类是什么,有什么好处?

  • 内部是一些静态方法,每个方法完成一个功能
  • 一次编写,处处可用,提高代码的复用性

工具类有什么要求?

  • 建议工具类的构造器私有化处理。
  • 工具类不需要创建对象

static实际应用案例:定义数组工具类

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

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

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

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

package com.csl.d3_static_test;

public class Test {
    public static void main(String[] args) {
        int[] arr = {10,20,30,40,50};
        System.out.println(arr);
        System.out.println(ArrayUtils.toString(arr));

        System.out.println(ArrayUtils.getAverage(arr));
    }
}

package com.csl.d3_static_test;

public class ArrayUtils {
    //构造器私有化处理
    private ArrayUtils(){

    }

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

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

        }
        return (sum - max - min)*1.0/(arr.length-2);
    }
}
output:
[I@1b6d3586
[10,20,30,40,50]
30.0

static注意事项

  • 静态方法只能访问静态的成员,不可以直接访问实例成员。(可以在静态方法中创建对象访问)
  • 实例方法可以访问静态的成员,也可以访问实例成员。
  • 静态方法中是不可以出现this关键字的。
package com.csl.d4_static_attention;

public class Test {
    //静态成员变量
    public static int age;

    //实例成员变量
    public String name;

    //静态成员方法
    public static void getMax(){
        //1.静态方法可以直接访问静态成员变量
        System.out.println(age);
        System.out.println(Test.age);
        //3.静态方法中不能出现this关键字
    }
    //2.实例方法可以直接访问静态成员,也可以访问实例成员
    public void run(){
        System.out.println(age);
        System.out.println(Test.age);
        study();
        Test.study();
        System.out.println(name);
        sin();
    }
    public void sin(){
        System.out.println("我在唱歌");
    }
    public static void study(){
        System.out.println("我正在学习!");
    }
}

static应用知识:代码块

代码块的分类、作用

代码块概述

  • 代码块是类的5大成分之一(成员变量、构造器、方法、代码块、内部类),定义在类中方法外
  • 在Java类中,使用 { }括起来的的代码称为代码块。

代码块分为

  • 静态代码块
    • 格式:static{}
    • 特点:需要通过static关键字修饰,随着类的加载而加载,并且自动触发、只执行一次
    • 使用场景:在类加载的时候做一些静态数据初始化的操作,以便后续使用。
package com.csl.d5_static_codeblock;

public class TestDemo1 {
    private static String stuName;

    public static void main(String[] args) {
        System.out.println("========main方法被执行输出=========");
        System.out.println(stuName);
    }
    /*
    特点:与类一起加载,自动触发执行一次,优先执行
    作用:可以在程序加载时对一些静态数据进行初始化操作(准备内容)
     */

    static {
        System.out.println("========静态代码块被触发执行=========");
        stuName = "陈太帅";
    }
}
output:
========静态代码块被触发执行=========
========main方法被执行输出=========
陈太帅

  • 构造代码块(了解,用的少)
    • 格式:{}
      • 特点:每次创建对象,调用构造器执行时,都会执行该代码块中的代码,并且在构造器执行器执行。
      • 使用场景:初始化实例资源。
package com.csl.d5_static_codeblock;

public class TestDemo2 {
    private String name;
    /*
        构造代码块,属于对象的,与对象一起加载,自动触发执行,优先于构造器
     */
    {
        System.out.println("=========构造代码块被执行了==========");
        name = "二蛋";
    }
    public TestDemo2(){
        System.out.println("========构造器被触发执行=========");
    }
    public static void main(String[] args) {
        TestDemo2 t = new TestDemo2();
        System.out.println(t.name);
        
        TestDemo2 t1 = new TestDemo2();
        System.out.println(t1.name);
    }
}
output
=========构造代码块被执行了==========
========构造器被触发执行=========
二蛋
=========构造代码块被执行了==========
========构造器被触发执行=========
二蛋

静态代码块的应用案例

斗地主游戏

需求

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

分析

  1. 该房间只需要一副牌
  2. 定义一个静态的ArrayList集合存储54张牌对象,静态的集合只会加载一份。
  3. 在启动游戏前,应该将54张牌初始化好
  4. 当系统启动的同事需要准备好54张牌数据,此时可以用静态代码块完成。
package com.csl.d5_static_codeblock;

import java.util.ArrayList;

public class StaticCodeTest {
    /*
        模拟初始化操作
        点数:"3","4","5","6","7","8","9","10","J","Q","K","A","2";
        花色:"♠","♥","♣","♦";
     */

    //1.准备一个容器,存储54张牌对象,这个容器建议使用静态的集合,静态的集合只加载一次
    static ArrayList<String> cards = new ArrayList<>();

    /**
     * 2.在游戏启动之前需要准备好54张牌放进去,使用静态代码块进行初始化
     */
    static {
        //3.加载54张牌放进去
        //4.准备4种花色,类型确定,个数确定
        String[] colors = {"♠", "♥", "♣", "♦"};
        //5.定义点数
        String[] sizes = {"3", "4", "5", "6", "7", "8", "9", "10", "J", "Q", "K", "A", "2"};
        //6.先遍历点数,再组合花色
        for (int i = 0; i < sizes.length; i++) {
            for (int j = 0; j < colors.length; j++) {
                cards.add(sizes[i] + colors[j]);
            }
        }
        //7.添加大小王
        cards.add("小王");
        cards.add("大王");
    }

    public static void main(String[] args) {
        System.out.println("新牌为:" + cards);
    }
}
output:
新牌为:[3♠, 3♥, 3♣, 3♦, 4♠, 4♥, 4♣, 4♦, 5♠, 5♥, 5♣, 5♦, 6♠, 6♥, 6♣, 6♦, 7♠, 7♥, 7♣, 7♦, 8♠, 8♥, 8♣, 8♦, 9♠, 9♥, 9♣, 9♦, 10♠, 10♥, 10♣, 10♦, J♠, J♥, J♣, J♦, Q♠, Q♥, Q♣, Q♦, K♠, K♥, K♣, K♦, A♠, A♥, A♣, A♦, 2♠, 2♥, 2♣, 2♦, 小王, 大王]

static应用知识:单例设计模式

设计模式

什么是设计模式

  • 设计模式是一套被前人反复使用、多数人知晓、经过分类编目的代码设计经验的总结,后来者可以直接拿来解决问题。
  • 设计模式是软设计中的常见解决方案,好的设计模式可以进一步提高代码的重用性。

单例模式介绍

单例模式:

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

单例的场景和作用

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

饿汉单例模式

  • 在用类获取对象的时候,对象已经提前为你创建好了。

设计步骤:

  • 定义一个类,把构造器私有。
  • 定义一个静态变量存储一个对象。
package com.csl.d6_static_singleinstance;

public class SingleInstance {
    /*
       2.定义一个公开的静态的成员变量存储一个类的对象
       饿汉:在这里加载静态变量 的时候就会创建对象了
       public static int onlineNumber = 161;
    */
    public static SingleInstance instance = new SingleInstance();

    /*
        1.构造器私有
     */
    private SingleInstance(){

    }

}

测试是不是单例

package com.csl.d6_static_singleinstance;

public class Test {
    public static void main(String[] args) {
        SingleInstance s1 = SingleInstance.instance;
        SingleInstance s2 = SingleInstance.instance;
        SingleInstance s3 = SingleInstance.instance;

        System.out.println(s1);
        System.out.println(s2);
        System.out.println(s3);
        System.out.println(s1==s3);
    }
}
output:
com.csl.d6_static_singleinstance.SingleInstance@1b6d3586
com.csl.d6_static_singleinstance.SingleInstance@1b6d3586
com.csl.d6_static_singleinstance.SingleInstance@1b6d3586
true

懒汉单例模式

  • 在真正需要该对象的时候,才去创建一个对象(延迟加载对象)

设计步骤:

  • 定义一个类,把构造器私有
  • 定义一个静态变量存储一个对象
  • 提供一个返回单例对象的方法
package com.csl.d6_static_singleinstance;

public class SingleInstance2 {
    /*
        1.构造器私有化
     */
    private SingleInstance2() {
    }

    /*
        2.创建一个静态的成员变量来存储本类的对象,注意此时不能初始化对象
     */
    private static SingleInstance2 instance;//null

    /*
        3.定义一个方法,让其他地方可以来调用获取一个对象
     */
    public static SingleInstance2 getInstance() {
        if (instance == null) {
            instance = new SingleInstance2();
        }
        return instance;
    }
}

测试

package com.csl.d6_static_singleinstance;

public class Test2 {
    public static void main(String[] args) {
        SingleInstance2 s1 = SingleInstance2.getInstance();
        SingleInstance2 s2 = SingleInstance2.getInstance();
        SingleInstance2 s3 = SingleInstance2.getInstance();

        System.out.println(s1);
        System.out.println(s2);
        System.out.println(s3);
        System.out.println(s1 == s3);
    }
}
output:
com.csl.d6_static_singleinstance.SingleInstance2@1b6d3586
com.csl.d6_static_singleinstance.SingleInstance2@1b6d3586
com.csl.d6_static_singleinstance.SingleInstance2@1b6d3586
true

posted @ 2022-01-09 22:57  tryAgainCs  阅读(131)  评论(0编辑  收藏  举报