static静态关键字详解(工具类、代码块、单例模式)

static静态关键字详解(工具类、代码块、单例模式)一 static 静态关键字 1 static 是什么 static 修饰成员变量的用法 static 是静态的意思 可以用来修饰成员变量 成员方法 static 修饰成员变量之后称为静态成员变量 类变量 修饰方法之后称为静态方法 类方法 static 修饰后的成员变量

大家好,我是讯享网,很高兴认识大家。

一.static静态关键字

1.static是什么,static修饰成员变量的用法

  • static是静态的意思,可以用来修饰成员变量、成员方法。
  • static修饰成员变量之后称为静态成员变量(类变量),修饰方法之后称为静态方法(类方法)。
  • static修饰后的成员变量,可以被类的所有对象共享(访问、修改)
  • 静态成员变量(有static修饰,属于类,加载一次,内存中只有一份),访问格式:
  1. 类名.静态成员变量(推荐)
  2. 对象.静态成员变量(不推荐)
  • 实例成员变量(无static修饰,属于对象,每个对象中都存储1份),访问格式:
  1. 对象.实例成员变量
  • 静态成员变量:表示在线人数等需要被类的所有对象共享的信息时。
  • 实例成员变量:属于每个对象,且每个对象的信息不同时(如:name、age....)
package com.gch.d1static; public class User { / 在线人数 注意:static修饰的成员变量,静态成员变量,只在内存中存储1份,可以被所有对象共享 */ // 静态成员变量 public static int onlineNumber = 161; // 实例成员变量:无static修饰的,属于每个对象的,必须使用对象名.访问 private String name; private int age; public static void main(String[] args) { // 目标:理解static修饰成员变量的作用和访问特点 // 1. 类名.静态成员变量 System.out.println(User.onlineNumber); // 161 // 2.对象名.静态成员变量 // System.out.println(User.name); 报错 User u = new User(); u.name = "张三"; u.age = 18; System.out.println(u.name); System.out.println(u.age); u.onlineNumber++; // 新进来了一个人 System.out.println(u.onlineNumber); // 162 // 注意:同一个类中静态成员变量的访问可以省略类名 System.out.println(onlineNumber); // 162 } }

讯享网

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

  • 实例成员变量属于每一个对象,对象在堆内存中。
  • 当这个类加载到方法区的同时,它会同步的在堆内存中开辟一块儿这个类的静态变量区,并且只加载一次。
  • 同一个类中,访问静态成员变量,类名可以省略不写。
  • 同一个类中,访问静态成员方法,类名可以省略不写。 


讯享网

 3.static修饰成员方法的用法

 成员方法的分类:

  • 静态成员方法(有static修饰,归属于类,属于类和对象共享):建议用类名访问,也可以用对象访问。
  • 实例成员方法(无static修饰,归属于对象):只能用对象触发访问。
  • 同一个类中,访问静态成员方法,类名可以省略不写。 
  1. 表示对象自己的行为的,且方法中需要访问实例成员的,则该方法必须申明成实例方法。
  2. 如果该方法是以执行一个共用 / 通用功能为目的,则可以申明成静态方法。
讯享网package com.gch.d1static; 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(10, 3)); // 注意:同一个类中,访问静态方法,类名可以省略不写 System.out.println(getMax(10, 30)); // study(); // 报错了 // 2.对象.实例方法 Student s = new Student(); s.name = "小明"; s.study(); // 3.对象.静态方法(语法可行,但是不推荐) System.out.println(s.getMax(10, 23)); } } 

 4.static访问的注意事项:

  • 静态方法只能访问静态的成员,不可以" 直接 "访问实例成员。
  • 实例方法中可以访问静态成员,也可以访问实例成员。
  • 静态方法中是不可以出现this关键字的
package com.gch.d1static; public class Test3 { public static void main(String[] args) { // 目标:理解static访问相关的语法:面试笔试题,或者以后理解程序很重要的知识(拓展) // 静态成员是可以被类和对象共享的 /* static访问注意事项: 静态方法只能访问静态的成员,不可以"直接"访问实例成员 实例方法可以访问静态成员,也可以访问实例成员 静态方法中是不可以出现this关键字的 */ } / 静态成员 */ public static int onlineNumber = 10; public static void test2(){ System.out.println("=====test2===="); } / 实例成员 */ private String name; public void run(){ System.out.println(name + "跑的快!"); } // 1.静态方法只能访问静态成员,不能"直接"访问实例成员 public static void test(){ System.out.println(Test3.onlineNumber); System.out.println(onlineNumber); test(); // System.out.println(name); // 直接报错,静态方法不能直接访问实例成员。 // run(); //直接报错,静态方法不能直接访问实例成员 } // 2.实例方法可以访问静态成员,也可以访问实例成员 public void go(){ System.out.println(Test3.onlineNumber); System.out.println(onlineNumber); test2(); System.out.println(this); // this可以出现在实例方法中,代表本类对象的地址 System.out.println(name); run(); } // 3.静态方法中不可以出现this关键字 public static void test3(){ // this代表本类对象,而静态方法是归属于类的 // System.out.println(this); // 直接报错,静态方法中不可以出现this关键字 } } 

二.static应用知识:工具类

工具类是什么?

  • 工具类类中都是一些静态方法,每个方法都是以完成一个共用的功能为目的,这个类用来给系统开发人员共同使用的。
  • 使用工具类的好处:一是调用方便,二是提高了代码的复用性,提高了开发效率(一次编写,处处可用)

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

  • 实例方法需要创建对象调用。
  • 而静态方法直接用类名即可访问,此时用对象只是为了调用方法,这样只会浪费内存

工具类定义时的其他要求:

  • 由于工具类里面都是静态方法,直接用类名即可访问,因此工具类无需创建对象,建议将工具类的构造器进行私有。
  • 工具类没有必要被其他类继承,因此将工具类用final修饰为最终类。

讯享网package com.gch.d2_static_util; import java.util.Random; / 工具类 使用工具类的好处:调用方便,提高了代码的复用性 使用工具类定义的方法只是为了完成一个公用功能,公用功能写成静态方法,调用方便,只需要通过类名来调用 如果定义成实例方法则需要创建对象,通过对象来调用,此时用对象只是为了调用方法,这样只会浪费内存 由于工具类里面都是静态方法,直接用类名即可访问,因此工具类无需创建对象,建议将工具类的构造器进行私有 将工具类的构造器私有,对外就不能创建对象了 将工具类用final修饰,不可以被其他类继承 */ public final class Util { // 将工具类的构造器私有,使其不能向外创建对象 / 注意:由于工具类无需创建对象,所以将其构造器私有化会显得很专业 */ private Util(){ } / 静态方法:随机生成n位验证码 */ public static String createVerifyCode(int n){ // 1.定义一个字符串存储可能出现的字符信息 String datas = "abcdefghijklmnopqrstovwxyzABCDEFGHIJKLMNOPQRSTOVWXYZ0"; // 2.定义一个循环,循环n次,每次随机一个索引,提取索引位置出的字符连接起来即可 // 3.定义一个字符串变量记录存储的字符 String code = ""; Random r = new Random(); for(int i = 0;i< n;i++){ // 4.随机一个索引 int index = r.nextInt(datas.length()); // 5.提取索引对应位置处的字符连接 code += datas.charAt(index); } // 6.返回生成的随机验证码 return code; } } 
package com.gch.d2_static_util; public class Check { public static void main(String[] args) { // 开发一个验证码 直接通过类名来调用工具类里面的静态方法 System.out.println(Util.createVerifyCode(4)); // Util u = new Util(); 直接报错,Util工具类不能对外创建对象 } } 
讯享网package com.gch.d2_static_util; public class Login { public static void main(String[] args) { // 开发一个验证码 直接通过类名来调用工具类里面的静态方法 System.out.println(Util.createVerifyCode(5)); } } 

package com.gch.d2_static_util; / 定义数组工具类 */ public class ArrayUtils { / 构造器私有 */ private ArrayUtils(){ } / * 定义静态方法返回整型数组的内容 * @param arr:传进来的整型数组 * @return:返回传进来数组的内容 */ public static String toString(int[] arr){ // 一些校验 if(arr == null){ return null; } String result = "["; for(int i = 0;i < arr.length;i++){ result += i == arr.length - 1 ? arr[i] : arr[i] + ", "; } result += "]"; return result; } / * 定义静态方法返回浮点型数组的平均值 * @param arr:传进来的数组 * @return:返回浮点型数组去掉最高分和最低分后的平均值 */ public static double getAerage(double[] arr){ // 1.定义三个变量记录当前数组的最大值,最小值,以及总分 double arrMax = arr[0]; double arrMin = arr[0]; double sum = 0; for(int i = 0;i < arr.length;i++){ if(arr[i] > arrMax){ arrMax = arr[i]; } if(arr[i] < arrMin){ arrMin = arr[i]; } sum += arr[i]; } System.out.println("当前最高分是:" + arrMax); System.out.println("当前最低分是:" + arrMin); // 计算平均分 double average = (sum - arrMax - arrMin) / (arr.length - 2); return average; } } 
讯享网package com.gch.d2_static_util; / 定义测试类,调用该工具类的工具方法,并返回结果 */ public class TestDemo { public static void main(String[] args) { // 静态初始化数组 // 1.静态初始化一个整型数组 int[] arr = {10,20,30,40}; int[] arr2 = null; int[] arr3 = {}; System.out.println(ArrayUtils.toString(arr)); // [10, 20, 30, 40] System.out.println(ArrayUtils.toString(arr2)); // null System.out.println(ArrayUtils.toString(arr3)); // [] // 2.静态初始化一个浮点型数组 double[] arr4 = {16.8,29.3,17.6,15.4}; System.out.println("平均分是:" + ArrayUtils.getAerage(arr4)); // 当前最高分是:29.3 // 当前最低分是:15.4 // 平均分是:17.0006 } } 

三.static应用知识:代码块

静态代码块的作用是什么?

  • 如果要在启动系统时对静态资源进行初始化,则建议使用静态代码块完成数据的初始化操作。

package com.gch.d3_static_code; import java.util.ArrayList; // 先加载类,然后才把mian方法提取到栈内存里面去运行 public class StaticDemo1 { // 静态成员:与类一起加载,只在内存中存储1份 public static String schoolName; public static ArrayList<String> cards = new ArrayList<>(); / 静态代码块:由static修饰,属于类,与类一起优先加载一次,自动触发只执行一次 作用:可以用于初始化静态资源。 */ static{ System.out.println("-------静态代码块被触发执行了!------"); schoolName = "西安电子科技大学"; cards.add("3"); } public static void main(String[] args) { // 目标:先理解静态代码块 System.out.println("-----main方法执行!"); System.out.println(schoolName); } } 

讯享网package com.gch.d3_static_code; public class StaticDemo2 { // 实例成员 private String name; // 无参构造器 public StaticDemo2(){ System.out.println("----无参构造器被触发执行----"); } / 构造代码块/实例代码块:无static修饰,属于对象,每次创建对象时,都会触发执行一次,并且在构造器执行前执行 构造代码块/实例代码块:每次创建对象,调用构造器执行时,都会执行该代码块中的代码,并且在构造器执行前执行 构造代码块/实例代码块:不属于类,不会与类一起加载 构造代码块/实力代码块的作用:初始化实例资源 */ { // name = "张三"; System.out.println("----实例代码块被触发执行----"); } public static void main(String[] args) { // 目标:理解构造代码块(实例代码块),了解,见得少 StaticDemo2 s1 = new StaticDemo2(); System.out.println(s1.name); StaticDemo2 s2 = new StaticDemo2(); System.out.println(s2.name); } } 

 

package com.gch.d3_static_code; import java.util.ArrayList; public class StaticTest3 { / 1.定义一个静态的集合,这样这个集合只加载一次,因为当前房间只需要一副牌 */ public static ArrayList<String> cards = new ArrayList<>(); / 2.在程序真正执行main方法前,把54张牌放进去,后续游戏可以直接使用了 静态代码块:初始化静态资源 */ static{ // 3.正式做牌,放到集合里面去 // a.定义一个数组存储全部点数:类型确定了,个数确定了 // 静态初始化数组 String[] sizes = {"3","4","5","6","7","8","10","J","Q","K","A","2"}; // b.定义一个数组存储全部的花色,类型确定了,个数确定了 String[] colors = {"♠","♥","♦","♣"}; // c.遍历点数 for(int i = 0;i < sizes.length;i++){ // sizes[i] // d.遍历花色 for(int j = 0;j < colors.length;j++){ // colors[j] // 一张牌 String card = sizes[i] + colors[j]; cards.add(card); } } // e.单独加入大小王 cards.add("大🃏"); cards.add("小🃏"); } public static void main(String[] args) { // 目标:模拟游戏启动前,初始化54张牌数据 System.out.println("新牌:" + cards); } } 

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

 单例解决保证一个类对外只产生一个对象

 单例的实现方式很多

  • 饿汉单例模式:饿汉单例模式是在获取对象前,对象已经准备好了,所以饿汉单例模式天生就是线程安全的!
  • 懒汉单例模式:一开始不去创建对象,等到要用这个实例对象的时候,才判断它存不存在真正的实例对象,如果存在我们就返回,不存在才去创建一个对象,那么这样,就可能会有问题,在多个线程都判断它都没有实例对象的时候,可能多个线程会多次创建这个实例对象!
  • ....
  • ....

讯享网package com.gch.d4_static_singleinstance; / * 使用饿汉单例实现单例类 */ public class SingleInstance { / * 饿汉单例是在获取对象前,对象已经提前准备好了一个 * 2.这个对象只能是一个,所以定义静态成员变量记住,因为静态成员变量在内存中只加载一次 */ public static final SingleInstance INSTANCE = new SingleInstance(); / * 1.必须把构造器私有化 */ private SingleInstance() { // 防止通过反射创建新的实例 if (INSTANCE != null) { throw new RuntimeException("单例对象不能重复创建~!"); } } } 
package com.gch.d4_static_singleinstance; public class Test1 { public static void main(String[] args) { // 目标:理解饿汉单例的设计步骤 SingleInstance s1 = SingleInstance.instance; SingleInstance s2 = SingleInstance.instance; System.out.println(s1 == s2); // true,表明s1、s2是同一个对象 } } 

讯享网package com.gch.d4_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.gch.d4_static_singleinstance; public class Test2 { public static void main(String[] args) { // 目标:掌握懒汉单例的设计,理解其思想 SingleInstance2 s1 = SingleInstance2.getInstance(); SingleInstance2 s2 = SingleInstance2.getInstance(); System.out.println(s1); System.out.println(s2); System.out.println(s1 == s2); // true } } 

小讯
上一篇 2025-01-04 16:24
下一篇 2025-01-29 13:05

相关推荐

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容,请联系我们,一经查实,本站将立刻删除。
如需转载请保留出处:https://51itzy.com/kjqy/11431.html