黑马程序员笔记--静态关键字:static

目录

1.静态关键字static

1.1.static的作用,修饰成员变量的用法

static关键字的作用:

成员变量分为两类:

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

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

根据有无static修饰的成员方法可分为两类:

两者的使用场景:

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

1.5.static实际应用案例:定义工具类

练习:定义数组工具类

1.6.static的注意事项

2.static应用知识:代码块

2.1代码块的分类,作用

代码块概述:

代码块的分类:

2.2静态代码块的应用案例

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

3.1设计模式,单例模式介绍,饿汉单例模式

什么是设计模式(Design pattern)

单例模式

3.2懒汉单例模式


1.静态关键字static

1.1.static的作用,修饰成员变量的用法

static关键字的作用:

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

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

成员变量分为两类:

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

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

2.实例成员变量(无static修饰,存在于每一个对象中):常表示姓名name,年龄age,等属于每个对象的信息。

public class User {
    // 在线人数信息:静态成员变量
    public static int onLineNumber = 161;
    // 实例成员变量
    private String name;
    private int age;
}

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

类(User.class)和主函数(main)放在了方法区,static修饰的静态成员变量onLineNumber被单独放在了堆内存,实例成员变量(name)和(age)以null和0的形式放在了堆内存,主函数放在的栈内存。

首先程序先执行static修饰的变量(onLineNumber)先被加载一次,然后执行主函数,主函数创建两个对象分别是u1和u2,并且将name和age分别放置到两个对象中,最后再进行onLineNumber++。

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

根据有无static修饰的成员方法可分为两类:

1.静态成员方法(有static修饰,属于类),建议用类名访问,也可以用对象访问。

2.实例成员方法(无static修饰,属于对象)只能用对象触发访问。

两者的使用场景:

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

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

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(10, 100);
        // 注意:同一个类中访问静态成员 可以省略类名不写
        getMax(200, 20);

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

        // 3、对象.静态方法(不推荐)
        s.getMax(300,20);
    }
}

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

 首先,静态成员方法可以在主函数中被直接调用(因为静态成员方法属于类),而实例成员方法不能被直接调用(因为实例成员方法属于对象),例如图中的study,需要创建一个对象s做中转站进而调用study。

1.5.static实际应用案例:定义工具类

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

案例:

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

分析:

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

import java.util.Random;

public class VerifyTool {
    /**
       私有构造器
     */
    private VerifyTool(){
    }

    /**
      静态方法
     */
    public static String createCode(int n){
        // 1、使用String开发一个验证码
        String chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
        // 2、定义一个变量用于存储5位随机的字符作为验证码
        String code = "";
        // 3、循环
        Random r = new Random();
        for (int i = 0; i < n; i++) {
            int index = r.nextInt(chars.length());
            // 4、对应索引提取字符
            code += chars.charAt(index);
        }
        return code;
    }
}

工具类的好处:一是调用方便,二是提高了代码复用。

为什么工具类中的方法不用实例对象来做?

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

工具类的定义注意:

1.建议将工具类的构造器进行私有,工具类无需创建对象。

2.里面都是静态方法,直接用类名访问即可。

总结:

1.工具类是什么,有什么好处?
内部都是一些静态方法,每个方法完成一个功能
一次编写,处处可用,提高代码的重用性。
2.工具类有什么要求?
建议工具类的构造器私有化处理。
工具类不需要创建对象。

练习:定义数组工具类

需求:在实际开发中,经常会遇到一些数组使用的工具类。请按照如下要求编写一个数组的工具类:ArraysUtils
1:我们知道数组对象直接输出的时候是输出对象的地址的,而项目中很多地方都需要返回数组的内容,请在ArraysUtils中提供一个工具类方法toString,用于返回整数数组的内容,返回的字符串格式如:[10, 20, 50, 34, 100](只考虑整数数组,且只考虑一维数组
2:经常需要统计平均值,平均值为去掉最低分和最高分后的分值,请提供这样一个工具方法getAerage,用于返回平均分。(只考虑浮点型数组,且只考虑一维数组
3:定义一个测试类TestDemo,调用该工具类的工具方法,并返回结果。

代码如下:

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);
    }
}

由于是创建工具类,故先将构造器私有化(private),然后使用静态方法(static)方便后续使用类名调用工具类。

1.6.static的注意事项

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

2.实例方法可以访问静态成员,也可以访问实例成员;

以上两点可以总结为:范围大的不能访问范围小的,而范围小的可以访问范围大的。

3.静态方法中是不可以出现this关键字的(this在静态方法中不能代表类,而在实例方法中可以代表对象)。

2.static应用知识:代码块

2.1代码块的分类,作用

代码块概述:

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

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

代码块的分类:

静态代码块:

格式:static{};

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

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

构造代码块(了解,用的少):
格式:{};

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

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

2.2静态代码块的应用案例

案例:斗地主游戏牌的数据初始化

需求: 在启动游戏房间的时候,应该提前准备好54张牌,后续才可以直接使用这些牌数据。
分析:
1.该房间只需要一副牌。
2.定义一个静态的ArrayList集合存储54张牌对象,静态的集合只会加载一份。
3.在启动游戏房间前,应该将54张牌初始化好
4.当系统启动的同时需要准备好54张牌数据,此时可以用静态代码块完成。

代码如下:

import java.util.ArrayList;

public class    StaticCodeTest3 {
    /**
       模拟初始化牌操作
         点数: "3","4","5","6","7","8","9","10","J","Q","K","A","2"
         花色: "♠", "♥", "♣", "♦"
       1、准备一个容器,存储54张牌对象,这个容器建议使用静态的集合。静态的集合只加载一次。
     */
    // int age = 12;
    public 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++) {
            // sizes[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);
    }
}

首先创建一个静态集合作为容器,存放54张卡牌,在代码块中(static{})使用两个for循环对卡片的花色和号码进行配对,构造出54张卡片,并且添加大小王,这样子当程序运行时,随着类的加载,代码块自动执行且只执行一次。

总结:代码块的作用是在系统启动时对数据进行初始化,使用静态代码块完成数据的初始化操作,代码优雅。

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

3.1设计模式,单例模式介绍,饿汉单例模式

什么是设计模式(Design pattern)

1.开发中经常遇到一些问题,一个问题通常有n种解法的,但其中肯定有一种解法是最优的,这个最优的解法被人总结出来了,称之为设计模式。
2.设计模式有20多种,对应20多种软件开发中会遇到的问题,学设计模式主要是学2点:
第一:这种模式用来解决什么问题。
第二:遇到这种问题了,该模式是怎么写的,他是如何解决这个问题的。

单例模式

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

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

单例的实现方式主要有:

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

设计步骤:先定义一个类,把构造器私有,并且定义一个静态变量存储一个对象。

public class SingleInstance1 {
    /**
       static修饰的成员变量,静态成员变量,加载一次,只有一份
     */
    // public static int onLineNumber = 21;
    public static SingleInstance1 instance = new SingleInstance1();

    /**
        1、必须私有构造器:私有构造器对外不能被访问。
     */
    private SingleInstance1(){
    }
}

2.懒汉单例模式。

3.2懒汉单例模式

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

设计步骤:

1.定义一个类,将构造器私有;

2.定义一个静态变量存储一个对象;

3.提供一个返回单例对象的方法。

public class SingleInstance2 {
    /**
       2、定义一个静态的成员变量用于存储一个对象,一开始不要初始化对象,因为人家是懒汉
     */
    private static SingleInstance2 instance;

    /**
       1、私有构造器啊
     */
    private SingleInstance2(){
    }

    /**
      3、提供一个方法暴露,真正调用这个方法的时候才创建一个单例对象
     */
    public static SingleInstance2 getInstance(){
        if(instance == null){
            // 第一次来拿对象,为他做一个对象
            instance = new SingleInstance2();
        }
        return instance;
    }
}

  • 4
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值