一.封装性
1.面向对象这个编程思想,有三个基本特征:
① 封装
② 继承
③ 多态
2.什么是封装性?
生活中,快递包裹,通常需要用袋子或箱子装起来。
目的:① 包含的内部商品,不会被损坏
② 可以包含隐私
③ 运输更方便
所以,代码也要考虑这些因素:
① 隐私 -> 安全,当某个类的代码,内部某些成员不希望外部知晓,或者随意的更改,那么就可以进行适当的封装
② 外部使用更方便
比如:生活中,洗衣机,只会留出几个简单的按钮和进水口,出水口,放衣服的入口这几个,它隐藏了内部复杂的结构。
代码中,String类,它内部的结构和实现是很复杂的,但是我们就算不是特别清除每一个内部实现,也不影响我们简单的使用
把代码控制在它的合理的可见性范围内,就是封装。
3.如何实现封装?
必须依赖于权限修饰符,或者又称为访问控制修饰符。
4.权限修饰符有哪些?
public,protected,缺省,private
本类 本包的其他类 其他包的子类中 其他包的非子类
private √ × × ×
缺省 √ √ × ×
protected √ √ √ ×
public √ √ √ √
5.权限修饰符的使用要注意
① 如果权限修饰符是在class前面(这里暂不讨论内部类),只能是public或缺省
② 如果权限修饰符是在类的成员前面(成员变量,成员方法等),四种都可以
二.成员变量选择那种权限修饰符?
1.实际应用中,习惯上,先声明为private。称为属性私有化。
但是如果确实这个成员变量需要扩大它的可见性范围,那么可以把private修改为其他合适的修饰符。
例如:扩大到本包,那么就是缺省的。
例如:扩大到其他包的子类中,那么就是protected
例如:扩大到其他包的非子类中,那么就是public
2.为什么要使用权限修饰符?
因为属性其实就是代表对象的“数据”,那么对象的数据是非常重要的,不应该完全暴露,至少要可控。
3.如何使用私有化的属性?
如果这个属性确实要被外部使用,需要提供get或set方法。
get方法:供调用者获取属性值的方法
set方法:供调用者修改属性值的方法
4.get/set方法要注意的地方:
① 如果方法中有局部变量(也就是形参)与对象的实例变量“重名”,那么需要在实例变量的前面加“this.”。如果没有重名问题,在实例变量前面可以加“this.”,也可以不加“this.”。
② get/set的方法名,通常都是
get + 属性名,并且属性名的首字母大写
set + 属性名,并且属性名的首字母大写
③ 如果属性是boolean类型,那么它对应的方法,就会把get单词换成 is
Student类代码:
package com.atguigu.encapsulability;
public class Student {
private String name;
private int score;
private int age;
private boolean marry;
//快捷键,自动生成get/set
//在要写get/set方法的位置,鼠标的光标不要定位错位置了
//按快捷键 Alt + Insert,部分同学需要同时按Fn
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getScore() {
return score;
}
public void setScore(int score) {
this.score = score;
}
public int getAge() {
return age;
}
public void setAge(int age) {
//加条件判断,加逻辑的控制
if(age<=20 || age>=35){
return;
// throw new IllegalArgumentException(age +"非法");
}
this.age = age;
}
public boolean isMarry() {
return marry;
}
public void setMarry(boolean marry) {
this.marry = marry;
}
}
对属性加上权限修饰符的话,也就是属性私有化,可以保证属性(数据)的安全,比如说设置属性值的时候,属性私有化就可以在set方法上加条件判断,看上述代码。
TestField类代码:
package com.atguigu.encapsulability;
public class TestField {
public static void main(String[] args) {
Student s1 = new Student();
/* s1.name = "张三";
s1.score = 89;
s1.age = 23;
//以上代码正常使用没问题,但是如果出现以下代码
s1.score = -89;
s1.age = -23;//没有设置权限修饰符,可以随便更改属性值(数据)
//这样写,逻辑上有问题,语法上没法控制*/
//这里是调用者的角色,调用s1学生对象的姓名name的get和set
System.out.println("修改之前,姓名:" + s1.getName());
s1.setName("张三");
System.out.println("修改之后,姓名:" + s1.getName());
System.out.println("修改之前,年龄:" + s1.getAge()) ;
s1.setAge(-23);
System.out.println("修改之后,年龄:" + s1.getAge()) ;
}
}
练习1:
(1)定义矩形类Rectangle,
- 声明实例变量长和宽,全部私有化private,
- 提供相应的get/set方法,如果set方法的参数值<=0,则提示矩形的长和宽必须是正数
- 声明public double area(),返回矩形面积
- 声明public double perimeter():返回矩形的周长
- 声明public String getInfo():返回矩形的长、宽、面积、周长信息
(2)测试类的main中创建一个可以装3个矩形对象的数组,并调用set方法为对象的属性赋值,依次长是8,7,6,宽是2,3,4
- 遍历输出矩形对象数组
- 按照矩形对象的length属性值从小到大排序后,遍历输出矩形对象数组
- 按照矩形对象的面积从小到大排序后,遍历输出矩形对象数组
编写代码的习惯:先写所有的成员变量的声明,再写方法
Rectangle类代码:文章来源:https://www.toymoban.com/news/detail-451554.html
public class Rectangle {
private double length;
private double width;
public double getLength() {
return length;
}
public void setLength(double length) {
if(length<=0){
System.out.println("长方形的长必须是正数");
return;//结束当前方法的执行,那么 this.length = length;就不执行了
}
this.length = length;
}
public double getWidth() {
return width;
}
public void setWidth(double width) {
if(width<=0){
System.out.println("长方形的宽必须是正数");
return;//结束当前方法的执行,那么 this.width = width;就不执行了
}
this.width = width;
}
public double area(){
return length * width;
}
public double perimeter(){
return 2 * (length + width);
}
public String getInfo(){
return "长:" + length +",宽:" + width +",面积:" + area() +",周长:" + perimeter();
}
}
TestRectangle类代码:文章来源地址https://www.toymoban.com/news/detail-451554.html
public class TestRectangle {
public static void main(String[] args) {
Rectangle[] arr = new Rectangle[3];
System.out.println("排序之前:");
for (int i = 0; i < arr.length; i++) {
arr[i] = new Rectangle();
arr[i].setLength(8-i);
arr[i].setWidth(2+i);
System.out.println(arr[i].getInfo());
}
System.out.println("按照length从小到大排序:");
for(int i = 1; i < arr.length; i++) {
for(int j = 0; j < arr.length-i; j++) {
if(arr[j].getLength() > arr[j+1].getLength()){
Rectangle temp = arr[j];
arr[j] = arr[j+1];
arr[j+1] = temp;
}
}
}
for(int i = 0; i < arr.length; i++) {
System.out.println(arr[i].getInfo());
}
System.out.println("按照面积从小到大排序:");
for(int i = 1; i < arr.length; i++) {
for(int j = 0; j < arr.length-i; j++) {
if(arr[j].area() > arr[j+1].area()){
Rectangle temp = arr[j];
arr[j] = arr[j+1];
arr[j+1] = temp;
}
}
}
for(int i = 0; i < arr.length; i++) {
System.out.println(arr[i].getInfo());
}
}
}
到了这里,关于面向对象的特征之一:封装的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!