【Java基础教程】(十八)包及访问权限篇 · 下:Java编程中的权限控制修饰符、单例设计模式 (Singleton)和多例设计模式的综合探析~

Java基础教程之包及访问权限 · 下

  • 本节学习目标
  • 1️⃣ 访问控制权限
  • 2️⃣ 命名规范
  • 3️⃣ 单例设计模式 (Singleton)
  • 4️⃣ 多例设计模式

在这里插入图片描述

本节学习目标

  • 掌握Java 中的4种访问权限;
  • 掌握Java 语言的命名规范;
  • 掌握单例设计模式与多例设计模式的定义结构;

1️⃣ 访问控制权限

对于封装性,实际上之前只详细讲解了 private, 而封装性如果要想讲解完整,必须结合全部4种访问权限来看,这4种访问权限的定义如下表所示。

范围privatedefaultprotectedpublic
同包的同类中
同包的不同类
不同包的子类
不同包的非子类

对于上表可以简单理解为: private 只能在本类中访问;default 只能在同一个包中访问;protected 可以在不同包的子类中访问;public 为所有类都可以访问。

前面文章中对于 privatedefaultpublic 都已经有所了解,所以本节主要讲解 protected

//	范例 1: 定义 com.xiaoshan.demoa.A 类
package com.xiaoshan.demoa; public class A{protected String info="Hello";//使用 protected权限定义
}
//	范例 2: 定义 com.xiaoshan.demob.B 类,此类继承A 类
package com.xiaoshan.demob;import com.xiaoshan.demoa.A;public class B extends A{    // B是A 不同包的子类public void print(){              //直接访问父类中的protected属性System.out.println("A 类的 info = "+ super.info);}
}

由于B类是A 的子类,所以在B 类中可以直接访问父类中的 protected 权限属性。

//	范例 3: 代码测试
package com.xiaoshan.test;import com.xiaoshan.demob.B;public class Test {public static void main(String args[]){new B().print();}
}

程序执行结果:

A 类的 info = Hello

此程序直接导入了B类 , 而后实例化对象调用 print() 方法,而在 print()方法中利用“super.info” 直接访问了父类中的 protected 权限属性。
而如果要在 com.xiaoshan.test 包中直接利用 Test 主类访问A 中的属性,由于它们不在同一个包下,也不存在继承关系,所以将无法访问。

//	范例 4: 错误的访问
package com.xiaoshan.test;import com.xiaoshan.demoa.A;public class Test {public static void main(String args[]){A a = new A();System.out.println(a.info);		//错误:无法访问}
}

此程序在进行编译时会直接提示用户,infoprotected 权限,所以无法被直接访问。

实际上在给出的4种权限中,有3种权限 ( privatedefaultprotected) 都是对封装的描述,也就是说面向对象的封装性现在才算是真正讲解完整。从实际的开发使用来讲,几乎不会使用到 default 权限,所以真正会使用到的封装概念只有两个权限 privateprotected

对于访问权限,初学者要把握以下两个基本使用原则即可。

  • 属性声明主要使用private权限;
  • 方法声明主要使用public权限。

2️⃣ 命名规范

命名规范的主要特点就是保证程序中类名称或方法等名称的标记明显一些,可是对于 Java 而言,有如下一些固定的命名规范还是需要遵守的。

  • 类名称:每一个单词的开头首字母大写,例如:TestDemo;
  • 变量名称:第一个单词的首字母小写,之后每个单词的首字母大写,例如: studentName;
  • 方法名称:第一个单词的首字母小写,之后每个单词的首字母大写,例如: printInfo();
  • 常量名称:每个字母大写,例如: FLAG;
  • 包名称:所有字母小写,例如:com.xiaoshanjava.util

需要注意以上所给出的5种命名规范,是所有开发人员都应该遵守的,而不同的开发团队也可能会有属于自己的命名规范,对于这些命名规范,在日后从事软件开发的过程中,都应该仔细遵守。

3️⃣ 单例设计模式 (Singleton)

在之前大部分的属性定义时都使用了 private 进行声明,而对于构造方法其实也可以使用 private 声明,则此时的构造方法就被私有化。而构造方法私有化之后会带来哪些问题,以及有什么作用呢?下面就来进行简单的分析。

首先在讲解私有化构造方法操作之前,来观察如下的程序。

//	范例 5: 构造方法非私有化
class Singleton {                 	//定义一个类,此类默认提供无参构造方法public void print(){System.out.println("Hello World.");}
}public class TestDemo{public static void main(String args[])(Singleton inst = null;                          //声明对象inst = new Singleton(;                       //实例化对象inst.print();                                       //调用方法}
}

程序运行结果:

Hello World.

在本程序中, Singleton 类里面存在构造方法 ( 因为如果一个类中没有明确地定义一个构造方法,则会自动生成一个无参的、什么都不做的构造方法) , 所以可以先直接实例化对象,再调用类中提供的 print()方法。下面将构造方法改变一下,即使用 private封装。

//	范例 5: 私有化构造方法
class Singleton{                                       //定义一个类private  Singleton(){                                 //构造方法私有化}public void print(){System.out.println("Hello World.");}
}public class TestDemo {public static void main(String args[]){Singleton inst = null;               //声明对象inst = hew Singletono:           //错误:The constructor Singleton() is not visibleinst.print();                      //调用方法}
}

此程序在实例化 Singleton 类对象时,程序出现了编译错误,因为构造方法被私有化了,无法在外部调用,即无法在外部实例化 Singleton类的对象。

那么现在在保证 Singleton 类中的构造方法不修改不增加,以及 print()方法不修改的情况下,如何操作才可以让类的外部通过实例化对象去调用 print()方法呢?

思考一:使用 private 访问权限定义的操作只能被本类所访问,外部无法调用,现在既然构造方法被私有化,就证明这个类的构造方法只能被本类所调用,即只能在本类中产生本类实例化对象。

//	范例 6: 第一步思考
class Singleton {	//定义一个类Singleton instance = new Singleton();	//在内部实例化本类对象private Singleton(){	//构造方法私有化}public void print(){System.out.println("Hello World.");}
}

思考二: 对于一个类中的普通属性,默认情况下一定要在本类存在实例化对象后才可以进行调用,可是此程序在 Singleton 类的外部无法产生实例化对象,就必须想一个办法,让 Singleton 类中的 instance 属性可以在没有 Singleton 类实例化对象时来进行调用。因此可以使用 static 完成,static 定义的属性特点是由类名称直接调用,并且在没有实例化对象时候可以调用。

//	范例 7: 第二步思考
class Singleton {	//定义一个类static Singleton instance = new Singleton();	//可以由类名称直接访问  private Singleton(){	//构造方法私有化}public void print(){System.out.println("Hello World.");}
}public class TestDemo {public static void main(String args[]){ Singleton inst = null; //声明对象inst = Singleton.instance; //利用“类.static属性”方式取得实例化对象inst.print();	//调用方法 }
}

程序运行结果:

Hello World.

思考三: 类中的全部属性都应该封装,所以上边范例中的 instance 属性也应该进行封装,而封装之后要想取得属性,则要编写 getter方法,只不过这时的 getter 方法应该也由类名称直接调用,定义为 static 型。

//	范例 8: 第三步思考
class Singleton {                	//定义一个类private static Singleton instance = new Singleton();private Singleton(){         	//构造方法私有化}public void print(){System.out.println("Hello World.");}public static Singleton getInstance(){                 //取得本类对象return instance;}
}public class TestDemo(public static void main(String args[]){ Singleton inst = null;			//声明对象inst = Singleton.getInstance();	//利用“类.static方法()”取得实例化对象inst.print();			//调用方法}
}

程序运行结果:

Hello World.

思考四: 这样做的目的是什么?程序中的 instance 属性属于 static 定义,就表示所有 Singleton 类的对象不管有多少个对象声明,其本质都会共同拥有同一个 instance 属性引用,那么既然是同一个,又有什么意义呢?

如果要控制一个类中实例化对象的产生个数,首先要锁定的就是类中的构造方法(使用 private 定义构造方法), 因为在实例化任何新对象时都要使用构造方法,如果构造方法被锁,就自然就无法产生新的实例化对象。

如果要调用类中定义的操作,那么很显然需要一个实例化对象,这时就可以在类的内部使用 static 方式来定义一个公共的对象,并且每一次通过 static 方法返回唯一的一个对象,这样外部不管有多少次调用,最终一个类只能够产生唯一的一个对象,这样的设计就属于单例设计模式 (Singleton)。

不过本程序依然有一个问题,那就是以下代码也可以使用。

//	范例 9: 程序出现的问题
class Singleton {       //定义一个类private static Singleton instance = new Singleton();private Singleton(){  	//构造方法私有化}public void print(){System.out.println("Hello World.");}public static Singleton getInstance(){	// 取得本类对象   instance = new Singleton();	//重新实例化对象return instance;}
}

此程序中操作语法没有错误,也不需要考虑是否有意义,现在的代码也允许这样做,而这样做会发现之前表示唯一一个实例化对象的所有努力就白费了。因此,必须想办法废除这种做法,于是需要在定义 instance 的时候增加一个 final 关键字。

//	范例 10: 一个完整的单例模式的程序 
class Singleton {                 	//定义一个类private final static Singleton instance = new Singleton();private Singleton(){        	//构造方法私有化}public void print(){System.out.println("Hello World.");}public static Singleton getInstance(){	//取得本类对象return instance;}
}public class TestDemo{public static void main(String args[]){ Singleton inst = null;	//声明对象inst =  Singleton.getInstance(); 	//利用“类.static方法()”取得实例化对象inst.print();		//调用方法}
}

程序运行结果:

Hello World.

在使用 Singleton 类时,不管代码如何操作,也永远只会存在唯一的一个 Singleton 类的实例化对象,而这样的代码,在设计模式上就称为单例设计模式(Singleton)。

4️⃣ 多例设计模式

单例设计模式只留下一个类的一个实例化对象,而多例设计模式,会定义出多个对象。

例如:定义一个表示星期几的操作类,这个类的对象只能有7个实例化对象(星期一 ~星期日);定义一个表示性别的类,只能有2个实例化对象(男、女);定义一个表示颜色基色的操作类,只能有3个实例化对象(红、绿、蓝)。

这些情况下,这样的类就不应该由用户无限制地去创造实例化对象,应该只使用有限的几个,这个就属于多例设计。不管是单例设计还是多例设计,有一个核心不可动摇,即构造方法私有化。

//	范例 11: 定义一个表示性别的类
package com.xiaoshan.demo;class Sex{private String title;private static final Sex MALE = new Sex("男");private static final Sex FEMALE = new Sex("女");private Sex(String title){		//构造私有化this.title = title;}public String toString(){return this.title;}public static Sex getInstance(int ch){	//返回实例化对象switch (ch){case 1:return MALE;case 2:return FEMALE;default:return;}}
}public class TestDemo  {public static void main(String args[]){Sex sex = Sex.getInstance(2);System.out.println(sex);}
}

程序执行结果:

此程序首先定义了一个描述性别的多例程序类,并且将其构造方法封装,然后利用 getInstance() 方法,接收指定编号后返回一个实例化好的Sex 类对象。

范例11的代码利用数字编号来取得了一个 Sex 类的对象,有朋友可能觉得这样做表示的概念不明确,那么为了更加明确要取得对象类型,可以引入一个接口进行说明。

//	范例 12: 利用接口标记对象内容
interface Choose {public int MAN = 1;		//描述数字public int WOMAN = 2;		//描述数字
}public class TestDemo  {public static void main(String args[]){	//利用接口标记内容取得对象Sex sex = Sex.getInstance(Choose.MAM); System.out.println(sex);}
}

此程序如果要取得指定的 Sex 类对象,可以利用接口中定义的全局常量(实际上也可以在Sex 类中定义一些全局常量)来进行判断。这样的做法是一种标准做法,但是这样做有一些复杂,所以利用字符串直接判断会更加简单一些。

在 JDK 1.7 之前, switch 只能支持对 intchar 类型进行判断,正因为如果纯粹是数字或字符意义不明确,所以增加了String 的支持。

//	范例 13: 对取得Sex 类对象进行修改
package com.xiaoshan.demo;class Sex{private String title;private static final Sex MALE = new Sex("男");private static final Sex FEMALE = new Sex("女");private Sex(String title){		//构造私有化this.title = title;}public String toString(){return this.title;}public static Sex getInstance(String ch){switch (ch){               	//利用字符串判断case "man":return MALE;case "woman":return FEMALE;default:return null;}}
}public class TestDemo {public static void main(String args[]){Sex sex = Sex.getInstance("man");System.out.println(sex);}
}

程序执行结果:

此程序直接使用 String 作为 switch 的判断条件,这样在取得实例化对象时就可以利用字符串来描述对象名字,这一点要比直接使用数字更加方便。


温习回顾上一篇(点击跳转)《【Java基础教程】(十七)包及访问权限篇 · 上:包的定义及导入、常用系统包概览,javac、java和 jar命令的作用,package和 import关键字的应用~》

继续阅读下一篇(点击跳转)《【Java基础教程】(十九)异常捕获处理篇 · 上:异常的概念及处理流程解析,try、catch、finally、throws、throw的作用,RuntimeException类介绍~》

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

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

相关文章

界面控件DevExpress WPF数据编辑器组件,让数据处理更灵活!(二)

界面控件DevExpress WPF编辑器库可以帮助用户提供直观的用户体验,具有无与伦比的运行时选项和灵活性。WPF数据编辑器提供了全面的掩码和数据验证支持,可以独立使用,也可以作为容器控件(如DevExpress WPF Grid和WPF TreeList)中的单元格编辑器…

【Kubernetes部署篇】ingress-nginx高可用架构实施部署

文章目录 一、环境说明二、实施过程1、部署Ingress Controller2、安装并配置Nginx3、安装并配置Keepalived3、测试keepalived主备切换 三、创建Ingress规则,测试七层转发 一、环境说明 1、环境说明: IP地址主机名称备注16.32.15.201node-1K8S节点16.32…

共享汽车管理系统nodejs+vue

语言 node.js 框架:Express 前端:Vue.js 数据库:mysql 数据库工具:Navicat 开发软件:VScode 前端nodejsvueelementui, 共享汽车管理系统的系统管理员可以管理用户,可以对用户信息修改删除以及查询操作。具体界面的展…

微信小程序02

组件 组件生命周期 小程序组件生命周期,写在lifetimes中: created : 当组件实例刚刚被创建,,不能调用 this.setData()attached : 组件实例进入 页面节点树时 执行detached: 组件实例 从 页面…

Django项目开发快速入门

Django项目开发快速入门 生成Django项目编写module后台管理系统admin自定义管理页面视图函数使用Django模板 生成Django项目 现在cmd中使用命令安装Django框架 pip install django3.2使用命令生成项目 django-admin startproject DjStore使用命令生成应用 python .\manage.…

Redis应用(2)——Redis的项目应用(一):验证码 ---> UUID到雪花ID JMeter高并发测试 下载安装使用

目录 引出Redis的项目应用(一):验证码1.整体流程2.雪花ID1)UUID(Universally Unique Identifier,通用唯一识别码)2)Twitter 的雪花算法(SnowFlake) 雪花ID优缺…

【Java】一个简单的接口例子(帮助理解接口+多态)

要求: 请实现笔记本电脑使用USB鼠标、USB键盘的例子 1. USB 接口:包含打开设备、关闭设备功能 2. 笔记本类:包含开机功能、关机功能、使用 USB 设备功能 3. 鼠标类:实现 USB 接口,并具备点击功能 4. 键盘类&am…

磁盘分区形式MBR与GPT介绍

磁盘分区形式MBR与GPT介绍 磁盘分区形式有两种: 1、MBR(主启动记录)形式,它是存在于磁盘驱动器开始部分的一个特殊的启动扇区; 2、GPT(GUID分区表)形式,它是一种使用UEFI启动的磁盘…

C#使用Linq和Loop计算集合的平均值、方差【标准差】

方差【标准差】 标准差公式是一种数学公式。标准差也被称为标准偏差,或者实验标准差,公式如下所示: 样本标准差方差的算术平方根ssqrt(((x1-x)^2 (x2-x)^2 ......(xn-x)^2)/n) 总体标准差σsqrt(((x1-x)^2 (x2-x)^2 ......(xn-x)^2)/n ) …

❤️创意网页:抖音汉字鬼抓人小游戏复刻——附带外挂(“鬼鬼定身术”和“鬼鬼消失术”)坚持60秒轻轻松松(●‘◡‘●)

✨博主:命运之光 🌸专栏:Python星辰秘典 🐳专栏:web开发(简单好用又好看) ❤️专栏:Java经典程序设计 ☀️博主的其他文章:点击进入博主的主页 前言:欢迎踏入…

OpenCv之图像形态学

目录 一、形态学 二、图像全局二值化 三、自适应阈值二值化 四、腐蚀操作 五、获取形态学卷积核 六、膨胀操作 七、开运算 八、闭运算 一、形态学 定义: 指一系列处理图像形状特征的图像处理技术形态学的基本思想是利用一种特殊的结构元(本质上就是卷积核)来测量或提取输…

Flink简介及部署模式

文章目录 1、Flink简介2、Flink部署2.1 本地模式2.1 Standalone模式部署2.2 Standalone模式下的高可用2.3 Yarn模式Yarn模式的高可用配置:yarn模式中三种子模式的区别: 3、并行度4、提交命令执行指定任务Application Mode VS yarn per-job 5、注意事项5、…

4.1 Bootstrap UI 编辑器

文章目录 1. Bootstrap Magic2. BootSwatchr3. Bootstrap Live Editor4. Fancy Boot5. Style Bootstrap6. Lavish7. Bootstrap ThemeRoller8. LayoutIt!9. Pingendo10. Kickstrap11. Bootply12. X-editable13. Jetstrap14. DivShot15. PaintStrap 以下是 15 款最好的 Bootstrap…

ffplay播放器剖析(5)----视频输出剖析

文章目录 1.视频输出模块1.1 视频输出初始化1.1.1 视频输出初始化主要流程1.1.2 calculate_display_rect初始化显示窗口大小 1.2 视频输出逻辑1.2.1 event_loop开始处理SDL事件1.2.2 video_refresh1.2.2.1 计算上一帧显示时长,判断是否还要继续上一帧1.2.2.2 估算当前帧显示时长…

笔记本电脑的电池健康:确保长时间使用和优异性能的关键

笔记本电脑已经成为我们日常生活中不可或缺的工具,无论是办公、学习还是娱乐,我们都依赖着它的便携性和高效性能。而在所有的硬件组件中,电池健康被认为是确保长时间使用和良好性能的关键因素之一。一块健康的电池不仅能提供持久的续航时间&a…

CHI协议保序之Compack保序

一致性系统中,使用三种保序方式; Completion ack response ⭕Completion acknowledgment: □ 该域段主要是用来, □ 决定 RN 发送的 trans,与其他 RN 发送的命令产生的 SNP 之间的顺序; …

MySQL存储过程——系统变量

1.存储过程中的变量 1.1 查看系统变量 查看所有的系统变量 show variables;查看会话级别的系统变量 show session variables;查看会话和auto相关的变量 show session variables like auto%;查看全局的和auto相关变量 show global variables like auto%;查看某一…

R语言贝叶斯METROPOLIS-HASTINGS GIBBS 吉布斯采样器估计变点指数分布分析泊松过程车站等待时间...

原文链接:http://tecdat.cn/?p26578 指数分布是泊松过程中事件之间时间的概率分布,因此它用于预测到下一个事件的等待时间,例如,您需要在公共汽车站等待的时间,直到下一班车到了(点击文末“阅读原文”获取…

ext4 - delay allocation数据结构

概述 延迟分配delay allocation是ext4非常重要的特性,启用该特性write系统将用户空间buffer写入内存page cache中即返回,此时也不会真正进行磁盘block分配,而是延迟到磁盘回写时(比如dirty ratio达到一定值,定时刷新&…

【华为c# OD机考参考答案】01---IPv4地址转换成整数

题目 1、题目 01---IPv4地址转换成整数2、解图思路 1、IP地址转为二进制 2、二进制转十进制 3、注意事项 1、IP地址的范围判断 2、空字符串判断 3、非法字符判断 4、考点 1、string的split 、convert等相关用法 2、正则表达式 3、进制转换 4、理解32位整数的意思 5、代码 判…