【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基础教程】(十九)异常处理篇 · 上:~》

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

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

相关文章

Java处理doc类型的Word文档转换成html(按顺序保留格式+图片)

最新有个新需求,就是doc文档转换html内容倒不是很难,给大家分享一下,总体思路就是按doc转html的思路来走,唯一缺点是不会自动转换图片,图片是要手动转成base64,默认是有html、body、head、meta等等标签&…

2023四大进销存软件推荐,第一款适合中小商户使用!

在当今竞争激烈的商业环境中,企业或商户迫切需要使用进销存管理软件,来优化库存控制、提高运营效率、降低成本,并加强与供应链合作伙伴之间的协作和沟通。 为了帮助企业选择适合自己需求的进销存软件,我们特别整理了2023年市面上比…

【Java虚拟机学习1】JVM运行时数据区

JVM运行时数据区 一、前言 我们知道Java程序是运行在JVM(Java虚拟机)上的,Java程序运行时会占用一定的内存,在虚拟机自动管理机制的帮助下,不再需要为每一个new操作去写配对的delete/free代码,不容易出现…

第一次用用Opencv进行图像处理

2023.7.06更新 codeblocks安装opencv 直接放参考链接,完成安装该步骤来,简单高效! 安装教程链接 有一个问题就是第一次安装完成后运行时会报确实某些ddl的错误,关机重启就好啦! 尝试运行 ddl的错误解决后可以用以…

行业追踪,2023-07-18,减速器,汽车零部件是重点关注板块,随时开启

自动复盘 2023-07-18 凡所有相,皆是虚妄。若见诸相非相,即见如来。 k 线图是最好的老师,每天持续发布板块的rps排名,追踪板块,板块来开仓,板块去清仓,丢弃自以为是的想法,板块去留让…

异步复位同步释放

1、概念 异步复位同步释放就是在复位信号到来的时候不受时钟信号的同步,在复位信号释放的时候受到时钟信号的同步; 优点是可以避免电路出现瞬态错误或者亚稳态。 2、原理图 3、代码实现 /***********************************************/ /**…

【unity之IMGUI实践】单例模式管理面板对象【一】

👨‍💻个人主页:元宇宙-秩沅 👨‍💻 hallo 欢迎 点赞👍 收藏⭐ 留言📝 加关注✅! 👨‍💻 本文由 秩沅 原创 👨‍💻 收录于专栏:uni…

你知道Apache 软件基金会如何选择开源项目吗

Apache软件基金会(Apache Software Foundation,简称ASF)是一个致力于开源软件发展的慈善组织,因其广泛的项目和开放的治理模式而备受社区赞誉。作为全球最大的开源基金会之一,ASF如何选择开源项目成为人们关注的焦点。…

哇~真的是你呀!今天是LIUNX中的SAMBA。

目录 前言 一、概述 二、安装 三、在SAMBA服务器中设置共享目录 四、客户端查看共享目录及登录 五、本地映射 六、客户端自动挂载 七、用户别名 八、访问控制 总结 前言 SAMBA是一个开源的软件套件,用于在Linux和UNIX系统上实现SMB/CIFS网络协议。SMB(S…

大语言模型(LLM)评估综述

论文地址:https://arxiv.org/abs/2307.03109 Github地址:https://github.com/MLGroupJLU/LLM-eval-survey 一 、背景 随着ChatGPT和GPT-4的推出,大型语言模型(LLM)在学术界和工业界的热度日益升高,这主要…

物联网(IoT):连接未来的万物之网

引言: 物联网(Internet of Things,简称IoT)是指通过各种智能设备和传感器,使物体能够互联互通、收集和共享数据的网络。随着科技的不断进步和智能设备的普及,物联网的应用呈现出爆发式增长,对各…

【网关】ShenYu Gateway入门Demo体验,ShenYu网关2.6.0直接调用Dubbo服务

本次为新开源框架接入ShenYu网关做基础学习指导,特地来下载官网的demo体验一把,具体是想通过网关泛化调用dubbo服务。本次使用的是最新版本2.6.0。 官网文档: 如何通过 Apache ShenYu 网关代理 Dubbo 服务 | Apache Dubbo 环境准备 第一步&a…