一、为何使用封装
什么是封装?(面向对象三大特征之一)
将类的某些信息隐藏在类内部,不允许外部程序直接访问,而是通过该类提供的方法来实现对隐藏信息的操作和访问
封装的两个大致原则
把所有的属性藏起来
把尽可能多的东西藏起来,对外提供更加便捷的接口
二、实现封装
**·**修改属性的可见性----->设为private,防止错误的修改
**·**创建公有的getter、setter方法------>用于属性的读写
**·**在getter/setter方法中加入属性控制语句------>对属性值得合法性进行判断
实现封装的意义:
- 便于使用者正确使用系统,防止错误修改属性
- 有助于系统之间的松耦合,提高系统独立性
- 提高软件的可重用性
- 降低了构建大型系统的风险
三、封装应用练习:企鹅类的封装
需求说明
使用封装实现电子系统的企鹅类正确输入健康值和亲密度
保持健康值的有效性(0-100),否则取默认值60
保持亲密度的有效性(0-100),否则取默认值60
作答:
1.先写企鹅类,通过private包装它的属性,再用getter/setter封装,再health与love里写入逻辑,之后再输出
//企鹅类
public class Penguin {
private String name="吴蠢蛋";
private int health = 100;
private int love = 99;
private String sex = "女";
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getHealth() {
return health;
}
public void setHealth(int health) {
if (health<0 || health>100){
System.out.println("企鹅的健康值只能在0-100之间");
this.health=60;
return;
}
this.health = health;
}
public int getLove() {
return love;
}
public void setLove(int love) {
if (love < 0 || love > 100) {
System.out.println("企鹅的健康值只能在0-100之间");
this.love = 60;
return;
}
this.love= love;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
public void print(){
System.out.println("我的名字叫"+name
+"我的健康值是"+health+"我与主人qjj的亲密度是"+love+"我的性别是"+
sex);
}
}
2.建立测试类,通过键盘输入来获得企鹅的信息最后调用输出。
public class TestPenguin {
public static void main(String[] args) {
Scanner input =new Scanner(System.in);
System.out.println("欢迎你来到宠物店");
System.out.println("请输入你要领养的宠物的名字");
String name =input.next();
System.out.println("请选择企鹅的性别:1.女,2.男");
int sexId =input.nextInt();
String sex =(sexId==1) ? "女" : "男";
Penguin p = new Penguin();
p.setHealth(90);
p.setLove(100);
p.setName(name);
p.setSex(sex);
p.print();
}
}
运行后就可以得到自己想要的姓名的宠物信息
四、关于包
如何存放两个同名的类而不冲突?
Windows树形文件系统
- 文档分门别类,易于查找和管理
- 使用目录解决文件同名冲突问题
java中就引用了包(package)来防止冲突
包的作用:
- 允许类组成较小的单元(类似文件夹),易于找到和使用相应的文件
- 防止命名冲突,区分名字相同的类
- 有助于实施访问权限控制
注意事项:
1.包名由小写字母组成,不能以圆点开头或结尾
2.包名之前最好加上唯一的前缀,通常使用组织倒置的网络域名
3.包名后续部分依不同机构内部的规范不同而不同
4.一个类同时引用了两个来自不同包的同名类必须通过完整类名来区分
5.每个包都是独立的,顶层包不会包含子包的类
6.package和import的顺序是固定的:package必须位于第一行,只允许有一个package语句,其次是import,接着是类的声明。
五、访问权限控制
之前我们学过private,public等等那么这些修饰类的方法什么时候能够适用,又使用哪一种最为方便呢?
下面我们用一张表来诠释这一内容:
六、关于static
static可以用来修饰什么?
- 成员变量:静态变量,可以直接通过类名访问
- 成员方法:静态方法,可以直接通过类名访问
- 代码块:静态代码块,当java虚拟机加载时,就会执行该代码块
再之前调用类的普通成员变量,需要创建对象(实例),通过对象去访问------->实例变量
静态变量------->通过类名去调用
类变量(静态变量)
被static修饰的变量
在内存中只有一个拷贝
类内部,可以在任何方法内直接访问静态变量
其他类中,可以直接通过类名访问
实例变量
没有被static修饰的变量
没创建一个实例,就会分配一次内存,实例变量可以在内存中有多个拷贝,互不影响
static变量的作用
(1.能被类的所有实例共享,可作为实例之间进行交流的数据
(2.如果类的所有实例都包含一个相同的常量属性,可把这个属性定义为静态常量类型,从而节省内存空间
static变量应用练习
需求说明:模拟实现选民投票过程,一群选民进行投票,每个选民只允许投一次票,并且当投票总数达到一百时,就停止投票
作答:
先建立投票类,撰写方法编写业务逻辑
public class Voter {
//目前投票数,被所有选民实例共享
static int count;
//投票总数达到100时就停止投票
static final int MAX_COUNT = 100 ;
private String name;
public Voter(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public void vote(){
if (count==MAX_COUNT){
System.out.println("达到100,无法继续投票");
return;
}else {
System.out.println(this.name+"投票成功,当前票数为"+count);
count++;
}
}
}
之后编写测试类,加入for循环,投一百票
public class TestVote {
public static void main(String[] args) {
Voter v1 =new Voter("张三");
v1.vote();
Voter v2 =new Voter("李四");
v2.vote();
Voter v3 =new Voter("王五");
v3.vote();
for (int i = 1; i <=97 ; i++) {
Voter v =new Voter("v"+i);
v.vote();
}
Voter v4 = new Voter("kdls");
v4.vote();
}
}
static的方法如何使用
静态方法即在返回类型前加入static
可以直接通过类名调用,也可以进行实例调用实例方法
static代码块
JVM加载类时,加载静态代码块
如果有多个静态块,按顺序加载
每个静态代码块只会被执行一次
七、面向对象特征之二------继承
将重复代码全部抽取到父类中,后面的子类直接继承,避免了重复代码
同时,子类与父类是 is a 的关系:比如dog is a pet
如何编写?
1.编写父类
2.编写子类,继承父类 extends来继承
继承是Java中实现代码重用的重要手段之一,java中只支持单根继承,即一个类只能有一个直接父类。
何时使用继承?
继承与真实世界类似
只要符合is a关系就可以设计使用继承