Java学习-类的隐藏机制(封装性)_封装使类不可见_jQueryZK的博客-程序员秘密

技术标签: 面向对象  java  java学习  封装性    封装  

Java学习-类的隐藏机制(封装性)

1、封装的含义

封装(encapsulation)是面向对象的三要素之一(其它两个是继承多态),它有两成含义:
1、将数据(属性)和函数(行为)放在一个独立的类中,使类成为一个独立的单元。
2、通过访问限定符(private等)实现对信息的隐藏或公开,隐藏类的内部实现。而留下一些接口(public的成员函数)与外界进行信息交换(外界要想访问某个成员只能通过接口实现)当类的设计者改变了类的内部实现时,但只要接口不变,对于类的使用者而言,没有任何影响。这就是所谓的“接口和实现的分离
那么什么是封装? 简单地说,封装就是将数据和函数放在一起,将不想让外界看到的内容(通常是数据)声明为private的,不允许外界存取。外界要想访问的话,就只能通过类留给外部的接口。
为了更好的理解为什么要对对象进行封装,下面举个例子进行说明
先写两个类 :

  • Person类
package day01
public class Person{
    
	public int age;
	public void printAge()
	{
     
		System.out.println("年龄是:"+age);
	}
}
  • Test测试类
package day01
public class Test{
    
    public static void main(String[] args)
    {
    
    	Person p = new Person();
    	p.age = -100;
    	p.printAge();
    }
}

运行后打印结果为:年龄是:-100
分析一下代码:
程序是没问题的也能正常运行,但是年龄为-100显然不符合正常逻辑。从代码可以看出在new完一个person对象后用户可以对它的age属性随便赋值。像这种情况是把类的属性开放出来,让调用者随意使用,这样就会出现问题,它们很容易被一些粗心的或不知情的客户端程序员所毁坏。
所以我们需要对这样不能让调用者随意使用的属性做封装和隐藏以减少程序的bug。这意味着类的创建者可以任意修改被隐藏的部分,而不用担心对其他调用者造成影响。
代码修改后如下:

package day01
public class Person{
    
	private int age;
	public void setAge(int a)
	{
    
		if(a <=150 && a>=0){
    
			this.age = a;	
		}else{
    
			System.out.println("输入的年龄:"+a+"不在0到150之间");
		}
	}
	public int getAge()
	{
     return this.age;}
	public void showAge()
	{
    
		System.out.println("年龄是:"+this.getAge());
	}
	
}
package day01
public class Test{
    
	 public static void main(String[] args)
	 {
    
	 	Person p1 = new Person();
	 	Person p2 = new Person();
	 	p1.setAge(55);
	 	p1.showAge();
	 	p2.setAge(60);
	 	p2.showAge();
	 }
}

可以看到修改过后的对象不能直接通过p.age进行赋值操作,因为此时的age属性已经是被private限制,只能由类内部的成员函数调用并进行传参。

2、类的setXXX 和 getXXX

封装的一个原则是:“信息的最小化公开”,所以在理想状态下,通常将所有的数据都声明为private(因为随便对类的内部数据进行更改是很危险的),如果想改变和得到某个数据的话,那么使用相应的接口进行访问

  • 通常设置数据的接口命名为setXXX(如public void setAge() )
  • 将得到数据的接口命名为getXXX(如public int getAge() )
    ?考虑这样两个问题:
    问题一: 使用Person类来定义的两个对象p1和p2,那么p1和p2两个对象在内存中的存储状态是怎么样的呢?即数据成员和成员函数是否都存放在对象中呢?
    问题二: p1和p2调用相同的成员函数,为什么显示结果不一样?它们调用的是同一段代码吗?
    其实对象空间中仅存储数据成员,而类的成员函数代码不会存储在对象中,用一个类的不同的对象调用成员函数时,调用的是同一段函数代码。
    成员函数和普通函数的区别:
    在编译器的角度来看,成员函数和普通函数是没有本质区别的,成员函数只不过是为了封装的需要,而在形式上放在类中。最主要的区别是:
    成员函数暗自具备了一个从编译器传过来的指向类对象的this(当前对象的引用),通过它成员函数就可以操作当前对象的数据成员。
	 	Person p1 = new Person();
	 	Person p2 = new Person();
	 	p1.setAge(55);//在这里this指向p1
	 	p2.setAge(60);//在这里this指向p2

3、this关键字

  • 在类的方法定义中使用的this关键字表示使用该方法对象的引用。
  • 当必须指出当前使用方法对象是谁时要使用this
  • this可以看作是一个变量,它的值是当前对象的引用
  • 当处理方法中成员变量和局部变量重名时要用this

4、总结

java中类的封装和隐藏就是:
通过将类的成员数据声明为私有的(private),再提供公共的(public)方法:getXXX()和setXXX()实现对该属性的操作。以实现以下目的。

  • 隐藏一个类中不需要对外提供的实现细节
  • 使用者只能通过事先定制好的方法来访问数据,可以方便地加入控制逻辑,限制对属性的不合理操作;
  • 便于修改,增强代码的可维护性

欢迎持续关注!
个人博客站:jQueryZK Blog

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/weixin_44279178/article/details/107883255

智能推荐

c#程序设计教程(李春葆第三版)第五章上机实验_c#实用教程第三版课后习题_中工彭于晏的博客-程序员秘密

1using System;using System.Collections.Generic;using System.Text;namespace experment5_1{class Student //学生类{int sno; //学号string sname; //姓名Course[] cou...

struts2.0多附件上传_yifeixiang的博客-程序员秘密

一、上传单个文件 上传文件是很多Web程序都具有的功能。在Struts1.x中已经提供了用于上传文件的组件。而在Struts2中提供了一个更为容易操作的上传文件组 件。所不同的是,Struts1.x的上传组件需要一个ActionForm来传递文件,而Struts2的上传组件是一个拦截器(这个拦截器不用配置, 是自动装载的)。在本文中先介绍一下如何用struts2上传单个文件,最后介绍一下用...

Kafka重启出错:Corrupt index found,_能量守恒洛的博客-程序员秘密

Kafka进程被强制退出(kill -9)后重启,碰到如下问题:FATAL Fatal error during KafkaServerStable startup. Prepare to shutdown (kafka.server.KafkaServerStartable)Java.lang.IllegalArgumentException: requirement failed: C

js中使用console.time显示程序运行耗时_shidaping的博客-程序员秘密

在js中可以使用console.time和console.timeEnd来监测程序的运行耗时,以便优化性能。代码如下console.time('aa');for(var i=0;i<1000;i++){console.log(i);};console.timeEnd('aa')最后打印出aa:120ms表示aa之间的代码共耗时120ms

Logstash——Logstash从MySQL中收集数据并输出_大·风的博客-程序员秘密

之前介绍过如何使用文件系统通过Logstash将数据推送至elasticsearch来实现日志的线上分析。而Logstash这次介绍通过logstash 将MySql数据同步至elasticsearchLogstash-MySql数据源配置最开始先看下MySQL作为数据来源时支持的所有配置input { jdbc { ### 查询参数的哈希,例如 { "target_id" =...

随便推点

PHP基础语法笔记_FrankHuang888的博客-程序员秘密

PHP基础 开发环境 PHP基本语法 PHP 标记符 &lt;?php --- ?&gt; 注释 //单行 /* 多行 */ # shell风格单行 PHP...

java开发常用的jar包的作用解释_aspectjweaver包的作用_tt07406的博客-程序员秘密

转载自:http://blog.csdn.net/chaod5659/article/details/8250845java开发中主要用到的jar包描述commons-io.jar:可以看成是java.io的扩展,用来帮助进行IO功能开发.它包含三个主要的领域:Utilityclasses-提供一些静态方法来完成公共任务.Filters-提供文件过滤器的各种实现.Streams-提供实用的S...

求助:Python接口自动化-如何遍历读取excel表格_Fandy_梵迪的博客-程序员秘密

以下是代码,两个函数意思是分别读取excel表格的第一行和第二行,发起request请求,i代表行数,请教一下,可以怎样把以下代码合并?两个函数差别只在i不同而已。想要做到每读取一行excel表格的内容,就发一次request请求。 def test_request1(self): i = 0 logger.logger.logger.debug('测试用例...

TCP、UDP及IP协议总结_进击的鸭嘴兽的博客-程序员秘密

TCP协议常见知识TCP协议特点 和 首部格式源端口(Source Port),目标端口(Destination Port) 各2字节源端口号,标识主机上发起传送的应用程序;目的端口标识主机上传送要到达的应用程序。源端和目的端的端口号,用于寻找发端和收端应用进程。这两个值加上I P首部中的源端I P地址和目的端I P地址唯一确定一个TCP连接。一个I P地址和一个端口号...

error LNK2038: 检测到“_ITERATOR_DEBUG_LEVEL”的不匹配项: 值“0”不匹配值“2_weixin_30571465的博客-程序员秘密

使用VS2013版本引用外部的lib进行编译时候提示:错误25error LNK2038: 检测到“_ITERATOR_DEBUG_LEVEL”的不匹配项: 值“0”不匹配值“2”(jrtplibSend.obj 中)F:\jrtplibProjects\jrtplibSend\jrtplibSend\jrtplib.lib(rtpudpv6transmitter.obj)jrtpl...

英语总结—— 翩若惊鸿, 婉若游龙_世代庄少主的博客-程序员秘密

【前言】           千山万水,斗转星移。于是精移神骇,忽焉思散。俯则末察,仰以殊观,睹一丽人,于岩之畔!【正文】           过去种种,历历在目。感觉有些脱离SLA,于是近日反思、追溯。总结入下:一、自己还应该继续听可视化的英语材料。听到对话常浮于脑中,影像与声音,能出似惊鸿,卧似游龙。二、与人英语沟通较少,原因是我实在是不喜欢AJ材料,可是大家都在听AJ、交

推荐文章

热门文章

相关标签