JavaSE进阶
静态关键字:static
static关键字的作用
static是静态的意思,可以修饰成员变量,表示该成员变量只在内存中只存储一份,可以被共享访问,修改
成员变量分类
静态成员变量
有static修饰,属于类,内存中加载一次
访问:
- 类名.静态成员变量(推荐)
- 对象.静态成员变量
实例成员变量
无static修饰,存在于每个对象中
访问:对象.实例成员变量
public class User {
//在线人数信息 静态成员变量
public static int onLineNumber;
//实例成员变量
private String name;
private int age;
public static void main(String[] args) {
//1.类名.静态成员变量
User.onLineNumber++;
//注意:同一个类中访问静态成员变量,类名可以省略不写
System.out.println(onLineNumber);
//2.对象.实例成员变量
User u1=new User();
u1.name="孙悟空";
u1.age=36;
//对象.静态成员变量(不推荐这样访问)
u1.onLineNumber++;
System.out.println(u1.name);
System.out.println(u1.age);
System.out.println(User.onLineNumber);
}
}
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,15);
//注意:同一个类中访问静态方法 可以省略类名不写
getMax(20,25);
//2.对象.实例方法
Student s = new Student();
s.name="王五";
s.age=10;
s.study();
//3.对象.静态方法
s.getMax(30,50);
}
}
static修饰成员方法内存原理
static的实际应用案例:使用静态方法定义工具类
案例导学
在企业的管理系统中,通常需要在一个系统的很多业务处使用验证码进行防刷新等安全控制
现状问题分析
- 如果登录和注册等多处地方都存在验证码逻辑,就会导致同一个功能多处开发,会出现代码重复度过高
工具类
- 对于一些应用程序中多次需要用到的功能,可以将这些功能封装成静态方法,放在一个类中,这个类就是工具类
- 工具类的作用:方便调用,提高了代码复用
- 建议将工具类的构造器私有,不让工具类对外产生对象,以便于节约内存
- 实例方法需要创建对象调用,此时用对象只是为了调用方法,这样只会浪费内存
import java.util.Random;
public class VerifyTool {
/**
* 静态方法:验证码
* @param n
* @return
*/
public static String createCode(int n){
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 Regist {
public static void main(String[] args) {
/**
* 验证码
*/
System.out.println(VerifyTool.createCode(10));
}
}
public class Login {
public static void main(String[] args) {
/**
* 验证码
*/
System.out.println(VerifyTool.createCode(5));
}
}
定义数组工具类
需求:在实际开发中,经常会遇到一些数组使用的工具类。请按照如下要求编写一个数组的工具类:ArraysUtils
- 我们知道数组对象直接输出的时候是输出对象的地址的,而项目中有很多地方都需要返回数组的内容的,请在ArraysUtils中提供一个工具类方法toString,用于返回整数数组的内容
- 进场需要统计平均值,平均值为去掉最低分和最高分后的分值,请提供这样一个工具方法getAverage,用于返回平均分
- 定义一个测试类TestDemo,调用该工具类的工具方法,并返回结果
public class ArraysUtils {
private ArraysUtils(){
}
/*
静态方法:工具类
*/
public static String toString(int[] arr){
if(arr!=null){
String chars="[";
for (int i = 0; i < arr.length; i++) {
chars+=(i==arr.length-1)?arr[i]:arr[i]+",";
}
chars+="]";
return chars;
}else{
return null;
}
}
/**
* 静态方法
*/
public static double getAverage(double[] arr){
//总和 最大值 最小值
double sum=0;
double max=arr[0];
double min=arr[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];
}
double ave=(sum-max-min)*1.0/(arr.length-2);
return ave;
}
}
public class TestDemo {
public static void main(String[] args) {
int[] a={1,2,3,4};
System.out.println(ArraysUtils.toString(a));
double[] b={10,20,30,40};
System.out.println(ArraysUtils.getAverage(b));
int[] c={};
System.out.println(ArraysUtils.toString(c));
int[] d=null;
System.out.println(ArraysUtils.toString(d));
}
}
static访问注意事项:
- 静态方法只能访问静态成员,不可以直接访问实例成员
- 实例方法可以访问静态的成员,也可以访问实例成员
- 静态方法中是不可以出现this关键字的
public class Test {
//静态成员变量
public static int onLineNumber=1500;
//实例成员变量
private String name;
public static void getMax(){
//1.静态方法可以直接访问静态成员
System.out.println(onLineNumber);
System.out.println(Test.onLineNumber);
inAddr();
//3.静态方法中不能出现this关键字
// System.out.println(this);
}
public static void inAddr(){
System.out.println("恭喜您,这是静态方法2");
}
public void run(){
//2.实例方法可以直接访问静态成员,也可以访问实例成员
System.out.println(name);
System.out.println(Test.onLineNumber);
getMax();
Test.getMax();
sing();
}
//实例成员方法
public void sing(){
System.out.println(this);
System.out.println(this.name);
}
public static void main(String[] args) {
Test.getMax();
Test t1 = new Test();
t1.run();
}
}
static应用知识: 代码块
代码块的分类、作用
代码块是类的5大成分之一,定义在类中方法外
在Java类下,使用{}括起来的代码被称为代码块
代码块分类
- 静态代码块
格式:static{}
特点:需要通过static关键字修饰,随着类的加载而加载,并且自动触发,只执行一次
使用场景:在类加载的时候做一些静态数据初始化的操作,以便后续使用
public class codeblock {
public static String name;
/**
* 特点:与类一起加载,自动触发一次,优先执行
* 作用:可以在程序加载时进行静态数据的初始化操作
*/
static{
System.out.println("====静态代码块被触发执行====");
name="张三";
}
public static void main(String[] args) {
System.out.println("====main方法被执行输出===");
System.out.println(name);
}
}
- 构造代码块
格式:{}
特点:每次创建对象,调用构造器执行时,都会执行该代码块中的代码,并且在构造器执行前执行
使用场景:初始化实例资源
public class test2 {
private String name;
/*
属于对象的,与对象一起加载,自动触发执行
*/
{
System.out.println("===构造代码块被触发执行===");
name="张三";
}
public test2(){
System.out.println("===构造器被触发执行==");
}
public static void main(String[] args) {
new test2();
test2 t1 = new test2();
System.out.println(t1.name);
}
}
静态代码块的应用案例:斗地主游戏
需求
在启动游戏房间的时候,应该提前准备好54张牌,后续才可以直接使用这些牌数据
分析
- 该房间只需要一副牌
- 定义一个静态的ArrayList集合存储54张牌对象,静态的集合只会加载一份
- 在启动游戏房间前,应该将54张牌初始化好
- 当系统启动的同时需要准备好54张牌数据,此时可以用静态代码块完成
public class doudizhu {
//1.准备一个容器,存储54张牌对象,这个容器建议使用静态的集合,静态的集合只加载一次
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应用知识:单例设计模式
设计模式、单例模式介绍、饿汉单例模式
- 设计模式是一套被前任反复使用、多数人知晓、经过分类编目的代码设计经验的总结,后来者可以直接拿来解决问题
- 设计模式是软件设计中的常见解决方案,好的设计模式可以进一步的提高代码的重用性
单例设计模式
可以保证系统中,应用该模式的这个类永远只有一个实例,即一个类永远只能创建一个对象
饿汉单例设计模式
在用类获取对象的时候,对象已经提前为你创建好了
设计步骤
- 定义一个类,把构造器私有
- 定义一个静态变量存储一个对象
public class SingleInstance {
/*
2、定义一个公开的静态的成员变量存储一个类的对象
*/
public static SingleInstance instance=new SingleInstance();
/**
* 1、把构造器私有起来
*/
private SingleInstance(){
}
}
public class Test5 {
public static void main(String[] args) {
SingleInstance s1=SingleInstance.instance;
SingleInstance s2=SingleInstance.instance;
System.out.println(s1==s2);
}
}
懒汉单例设计模式
在真正需要该对象的时候,才去创建一个对象(延迟加载对象)
设计步骤
- 定义一个类,把构造器私有
- 定义一个静态变量存储一个对象
- 提供一个返回单例对象的方法
public class SingleInstance {
/**
* 2.创建一个静态的成员变量存储本类的对象,注意:此时不能初始化对象
*/
private static SingleInstance instance;
/**
* 1.私有构造器
*/
private SingleInstance(){
}
/**
* 3.定义一个方法,让其他地方可以来调用获取一个对象
* @return
*/
public static SingleInstance getInstance(){
if(instance==null){
//第一次获取对象
instance= new SingleInstance();
}
return instance;
}
}
public class Test {
public static void main(String[] args) {
SingleInstance s1=SingleInstance.getInstance();
SingleInstance s2=SingleInstance.getInstance();
SingleInstance s3=SingleInstance.getInstance();
System.out.println(s1);
System.out.println(s2);
System.out.println(s3);
System.out.println(s1==s2);
}
}