static静态关键字
一.static是什么,static修饰成员变量的用法
1.static概述
- static是静态的意思,可以用来修饰成员变量,成员方法
- static修饰成员变量之后称为静态成员变量(类变量),修饰方法之后称为静态方法(类方法)。
- static修饰后的成员变量,可以被类的所有对象共享(访问、修改)。
2.static修饰的成员变量是什么,有何特点
-
静态成员变量(有static修饰,属于类、加载一次,内存中只有一份),访问格式
-
类名.静态成员变量(推荐)
对象.静态成员变量(不推荐)。
-
实例成员变量(无static修饰,属于对象),访问格式:
-
对象.实例成员变量。
3.两种成员变量各自在什么情况下定义?
- 静态成员变量:表示在线人数等需要被类的所有对象共享的信息时。
- 实例成员变量:属于每个对象,且每个对象的该信息不同时(如:name,age,money…)
public class Study {
//有static修饰,为静态成员变量
public static int onlineNumber = 100;
//无static修饰,为实例成员变量,属于每个对象的,必须用对象名访问
private String name;
private int age;
public static void main(String[] args) {
//目标:理解static修饰成员边的作用和访问特点
//1.类名.静态成员变量
System.out.println(Study.onlineNumber);
System.out.println(onlineNumber);//调用静态成员变量可以省略类名
//2.对象名.实例成员变量
//System.out.println(Study.name);//无对象的的时候,不可使用类名来调用实例成员变量
Study s = new Study();
s.name = "张飞";
s.age = 38;
System.out.println(s.name);
System.out.println(s.age);
s.onlineNumber++;//新来了一个人
System.out.println(s.onlineNumber);
}
}
二.static修饰成员变量方法的基本用法
1.成员方法的分类:
-
静态成员方法(有static修饰,归属于类),建议用类名访问,也可以用对象访问。
-
实例成员方法(无static修饰,归属于对象),只能用对象触发访问。
使用场景:
-
表示对象自己的行为的,且方法中需要访问实例成员的,则该方法必须申明成实例方法。
-
如果该方法是以执行一个共用功能为目的,则可以申明成静态方法。
2.成员方法的分类和访问分别是什么样的
- 静态成员方法(有static修饰,属于类和对象共享)访问格式:
类名.静态成员方法。
对象.静态成员方法。(不推荐)
- 实例成员方法(无static修饰,属于对象)的访问格式:
对象.实例成员方法。
public class Student {
//实例成员变量,无static修饰,属于对象
private String name;
//静态方法,有static修饰,归属于类,可以被共享,用类名或者对象都可以访问。
public static int getMax(int age1,int age2){
return age1 > age2 ? age1 : age2;
}
//实例方法:属于对象的,只能用对象触发访问
public void study (){
System.out.println(name + "天下无敌!");
}
public static void main(String[] args) {
//1.类名.静态成员变量
System.out.println(Student.getMax(100,20));
System.out.println(getMax(100,20));//注意:同一个类中,访问静态方法,类名可以省略
//study();报错,需要对象来调用实例方法
//2.对象名,实例方法
Student s = new Student();
s.name = "二弟";
s.study();
//3.对象.静态方法(语法可行,但是并不推荐)
System.out.println(s.getMax(180,20));//不推荐使用
System.out.println(Student.getMax(180,20));
System.out.println(getMax(180,20));
//使用类名直接调用 静态方法 ,可以省略类名
}
}
3.static访问注意事项:
- 静态方法只能访问静态的成员,不可以直接访问实例成员。
- 实例方法可以访问静态的成员,也可以访问实例成员。
- 静态方法中是不可以出现this关键字的。
三.static:工具类
1.工具类:
-
类中都是一些静态方法,每个方法都是以完成一个共用的功能为目的,这个类用来给系统开发人员共同使用的。
-
工具类的好处:一是调用方便,二是提高了代码复用(一次编写,处处可用)
-
由于工具里面都是静态方法,直接用类名即可访问,因此,工具类无需创建对象,建议将工具类的构造器进行私有。
public class Util { /** * 由于工具类无需创建对象,可将其构造器进行私有化! */ private Util(){ } /** * 静态方法 */ public static String createVerifyCode(int n){ //开发一个验证码: //1.定义一个变量记住验证码 String code = ""; //2.定义一个变量记住全部验证码字符 String data = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; //3.定义一个循环生成几个随机索引,去得到几个字符 Random r = new Random(); for (int i = 0; i < n; i++) { //4.获取验证码索引对应的字符,接给code int index = r.nextInt(data.length()); code += data.charAt(index); } return code; } }
public class Login { public static void main(String[] args) { System.out.println(Util.createVerifyCode(5)); } }
案例.定义数组类工具类:
public class ArrayUtil { /** * 将构造器私有化 */ private ArrayUtil(){ } /** * 静态方法 */ public static String toString (int [] arr){ //1.校验 if(arr == null){ return null; } //2.拼接内容并返回 String result = "["; for (int i = 0; i < arr.length; i++) { result += (i == arr.length - 1 ? arr[i] : arr[i]+","); } result += "]"; return result; } }
public class demo { public static void main(String[] args) { int[] arr = null; int[] arr1 = {}; int[] arr2 = {11,22,33,44,55}; System.out.println(ArrayUtil.toString(arr)); System.out.println(ArrayUtil.toString(arr1)); System.out.println(ArrayUtil.toString(arr2)); } }
2.代码块:
1.代码块概述:
-
代码块是类的5大成分之一(成员变量、构造器,方法,代码块,内部类),定义在类中方法外。
-
在Java类下,使用 { } 括起来的代码被称为代码块 。
2.代码块分为:
静态代码块:
格式:static{}
特点:需要通过static关键字修饰,随着类的加载而加载,并且自动触发、只执行一次
使用场景:在类加载的时候做一些静态数据初始化的操作,以便后续使用。
构造代码块(了解,见的少):
格式:{}
特点:每次创建对象,调用构造器执行时,都会执行该代码块中的代码,并且在构造器执行前执行
使用场景:初始化实例资源。
3.静态代码块的应用案例:斗地主游戏
public class StaticDemo {
/**
1.定义一个静态的集合,这样这个集合只加载一个,当前房间只需要一副牌
*/
public static ArrayList<String> cards = new ArrayList<>();
/**
2.在程序真正运行main方法前,把54张牌放进去,后续游戏可直接使用
*/
static {
//3.开始做牌,放到集合中去
//a.定义一个数组存放全部点数:类型确定,个数确定
String[] sizes = {"3","4","5","6","7","8","9","J","Q","K","A","2"};
//b.定义一个数组存放全部花色:类型确定,个数确定
String[] colors= {"♥","♠","♦","♣"};
//c.遍历
for (int i = 0; i < sizes.length; i++) {
for (int j = 0; j < colors.length; j++) {
String card = sizes[i] + colors[j];
cards.add(card);
}
}
//d.单独加入大小王
cards.add("大🃏");
cards.add("小🃏");
}
public static void main(String[] args) {
//模拟游戏前,初始化54张牌
System.out.println(cards);
}
}
静态代码块的作用是什么?
如果要在启动系统时对静态资源进行初始化,则建议使用静态代码块完成数据的初始化操作。
4.static应用知识:单例设计模式
什么是设计模式(Design pattern)
-
开发中经常遇到一些问题,一个问题通常有n种解法的,但其中肯定有一种解法是最优的,这个最优的解法被人总结出来了,称之为设计模式。
-
设计模式有20多种,对应20多种软件开发中会遇到的问题。
学设计模式主要是学2点:
-
这种模式用来解决什么问题。
-
遇到这种问题了,该模式是怎么写的,他是如何解决这个问题的。
单例模式
-
可以保证系统中,应用该模式的这个类永远只有一个实例,即一个类永远只能创建一个对象。
-
例如任务管理器对象我们只需要一个就可以解决问题了,这样可以节省内存空间。
1.饿汉单例设计模式
在用类获取对象的时候,对象已经提前为你创建好了。
设计步骤:
-
定义一个类,把构造器私有。
-
定义一个静态变量存储一个对象。
/**
* 使用饿汉单例实现单例类
*/
public class SingleInStance {
//1.首先把构造器定义私有,藏起来
private SingleInStance(){
}
//2.饿汉单例是在获取对象前,对象已经提前准备好了一个
//这个对象只能是一个,所以定义静态成员变量记住。
public static SingleInStance instance = new SingleInStance();
}
public class Test {
public static void main(String[] args) {
SingleInStance s1 = SingleInStance.instance;
SingleInStance s2 = SingleInStance.instance;
System.out.println(s1 == s2);
}
}
2.懒汉单例设计模式
在真正需要该对象的时候,才去创建一个对象(延迟加载对象)。
设计步骤:
-
定义一个类,把构造器私有。
-
定义一个静态变量存储一个对象。
-
提供一个返回单例对象的方法。
//使用懒汉单例实现单例
public class SingleInStance2 {
/**
1.首先将构造器私有化
*/
private SingleInStance2(){
}
/**
2.懒汉单例是指获取对象前,对象已经提前准备好了一个
这个对象只能是一个,所以定义静态成员变量记住
*/
private static SingleInStance2 inStance;
/**
3.提供一个方法,对挖返回单例对象
*/
public static SingleInStance2 getInStance(){
if (inStance == null){
//第一次来拿对象:此时需要创建对象。
inStance = new SingleInStance2();
}
return inStance;
}
}
public class Test2 {
public static void main(String[] args) {
SingleInStance2 s1 = SingleInStance2.getInStance();
SingleInStance2 s2 = SingleInStance2.getInStance();
System.out.println(s1==s2);
}
}