static的作用
static是静态的意思,可以修饰成员变量和成员方法。
static修饰成员变量表示该成员变量只在内存中只存储一份,可以被共享访问、修改。
成员变量
分为2类
静态成员变量(有static修饰,属于类,内存中加载一次): 常表示如在线人数信息等需要被共享的信息,可以被共享访问。
实例成员变量(无static修饰,存在于每个对象中):常表示姓名name、年龄age等属于每个对象的信息。
访问格式
类名.静态成员变量(推荐)
对象.静态成员变量(不推荐)
对象.实例成员变量
使用场景
静态成员变量:表示在线人数等需要被共享的信息。
实例成员变量:属于每个对象,且每个对象信息不同时(name,age,…等)
示例
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);// 2、对象.实例成员变量// System.out.println(name);User u1 = new User();u1.name = "猪八戒";u1.age = 36;System.out.println(u1.name);System.out.println(u1.age);// 对象.静态成员变量(不推荐这样访问)u1.onLineNumber++;User u2 = new User();u2.name = "孙悟空";u2.age = 38;System.out.println(u2.name);System.out.println(u2.age);// 对象.静态成员变量(不推荐这样访问)u2.onLineNumber++;System.out.println(onLineNumber);}
}
static修饰成员变量的内存原理
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(10, 100);// 注意:同一个类中访问静态成员 可以省略类名不写getMax(200, 20);// 2、对象.实例方法// study(); // 报错的Student s = new Student();s.name = "全蛋儿";s.study();// 3、对象.静态方法(不推荐)s.getMax(300,20);}
}
static修饰成员方法的内存原理
static实际应用案例:设计工具类
工具类中定义的都是一些静态方法,每个方法都是以完成一个共用的功能为目的。
案例导学:
在企业的管理系统中,通常需要在一个系统的很多业务处使用验证码进行防刷新等安全控制。
现状问题分析:
如果登录和注册等多处地方都存在验证码逻辑,就会导致同一个功能多处开发,会出现代码重复度过高。
代码实现
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;}
}
工具类的好处
一是调用方便,二是提高了代码复用(一次编写,处处可用)。
为什么工具类中的方法不用实例方法做?
实例方法需要创建对象调用,此时用对象只是为了调用方法,这样只会浪费内存。
工具类的定义和使用的建议
建议将工具类的构造器进行私有,工具类无需创建对象。
里面都是静态方法,直接用类名访问即可。
static的注意事项总结[面试热点]
静态方法只能访问静态的成员,不可以直接访问实例成员。
实例方法可以访问静态的成员,也可以访问实例成员。
静态方法中是不可以出现this关键字的。
static应用知识:代码块
代码块概述
代码块是类的5大成分之一(成员变量、构造器,方法,代码块,内部类),定义在类中方法外。 在Java类下,使用 { } 括起来的代码被称为代码块 。
代码块的分类
静态代码块:
格式:static{}
特点:需要通过static关键字修饰,随着类的加载而加载,并且自动触发、只执行一次
使用场景:在类加载的时候做一些静态数据初始化的操作,以便后续使用。
构造代码块(了解,用的少):
格式:{}
特点:每次创建对象,调用构造器执行时,都会执行该代码块中的代码,并且在构造器执行前执行。
使用场景:初始化实例资源。
静态代码块的应用案例--斗地主游戏
需求: 在启动游戏房间的时候,应该提前准备好54张牌,后续才可以直接使用这些牌数据。
分析:
该房间只需要一副牌。
定义一个静态的ArrayList集合存储54张牌对象,静态的集合只会加载一份。
在启动游戏房间前,应该将54张牌初始化好。
当系统启动的同时需要准备好54张牌数据,此时可以用静态代码块完成。
代码实现:
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);}
}
static应用知识:单例
设计模式
开发中经常遇到一些问题,一个问题通常有n种解法的,但其中肯定有一种解法是最优的,这个最优的解法被人总结出来了,称之为设计模式。
设计模式有20多种,对应20多种软件开发中会遇到的问题,学设计模式主要是学2点:
第一:这种模式用来解决什么问题。
第二:遇到这种问题了,该模式是怎么写的,他是如何解决这个问题的。
单例模式介绍
可以保证系统中,应用该模式的这个类永远只有一个实例,即一个类永远只能创建一个对象。
例如任务管理器对象我们只需要一个就可以解决问题了,这样可以节省内存空间。
饿汉单例模式
在用类获取对象的时候,对象已经提前为你创建好了。
设计步骤:
定义一个类,把构造器私有。
定义一个静态变量存储一个对象。
代码实现:
public class SingleInstance1 {/**static修饰的成员变量,静态成员变量,加载一次,只有一份*/// public static int onLineNumber = 21;public static SingleInstance1 instance = new SingleInstance1();/**1、必须私有构造器:私有构造器对外不能被访问。*/private SingleInstance1(){}
}
懒汉单例模式
在真正需要该对象的时候,才去创建一个对象(延迟加载对象)。
设计步骤:
定义一个类,把构造器私有。
定义一个静态变量用来指向一个对象。
提供一个返回单例对象的方法。
代码实现:
public class SingleInstance2 {/**2、定义一个静态的成员变量用于存储一个对象,一开始不要初始化对象,因为人家是懒汉*/private static SingleInstance2 instance;/**1、私有构造器啊*/private SingleInstance2(){}/**3、提供一个方法暴露,真正调用这个方法的时候才创建一个单例对象*/public static SingleInstance2 getInstance(){if(instance == null){// 第一次来拿对象,为他做一个对象instance = new SingleInstance2();}return instance;}
}