044_面向对象_17_封装
一、封装的概念
制造厂家为了方便我们使用对象(电视、车辆),把复杂的内部细节全部封装起来。只给我们暴露简单的接口,比如:电源开关、比如:油门。具体怎么内部实现的,我们不需要操心。需要让用户知道的暴露出来,不需要让用户了解的全部隐藏起来。这就是封装。
我要看电视,只需要按一下开关和换台就可以了。有必要了解电视机内部的结构吗?有必要碰碰显像管吗?
二、为什么需要封装?封装的作用和含义?
专业:我们程序设计要追求“高内聚,低耦合”。高内聚就是类的内部数据操作细节自己完成,不允许外部干涉;低耦合:仅暴露少量的方法给外部使用。
编程中封装的具体意义:便于调用者调用。
良好的封装,便于修改内部代码,提高可维护性。
良好的封装,可进行数据完整性检测,保证数据的有效性。
三、使用访问控制符(private、default、protected、public),实现封装
同一个类 |
同一个包中 |
子类 |
所有类 |
|
private |
* |
|||
default(即不加修饰符的时候) |
* |
* |
||
protected |
* |
* |
* |
|
public |
* |
* |
* |
* |
四、封装的使用细节
1.属性一般使用private.(除非本属性确定会让子类继承并且使用时)才提供相应的get/set方法来访问相关属性. 这些方法通常是public,从而提供其他类对属性的读取操作。 (注意:boolean变量的get方法是用:is开头!)
2.一些只用于本类的辅助性方法可以用private,希望其他类调用的方法用public。
五、演示示例
一、private修饰符
1.测试private修饰符所修饰的属性或方法在同一类中是否能被访问
package edu.aeon.test; /** * [说明]:测试访问控制符 * @author aeon * 测试步骤: * 1、测试private修饰的方法或属性是否能在当前类(本类)中被调用?(结果:可以被调用) * 2、测试private修饰的方法或属性在非本类(同包的其它类/子类、不同包其他类/子类、)中是否能被调用?(结果:不可以被调用) */ public class A { //比如我们将本类的一个属性a用private修饰(私有化) private int a=10; private void seeA(){ //测试用private修饰的属性是否在本类中可见、 System.out.println(this.a); } public static void main(String[] args) { A a=new A(); //测试结果:用private修饰的属性、在本类中可以调用! System.out.println(a.a); a.seeA(); } }
测试结果截图:
2、测试private修饰符所修饰的属性或方法在同一包中的子类中是否能被访问
演示示例:
package edu.aeon.test; /** * [说明]:测试访问控制符 * @author aeon * 测试步骤: * 1、测试private修饰的方法或属性是否能在当前类(本类)中被调用?(结果:可以被调用) * 2、测试private修饰的方法或属性在非本类(同包的其它类/子类、不同包其他类/子类、)中是否能被调用?(结果:不可以被调用) */ public class A { //比如我们将本类的一个属性a用private修饰(私有化) private int a=10; private void seeA(){ //测试用private修饰的属性是否在本类中可见、 System.out.println(this.a); } public static void main(String[] args) { A a=new A(); //测试结果:用private修饰的属性、在本类中可以调用! System.out.println(a.a); a.seeA(); } }
package edu.aeon.test; /** * [说明]:测试private修饰的属性或者方法在同一包中的子类中是否能被访问(测试结果:不能被访问) * @author aeon * */ public class B extends A{ public static void main(String[] args) { A a=new A(); System.out.println(a.a); a.seeA(); /*我们测试一个在父类中根本不存在的方法或者属性:显然从测试结果可以看出来、父类中用private修饰的属性或者方法所报的错误 和调用一个父类中根本不存在的属性和方法所报的错误是不一样的。*/ a.seeAd(); } }
运行结果截图:
3、测试private修饰符所修饰的属性或方法在不同一包中的子类中是否能被访问
测试结果:这个肯定不能被访问了,同包子类中不能访问、不同包中的子类更加就不能访问了!
测试结论:
1、用private修饰的属性或者方法只能在本类中调用、其它(同一包中[类/子类]/不同包中[类/子类])均不能访问!
2、测试结果可以看出来、父类中用private修饰的属性或者方法所报的错误和调用一个父类中根本不存在的属性和方法所报的错误是不一样的、可见编译器能识别一个private修饰的属性和方法和调用一个根本不存在的方法。
二、默认(不写)修饰符
1.测试默认(不写)修饰符的属性或方法在同一包的同一类中是否能被访问
package edu.aeon.test; /** * [说明]:测试默认(不写时)访问控制符 * @author aeon * 测试步骤: * 1、测试不写访问修饰的方法或属性是否能在当前类(本类)中是否能被访问?(结果:可以被访问) * 2、测试不写访问修饰的方法或属性在同一包中的其它类中是否能被访问(结果:可以被访问) * 3、测试不写访问修饰的方法或属性在不同包中的其它类中是否能被访问(结果:不可以被访问) * 4、测试不写访问修饰的方法或属性在不同包中的其它子类中是否能被访问(结果:不可以被访问) * 结论:可见默认(不写)访问控制符修饰的属性和方法界限是同一包中、不同包中的其它类及其子类均不能被访问 */ public class A { //比如我们将本类的一个属性a用默认(不写)访问控制符修饰 int a=10; void seeA(){ //默认(不写)修饰符的属性是否在本类中可见、 System.out.println(this.a); } public static void main(String[] args) { A a=new A(); //测试结果:默认(不写)修饰的属性、在本类中可以调用! System.out.println(a.a); a.seeA(); } }
测试结果截图:
2、测试不写访问(默认)修饰的方法或属性在同一包中的其它类中是否能被访问(结果:可以被访问)
package edu.aeon.test; /** * [说明]:测试默认(不写时)访问控制符 * @author aeon * 测试步骤: * 1、测试不写访问修饰的方法或属性是否能在当前类(本类)中是否能被访问?(结果:可以被访问) * 2、测试不写访问修饰的方法或属性在同一包中的其它类中是否能被访问(结果:可以被访问) * 3、测试不写访问修饰的方法或属性在不同包中的其它类中是否能被访问(结果:不可以被访问) * 4、测试不写访问修饰的方法或属性在不同包中的其它子类中是否能被访问(结果:不可以被访问) * 结论:可见默认(不写)访问控制符修饰的属性和方法界限是同一包中、不同包中的其它类及其子类均不能被访问 */ public class A { //比如我们将本类的一个属性a用默认(不写)访问控制符修饰 int a=10; void seeA(){ //默认(不写)修饰符的属性是否在本类中可见、 System.out.println(this.a); } public static void main(String[] args) { A a=new A(); //测试结果:默认(不写)修饰的属性、在本类中可以调用! System.out.println(a.a); a.seeA(); } }
package edu.aeon.test; /** * [说明]:测试default(不写时)修饰的属性或者方法在同一包类中是否能被访问(测试结果:能被访问) * @author aeon * */ public class B{ public static void main(String[] args) { A a=new A(); System.out.println(a.a); a.seeA(); /*我们测试一个在父类中根本不存在的方法或者属性:显然从测试结果可以看出来、父类中用private修饰的属性或者方法所报的错误 和调用一个父类中根本不存在的属性和方法所报的错误是不一样的。*/ } }
测试结果:
3、测试不写访问修饰的方法或属性在不同包中的其它类中是否能被访问(结果:不可以被访问)
package edu.aeon.test1; import edu.aeon.test.A; /** * [说明]:测试不写访问修饰符的属性或者方法在不同包中的类中是否能被访问(测试结果:不能被访问) * @author aeon * */ public class C{ public static void main(String[] args) { A a=new A(); System.out.println(a.a); a.seeA(); /*我们测试一个在父类中根本不存在的方法或者属性:显然从测试结果可以看出来、父类中用private修饰的属性或者方法所报的错误 和调用一个父类中根本不存在的属性和方法所报的错误是不一样的。*/ } }
测试结果:
4、测试不写访问修饰的方法或属性在不同包中的其它子类中是否能被访问(结果:不可以被访问)
package edu.aeon.test1; import edu.aeon.test.A; /** * [说明]:测试不写访问修饰符的属性或者方法在不同包中的子类中是否能被访问(测试结果:不能被访问) * @author aeon * */ public class D extends A{ public static void main(String[] args) { A a=new A(); System.out.println(a.a); a.seeA(); /*我们测试一个在父类中根本不存在的方法或者属性:显然从测试结果可以看出来、父类中用private修饰的属性或者方法所报的错误 和调用一个父类中根本不存在的属性和方法所报的错误是不一样的。*/ } }
测试结果:
结论:
可见默认(不写)访问控制符修饰的属性和方法界限是同一包中、不同包中的其它类及其子类均不能访问!
五、总结
1、通过private访问控制符修饰的属性或者方法只能在同一个类中能被访问 2、通过默认(不写时)访问控制符修饰的属性或者方法只能在同一个类、同一个包中的其他类及同一个包中的子类中可以被访问。记住此处的界限是包、其它包中的类及其子类均无法访问。 3、通过protected访问控制符修饰的属性或者方法只能在同一个类、同一个包中的其他类及其同一个包中的子类中可以被访问。记住此处的界限是包、其它包中的类及其子类均无法访问。(经测试结果发现和默认访问控制符一样?) 4、通过public访问控制符修饰的属性或者方法在同一个类、同一个包中的其他类及其同一个包中的子类、不同包中的其它类、及其不同包中的子类均可以被访问。 |