【Java基础教程】(十一)面向对象篇 · 第五讲:透彻讲解Java中的static关键字及代码块——静态属性、静态方法和普通代码块、构造块、静态块的使用~

Java基础教程之面向对象 · 第五讲

  • 本节学习目标
  • 1️⃣ static 关键字
    • 1.1 static定义静态属性
    • 1.2 static定义静态方法
    • 1.3 主方法
    • 1.4 实际应用
      • 功能一:实现类实例化对象个数的统计
      • 功能二: 实现属性的自动设置
  • 2️⃣ 代码块
    • 2.1 普通代码块
    • 2.2 构造块
    • 2.3 静态块
  • 🌾 总结

在这里插入图片描述

本节学习目标

  • 掌握关键字static的特征以及使用;
  • 掌握代码块的概念及使用;

1️⃣ static 关键字

相信大家对于 static关键字并不陌生,从第一个Java程序到现在,我们一直都可以看到这个关键字的使用(例如 public static void main(String args[]) )。在Java中,static关键字可以用于定义属性和方法。接下来将为大家详细讲解 static关键字的使用。

1.1 static定义静态属性

一个类的主要组成就是属性和方法(构造方法与普通方法),而每一个对象都分别拥有各自的属性内容(不同对象的属性保存在不同的堆内存中),如果类中的某个属性希望定义为公共属性(所有对象都可以使用的属性),则可以在声明属性前加上 static关键字。

//	范例 1: 定义程序
class Book{ private	String title;	//普通属性private double price;static String pub = "清华大学出版社"; 	//定义一个描述出版社信息的属性,为操作方便,暂不使用 private封装public Book(String title, double price){this.title = title;this.price = price;}public String getInfo(){return "图书名称:"+this.title+",价格:"+this.price+",出版社:"+this.pub;}
}public class TestDemo  {public static void main(String args[]){Book ba = new Book("Java开发",10.2);   		//实例化Book 类对象Book bb = new Book("Android 开发",11.2);Book bc = new Book("Oracle开发",12.2);ba.pub = "北京大学出版社";               //修改了一个属性的内容System.out.println(ba.getInfo());System.out.println(bb.getInfo());System.out.printin(bc.getlnfo());}
}     

程序执行结果:

图书名称:Java 开发,价格:10.2,出版社:北京大学出版社
图书名称:Android 开发,价格:11.2,出版社:北京大学出版社
图书名称:Oracle开发,价格:12.2,出版社: 北京大学出版社

此程序在定义 Book 类的时候提供了一个 static 属性,而这个属性将成为公共属性,也就是说有任何一个对象修改了此属性的内容都将影响其他对象。此程序在主方法中利用 ba 对象修改了 pub 属性, 所以其他两个对象的 pub 内容都发生了改变。此程序的内存关系如下图所示。

在这里插入图片描述

既然 static 是一个公共属性的概念,那么如果只是简单地由一个对象去修改 static 属性的做法显然很不合适,最好的做法是由所有对象的公共代表来进行访问,这个公共代表就是类。所以利用 static 定义的属性是可以由类名称直接调用的:

Book.pub = "北京大学出版社";

此时 Book 类中定义了 pubstatic 属性(没有封装),所以可以利用 “Book” 类直接调用 staticpub 属性。

static 属性与非 static 属性还有一个最大的区别,所有的非 static 属性必须产生实例化对象才可以访问,但是 static 属性不受实例化对象的控制,也就是说,在没有实例化对象产生的情况下,依然可以直接使用 static 属性。

//	范例 2: 在没有实例化对象产生时直接操作 static 属性
public class TestDemo{public static void main(String args[]){System.out.println(Book.pub);	//在没有实例化对象的情况下直接输出属性内容Book.pub = "北京大学出版社";	//修改static属性内容Book ba = new Book("Java开发",10.9);	//实例化Book 类对象System.out.println(ba.getInfo());	//输出Book 类对象信息}
}

程序执行结果:

清华大学出版社
图书名称: Java开发,价格:10.9,出版社:北京大学出版社

通过本程序可以发现,在没有实例化对象产生时,依然可以直接利用 ·Book 类输出或设置 static 属性的内容,并且此修改的结果将影响以后的 Book 类对象。

需要注意的是,在编写代码时,static 定义的属性出现几率并不是很高,一般只有在描述共享属性概念或者是不受实例化对象限制的属性时才会使用 static 定义属性,而大部分情况下依然都使用非static属性。

在实际应用中,选择是否使用 static属性主要取决于需求和设计考虑。

当一个属性需要被所有该类的实例对象所共享并且对整个类来说具有全局性质时,可以考虑使用 static 属性。这样的属性可以被所有实例对象访问和修改,并且只占用一份内存空间,节省了资源。典型的例子是用于计数或跟踪某个类的实例数量的属性。

而如果一个属性是独立于每个实例对象的,每个实例都应该有自己的值,那么该属性应该是非static的。每个对象对于非static属性都会拥有自己的副本,它们的取值可以相互独立。典型的例子是每个对象的名称、颜色等个性化属性。

1.2 static定义静态方法

在定义类的普通方法时可以使用 static 进行定义,很明显使用 static 定义的方法也可以在没有实例化对象产生的情况下由类名称直接进行调用。

//	范例 3: 使用 static 定义方法
class Book  {  	//描述的是同一个出版社的信息private String title;private double price;private static String pub = "清华大学出版社";        //定义一个描述出版社信息的属性public Book(String title, double price){this.title = title;this.price = price;}public static void setPub(String p){		//定义static方法可以由类名称直接调用pub = p;}public String getInfo(){return "图书名称:"+this.title+",价格:"+this.price+",出版社:"+this.pub;}
}public class TestDemo{public static void main(String args[]){Book.setPub("北京大学出版社");		//在没有对象产生的时候进行调用Book ba = new Book("Java 开发",10.2);	//实例化Book 类对象Book bb = new Book("Android 开发",11.2); Book bc = new Book("Oracle 开发",12.2);System.out.println(ba.getInfo());System.out.println(bb.getInfo());System.out.println(bc.getInfo());}
}

程序执行结果:

图书名称:Java 开发,价格:10.2,出版社:北京大学出版社
图书名称:Android开发,价格:11.2,出版社:北京大学出版社
图书名称:Oracle开发,价格:12.2,出版社:北京大学出版社

此程序对 Book 类中的 pub 属性使用了private封装,所以专门定义了一个 setPub()static 方法,这样就可以通过类名称直接调用 setPub() 方法来修改属性内容。

从上面讲解可以发现 static 定义的属性和方法都不受实例化对象的控制,也就是说都属于独立类的功能。但是这个时候会出现一个问题:此时类中的方法就变为 static 方法和非 static 方法两组,这两组方法间的访问也将受到如下限制。

  • static 方法不能直接访问非 static 属性或方法,只能调用 static 属性或方法;
  • static 方法可以访问 static的属性或方法,不受任何的限制。

之所以会存在上述操作限制,原因有以下两点。

  • 所有的非static定义的结构,必须在类已经明确产生实例化对象时才会分配堆空间,才可以使用;
  • 所有的 static定义的结构,不受实例化对象的控制,即可以在没有实例化对象的时候访问。

那么类中可以定义static方法,也可以定义非static方法,除了能用类名称直接访问外, 还有什么情况是需要考虑static方法呢?

  1. 工具方法或辅助功能:如果某个方法在整个应用程序中都具有通用的功能,并且不需要访问非静态成员(例如非静态属性),那么将该方法定义为static可以更加清晰地表示其作用和无需依赖于对象状态。

  2. 纯函数:纯函数是指在相同的输入条件下,始终产生相同的输出结果,并且不产生副作用的函数。这样的方法可以被定义为静态方法,因为它们不需要依赖于任何特定的实例状态,只根据参数传递的数据进行计算。

  3. 辅助工具类方法:如果一个方法提供一些通用的、与业务无关的操作,比如数据转换、校验等,而且这些方法不需要访问或修改类的实例属性,那么可以将它们定义为静态方法。

需要注意的是,在使用static方法时要小心滥用。如果方法需要访问或修改实例属性,或者需要多态性行为,那么它可能更适合定义为非静态方法,以便让每个实例都能够独立地执行方法。所以在选择是否使用 static方法时,要权衡需求、设计考虑和面向对象的原则。

//	范例 4:定义一个数学的加法操作
class MyMath {     	//数学操作类,类中没有属性public static int add(int x, int y){ 	//只是一个加法操作return x+y;}
}
public class TestDemo {public static void main(String args[]){System.out.println(MyMath.add(10, 20));//直接调用}
}

程序执行结果:

30

此时 MyMath 类没有属性,产生对象完全没有任何意义,所以就使用 static关键字定义方法。

1.3 主方法

Java 语言最大的特点就在于主方法,因为在 Java 中的主方法的组成单元很多。下面就概括一下前面所学知识,来介绍每一个组成单元的含义。

public static void main(String args[]){...}
  • public:主方法是程序的开始,所以这个方法对任何操作都一定是可见的,既然是可见的就必须使用 public (公共)。(权限修饰符这块还没介绍到,将在后面文章中详细介绍)
  • static:此方法由类名称调用;
  • void:主方法是一切执行的开始点,既然是所有的开头,就没有返回值;
  • main:是一个系统规定好的方法名称,不能修改;
  • String args[]:指的程序运行时传递的参数,格式为: “java 类名称 参数 参数...”。
//	范例 5: 得到参数
public class TestDemo {public static void main(String args[]){for(int x=0; x<args.length; x++){ //循环输出参数System.out.println(args[x]);}}
}

程序执行输入:java TestDemo hello world xiaoshan
程序执行结果:

hello
world  
xiaoshan

通过本程序可以发现,如果要为程序运行输入参数,只需要在执行时配置即可,不同的参数之间使用空格分隔,而如果配置的参数本身就包含空格,则可以使用"""声明,例如: java TestDemo "Hello world" "Hello everybody"

1.4 实际应用

通过之前的讲解,可以发现 static关键字具备如下特点:

  • 不管有多少个对象,都使用同一个 static 属性;
  • 使用 static方法可以避免实例化对象调用方法的限制。

下面依照这两个特点来研究 static 的实际应用。

功能一:实现类实例化对象个数的统计

希望每当实例化一个类对象时都可以打印一个信息:产生第 x 个实例化对象。

因为只要是新的实例化对象产生了,就一定会去调用类中的构造方法,所以可以在构造方法里面增加一个统计数据的操作,每当新对象产生后统计的内容就自增一个。

//	范例 6: 实现类实例化对象个数的统计
class Book {private static int num=0;	//保存统计个数public Book(){		//只要是新对象实例化就执行此构造num++;			//保存个数自增System.out.println("这是第"+ num+" 个产生的对象!");}
}public class TestDemo{public static void main(String args[]){new Book();new Book();new Book();}
}

程序执行结果:

这是第1个产生的对象!
这是第2个产生的对象!
这是第3个产生的对象!

此程序在构造方法中进行了实例化对象个数的统计操作,所以每当调用构造方法时都会相应地进行统计个数的修改。

在本程序中构造方法主要是创建新对象时调用的,所以可以通过构造方法实现对象个数的统计,但是当某一个对象不再使用时,应该进行实例化对象个数的减少,而这一执行操作,可以通过学习后续文章中将会介绍到的 finalize() 方法后实现。

功能二: 实现属性的自动设置

例如,某一个类有一个无参构造方法, 一个有参构造方法。有参构造的主要目的是传递一个 title 属性,但是希望不管调用的是无参的还是有参的构造方法,都可以为 title 设置内容(尽量不使用重复的内容设置)。

//	范例 7: 实现属性的自动设置
class Book{private String title;		//title 属性private static int num = 0;	//自动命名索引号public Book(){	//没有设置title属性内容this("NOTITLE-" + num++);	//自动命名}public Book(String title){	//设置title 属性内容this.title = title;}public String getTitle(){return this.title;}
}public class TestDemo {public static void main(String args[]){System.out.printIn(new Book("Java").getTitle());System.out.printIn(new Book().getTitle());System.out.println(new Book().getTitle());}
}

程序执行结果:

Java
NOTITLE-0
NOTITLE-1

此程序提供了两个构造方法,如果调用有参构造方法则会将指定的内容赋值给 title 属性,而如果调用的是无参构造, title 属性会采用自动命名的方式配置,所以就算是没有设置 title 属性的内容,最终的结果也不会是 null

2️⃣ 代码块

在程序编写中可以直接使用“{}”定义一段语句,根据此部分定义的位置以及声明的关键字的不同,代码块一共可以分为4种:普通代码块、构造块、静态块、同步代码块(用于多线程编程)。

需要注意的是,代码块本身有许多破坏程序结构的操作,所以在编写实际代码的过程中,不太建议使用代码块。这里只是对这个语法结构做一个大致介绍。

2.1 普通代码块

如果一个代码块写在方法里,就称它为普通代码块。

//	范例 8: 编写普通代码块
public class TestDemo{public static void main(String args[]){// 普通代码块{int num = 10;	//局部变量System.out.println("num = " + num);}int num = 100;		//全局变量System.out.println("num = " + num);}
}

程序执行结果:

num = 10
num = 100

此程序首先在普通代码块中定义了一个 num 变量,然后在普通代码块的外部定义了一个 num 变量。由于第一个 num 变量定义在代码块中,所以是个局部变量;第二个 num 变量定义在普通代码块外,所以相对而言就属于全局变量,这两个变量彼此不会互相影响。 一般而言普通代码块可以实现较大程序的分隔,这样可以更好地避免重名变量的问题。

2.2 构造块

如果将一个代码块写在一个类里,这个代码块就称为构造块。

//	范例 9: 定义构造块
class Book {public Book(){	//构造方法System.out.println("【A】Book类的构造方法");}//将代码块写在类里,所以为构造块 {System.out.println("【B】Book类中的构造块");}
}	
public class TestDemo {public static void main(String args[]){ new Book();	//实例化类对象new Book();}
}

程序执行结果:

【B】Book类中的构造块
【A】Book类的构造方法
【B】Book类中的构造块
【A】Book类的构造方法

此程序为了说明问题,特别将构造方法放在构造块之前定义,可以发现代码的结构与顺序无关。同时也可以发现,构造块在每一次实例化类对象时都会被调用,而且优于构造方法执行。

2.3 静态块

如果一个代码块使用 static 进行定义,就称其为静态块,静态块有时需要分为两种情况。

//	范例 10: 在非主类中使用
class Book {public Book(){		//构造方法System.out.println("【A】Book类的构造方法");}//将代码块写在类里,所以为构造块 {System.out.println("【B】Book类中的构造块");}//定义静态块static{	System.out.println("【C】Book类中的静态块");}
}public class TestDemo {public static void main(String args[]){new Book();	//实例化类对象new Book();}
}

程序执行结果:

【C】Book 类中的静态块
【B】Book 类中的构造块
【A】Book 类的构造方法
【B】Book 类中的构造块
【A】Book 类的构造方法

此程序在 Book 类中增加了静态块的定义,通过运行结果可以发现当有多个实例化对象产生时,静态块会优先调用,而且只调用一次。静态块的主要作用一般可以为 static 属性初始化。

//	范例 11: 利用静态块为 static 属性初始化
class Book{static String msg;	// static 属性,暂不封装public Book(){		//构造方法System.out.println("【A】Book类的构造方法");}//将代码块写在类里,所以为构造块{System.out.println("【B】Book类中的构造块");}static { 			//定义静态块msg = "Hello".substring(0,2);System.out.println("【C】Book类中的静态块");}
}public class TestDemo {public static void main(String args[]){new Book();   	//实例化类对象new Book();       System.out.println(Book.msg);}
}

程序执行结果:

【C】Book 类中的静态块
【B】Book 类中的构造块
【A】Book 类的构造方法
【B】Book 类中的构造块
【A】Book 类的构造方法
He

此程序利用静态块为 static 属性进行赋值操作,但是这样做一般意义不大,所以有个了解即可。

//	范例 12: 在主类中定义静态块
public class TestDemo {public static void main(String args[]){System.out.println("Hello World!");}static{   	//静态块System.out.println("更多文章请访问:https://blog.csdn.net/LVSONGTAO1225");}
}

程序执行结果:

更多文章请访问:https://blog.csdn.net/LVSONGTAO1225
Hello World!

通过本程序的执行可以发现,静态块将优先于主方法执行。

🌾 总结

本文详细介绍了Java中的static关键字以及代码块的使用。通过学习static关键字,我们了解到它可以用于定义静态属性和静态方法。静态属性是类级别的变量,在整个类中只有一份副本,并且被所有实例对象所共享。静态方法则是类级别的方法,可以通过类名直接调用,而无需创建对象实例。

同时,我们也探索了代码块的不同类型:普通代码块、构造块和静态块。普通代码块用于在方法中限定变量的作用域,构造块在创建对象时执行,用于初始化对象的特定属性,而静态块在类加载时执行,常用于初始化静态成员和执行其他预处理操作。

在实际应用中,static关键字和代码块具有很多用途。静态成员可以用来跟踪全局状态或提供公用的工具方法;静态方法可以在不创建对象实例的情况下实现某些功能;代码块则可以用来进行额外的初始化操作或执行一些特定的逻辑。


温习回顾上一篇(点击跳转)《【Java基础教程】(十)面向对象篇 · 第四讲:解析Java中的this关键字,引用传递印象加强:理解与实践~》

继续阅读下一篇(点击跳转)《【Java基础教程】(十二)面向对象篇 · 第六讲:深入剖析内部类:成员内部类、局部内部类、匿名内部类及静态内部类的特征,外部类及其他类访问内部类的特征~》

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/17868.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

由于找不到vcomp100.dll,无法继续执行代码,解决方法

为什么会由于找不到vcomp100.dll,无法继续执行代码问题呢&#xff1f; 文件被误删除&#xff1a;有时候&#xff0c;在进行系统清理或卸载应用程序时&#xff0c;可能会不小心删除了vcomp100.dll文件。如果某个程序依赖于该文件&#xff0c;并且文件被删除&#xff0c;那么该程…

详解Hystrix

目录 1.微服务中的容错 1.1.服务雪崩 1.2.解决办法 2.hystrix 2.1.概述 2.2.项目结构及依赖 2.3.代码示例 2.3.1.注册中心 2.3.2.服务调用者 2.3.3.服务提供者 2.4.服务降级 2.4.1.单点响应 2.4.2.默认响应 2.4.3.前置响应 2.5.服务熔断 2.5.1.概述 2.5.2.使用…

【数据分析 - 基础入门之pandas篇②】- pandas数据结构——Series

文章目录 前言一、Series的创建1.1 列表创建1.2 NumPy数组创建1.3 字典创建 二、Series索引2.1 显式索引2.2 隐式索引 三、Series切片2.1 显式切片2.2 隐式切片 四、Series基本属性和方法4.1 属性4.2 方法4.3 案例——使用 bool 值去除空值 五、Series运算六、Series多层行索引…

ChatGPT潮落 资金逃离AI概念股

ChatGPT访问量首次出现负增长&#xff0c;寒气传导到证券市场。 上半年经历暴涨的一众AI概念股偃旗息鼓&#xff0c;蓝色光标、三六零、昆仑万维等知名个股均较高点跌超30%。微软、英伟达也未能幸免&#xff0c;同样有不同程度回调。 回顾这波过山车般的市场表现&#xff0c;…

LVS+Keepalived负载均衡高可用群集

目录 一、Keepalived高可用详解 1.应用场景 2.介绍和原理简介 3.主要模块和作用 二、LVSkeepalived配置实例&#xff08;抢占模式&#xff09; 1.配置NFS共享存储器 2.配置节点web服务&#xff08;两台的配置相同&#xff09; 3.配置主备LVSkeepalived负载调度器 三、非…

相机- yolo训练集 环境搭建

一、环境准备 运行cmd执行python --version 检查是否安装成功 安装pip&#xff0c;打开运行指令 python -m ensurepip --upgrade 打开官网&#xff0c;下载get_pip.py 运行cmd 运行指令python get-pip.py 运行cmd 运行指令 pip --version 显示pip版本即安装成功 根据上面获…

111、基于51单片机的电磁感应无线充电系统 手机无线充电器设计(程序+原理图+Proteus仿真+程序流程图+论文参考资料等)

方案选择 单片机的选择 方案一&#xff1a;AT89C52是美国ATMEL公司生产的低电压&#xff0c;高性能CMOS型8位单片机&#xff0c;器件采用ATMEL公司的高密度、非易失性存储技术生产&#xff0c;兼容标准MCS-51指令系统&#xff0c;片内置通用8位中央处理器(CPU)和Flash存储单元…

【LeetCode热题100】打卡第32天:最长连续序列只出现一次的数字单词拆分环形链表

文章目录 【LeetCode热题100】打卡第32天&#xff1a;最长连续序列&只出现一次的数字&单词拆分&环形链表⛅前言 最长连续序列&#x1f512;题目&#x1f511;题解 只出现一次的数字&#x1f512;题目&#x1f511;题解 单词拆分&#x1f512;题目&#x1f511;题解…

mysql管理

目录 一、数据库的组成 1.数据 (Data) 2. 表 3. 数据库 二、数据库系统 1.数据库管理系统(DBMS) 2. 数据库系统&#xff08;DBS&#xff09; 3. DBMS的工作模式 三、数据库系统发展史 1.第一代数据库&#xff08;人工管理&#xff09; 2. 第二代数据库&#xff08…

C++线性表、单链表

概述 在先说链表前&#xff0c;我们先来理清几个概念。 什么是线性表、顺序表和链表&#xff1f;三者有什么关系&#xff1f; 线性表&#xff1a;元素线性排列&#xff0c;在逻辑上具有次序的存储结构。 顺序表&#xff1a;线性表的顺序存储称为线性表。它是用一组地址连续(逻…

Windows server 2012服务器远程桌面登录时出现错误提示:“由于没有远程桌面授权服务器可以提供许可证,远程会话被中断

简单粗暴&#xff1a; Windows server 2012服务器远程桌面登录时出现错误提示&#xff1a;“由于没有远程桌面授权服务器可以提供许可证&#xff0c;远程会话被中断。请跟服务器管理员联系 使用 mstsc /admin /v:目标ip 来强制登录服务器&#xff0c;但只能是管理员身份…

【C++修炼之路】31.异常

每一个不曾起舞的日子都是对生命的辜负 异常 一.C语言传统的处理错误的方式二.C异常概念三.异常的使用3.1 异常的抛出和捕获3.2 异常的重新抛出3.3 异常安全3.4 异常规范 四.自定义异常体系五.C标准库的异常体系六.异常的优缺点 一.C语言传统的处理错误的方式 传统的错误处理机…