目录
2)get方法:获取属性值的方法
一、引入
——生活中的封装:当我们去来伊份买一些独立包装的小零食,当看到自己爱吃的就会一抓一大把,然后“装”进食品袋,最后让服务员给我们“封”好。所以在Java中提到封装时,我们不难联想到食品中的封装,那么我们如何从食品封装过渡到Java封装呢?两者又有什么异曲同工之妙呢?知识的学习往往都是源于生活,却高于生活。
不妨让我们先对生活中的这一现象进行分析,食品中的封装具有什么特征?
- 首先我们会一般拿很多一小袋一小袋的零食,所以如果不装起来就会很不方便,装是否为我们提供了便捷呢?
- 我们把食物封起来则会使得这些零食更安全,而不会掉出来,要取的时候只需要轻轻拉开这个封口就好了,封是否提高了安全性?
好了,下面我们先看看有关封装的基本知识,最后再回到这个生活现象上,或许对封装的概念会更加通透。
在开始之前不妨先提出几个问题,最后再来看它们是否都能被解决:
- 什么是封装?——尝试从“封”和“装”的角度来看
- 为什么要用封装?什么情况下会用到封装?封装又有什么优点?
二、封装中的“封”
1. “封”:数据的封装 在面向对象编程中,封装首先意味着将数据(属性)封装在类的内部,对外部隐藏数据的具体实现细节。 这样做的目的是为了保护数据,防止外部直接对数据进行修改而破坏数据的完整性。 通过将数据封装起来,类可以控制数据的访问权限,只允许通过公共接口来访问和修改数据,从而确保数据的安全性。 举个例子,一个名为`Person`的类可能有一个私有属性`age`来表示年龄,通过封装,我们可以提供公共的`getAge()`和`setAge()`方法来访问和修改年龄属性,而不直接暴露`age`属性给外部。 这样做可以确保年龄只能通过指定的方法进行访问和修改,避免外部直接修改年龄属性。 |
2. “装”:行为的封装 除了将数据进行封装外,封装还包括行为(方法)的封装。通过将操作数据的方法与数据本身捆绑在一起,封装可以确保数据的一致性和有效性。类的方法定义了可以对数据执行的操作,外部对象通过调用这些方法来实现对数据的修改和处理,而不需要了解具体的实现细节。 继续以`Person`类为例,除了封装年龄属性外,我们还可以定义一些方法如`increaseAge()`和`printInfo()`来实现增加年龄和打印个人信息的功能。通过封装这些行为,我们可以将相关的操作封装在类的内部,外部对象只需调用这些方法而无需了解其具体实现。 通过将数据和行为封装在一起,封装不仅提高了数据的安全性和完整性,还使类的设计更加清晰和灵活。数据的封装保护数据的隐私,行为的封装确保数据的一致性和有效性,这两者共同构成了面向对象编程中封装的核心思想。 |
1.关于访问权限修饰符
访问权限修饰符 | |||
public(公共的) | private(私有的) | protected(受保护的) | default(缺省/无) |
1)在哪里见过public?(用来修饰类 属性 方法)
——思考:回顾写过的Java代码中哪里出现过public,然后再去思考为什么这里要用public,最后从中总结它的用途。
public class
public int/String
public void
2)private是能修饰属性和方法,不能修饰类,我们从来没有见过private class
3)protected同样是可以修饰属性和方法
4)类、属性、方法都可以无修饰符修饰
2.项目结构是什么
在这里大家可能会有疑惑:封装跟项目结构有什么关系?两者并没有直接的关系,但项目结构跟访问权限修饰符的作用范围有紧密的关系,所以两者间接也算有了关系。
但可能有人觉得你到现在也没有说访问权限修饰符跟封装有什么关系呀,别急,马上就答案揭晓。
- Pro23为项目名
- out是src编译后的代码文件( .class)
- Src(source code)源代码目录(一般里面都是.java的文件,所有的代码文件都要定义在此目录中才可以编译运行)
- lzc0916是包名,这是一个package包的图标
- HelloWorld是一个Java Class类文件名
- public class HelloWorld{ } 类
public | 整个项目下(最宽松的修饰符) |
private | 只能在本类中使用(最高级别的封装性) |
protected | 可以同包下使用,不同包中只有子类(与继承有关,后面会陆续介绍)可以使用 |
缺省/无 | (包默认)可以在同一个包中调用 |
3.访问权限修饰符所能“封”的范围
请参考以下Java代码实例:从上至下分别是无、公共的、私有的、受保护的访问权限修饰符的数据
1)同一类中
这张图说明在一个类中,所有修饰符都能正常运行,不受限制
然后我们在同一个包中定义一个新的类
将已经写好的主函数复制一份后粘贴至新的类(此时是在同一个包中不同类)
2)同一包不同类中
不难发现只有gender报错了,而回到初始代码中,修饰gender的修饰符是private
可以得出:同一包中不同类,仅私有权限受到限制无法调用
然后是不同包中
3)不同包中
Name是无修饰符的,gender同上是私有的,habit是protected受保护的,三者皆无法调用
所以在不同包中,只能调用公共的public
还有一种是关于子类(这点比较难可能还需要熟练掌握继承的知识后才能理解的更通透)
(继承后的类为子类)
4)子类
需要注意继承后,这一块也需要改写
由此可见:
在不同包中,子类只能调用公共的以及受保护的
总结:根据不同情况使用不同的访问权限修饰符对类中的方法或属性进行修饰,可以得到不同的调用结果,使得有些可以被调用,而有些不能。
4.关于封装中的一些数据
“封”的本质是为了保护我们数据与方法内部的安全性,方便代码的维护与修改。
而数据不仅仅要符合定义的数据类型,也要符合数据本身的数据特征!
所以当数据特征不匹配——我们也称为数据不安全。
- 比如呢我们想要用户名由大写字母+小写字母+数字(+特殊字符)组成,要求长度范围为[8,16],不能以数字开头、不能使用标点...
- 再比如年龄,注册年龄应该为(0,200),当然我们一般不会让用户在注册时选择自己的年龄,而是通过让他们设置出生日期从而自动生成年龄
*(代码灵感)对于用户名中不应该出现不合法字符,可以使用循环遍历结合ASCII表(char每个字符都有相对应的编码范围)来避免(对ASCII表做一个简单介绍,包含字母、符号) 中文汉字则用的是unicode编码(\u4e00-\u9fff为中文字符)
三、如何对封起来的属性和方法进行操作呢——封装中的“装”
1.“装”的方法
1)set方法:给属性赋值的方法
public void set属性名(数据类型 参数名){
this.参数名=参数名;
}
2)get方法:获取属性值的方法
public 数据类型 get属性名(){
return 属性名;
}
3)is方法
判断boolean值的方法(特别是在表示某个属性是否具有某种状态或特征时。通常情况下,以"is"开头的方法名返回一个布尔值,通常用于查询对象的状态或特征)
2.对“装”的总结
Setter 方法(set方法) | Setter 方法通常用于设置对象的属性值。 接受一个参数,并将该参数的值赋给对象的相应属性。 通常的 setter 方法命名约定是以 "set" 开头,后面跟随属性名的驼峰命名规则。例如,如果有一个属性名为 `name`,那么对应的 setter 方法可能是 `setName(String name)`。 |
Getter 方法(get方法) | Getter 方法通常用于获取对象的属性值。 不接受任何参数,而是返回对象的属性值。 通常的 getter 方法命名约定是以 "get" 开头,后面跟随属性名的驼峰命名规则。例如,如果有一个属性名为 `name`,那么对应的 getter 方法可能是 `getName()`。 |
3.代码实例
public class Person {
private String name;
// Getter 方法
public String getName() {
return this.name;
}
// Setter 方法
public void setName(String name) {
this.name = name;
}
}
this.name表明该name为实例(成员)变量name,且是将局部变量的值赋给成员变量(理清a=b;和b=a;在java中的区别:前者是将b的值赋给a,后者则是将a赋予给b)
注意局部变量一般多出现于方法、循环、条件语句中
通过使用 setter 和 getter 方法,可以实现对对象属性的封装,遵循面向对象编程的封装原则,隐藏对象的内部实现细节,通过公开的接口来操作对象的属性,提高了代码的可维护性和可扩展性。
4.数据类型:long
在Java编程语言中,long 是一种基本数据类型,用于存储整数值,占用 8 个字节(64 位),范围为 -9,223,372,036,854,775,808 到 9,223,372,036,854,775,807。
通常它会有一个较大的范围,可以表示比 int 类型更大的整数值。
在Java中,如果一个整数值超出了 int 类型的范围,可以使用 long 类型来存储更大的整数值。
在为 long 类型变量赋值时,需要在数字的末尾加上 L 或 l,以明确指示这是一个 long 类型的常量。
四、算法联动
算法题——来自封装操作中的联想
判断输入的字符串是否包含中文、大小写字母、或数字