封装[20分钟]
1) 为什么需要封装
a) 通过以下示例来分析
1. 编写一个Person类,要求:
a) 具有属性:姓名、年龄
b) 具有行为:自我介绍
2. 以上要求很容易实现,代码如下:
class Person01 {
public String name = "tom"; //姓名
public int age = 20; //年龄
public void salaryInfo() {
System.out.println("大家好,我是:" + name + "\t年龄是:" + age);
}
}
b) 现在实例化一个对象来测试创建的类是否符合要求:
1. 代码示例:
public class Demo001 {
public static void main(String args[]) {
// 创建“人”类对象
Person01 person = new Person01();
// 为人类对象的属性赋值————很明显,这个值不符合实际情况:没有人的年龄会是1000
person.age = 1000;
person.salaryInfo();
}
}
2. 输出结果:
3. 以上结果不符合要求(没有人的年龄会是1000),如何解决呢?
c) 要满足年龄要求,可以通过对属性的封装来实现
2) 什么是封装
a) 封装:就是隐藏实现细节
1. 将属性私有化,提供公有方法访问私有属性
2. 通过这些公有方法访问私有属性
b) 代码示例:
class Person02 {
// 私有的属性
private String name = "tom";
// 对name属性进行封装
//如果只有get封装,表明属性是只读的
//如果只有set封装,表明属性是只写的
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
public class Demo002 {
public static void main(String args[]) {
// 创建“人”类对象
Person02 person = new Person02();
person.setName("张三");
String sName = person.getName();
}
}
3) 如何实现封装
a) 封装的实现:
1. 修改属性的可见性来限制对属性的访问
2. 为每个属性创建一对赋值(setter)方法和取值(getter) 方法,用于对这些属性的访问
3. 在setter和getter方法中,加入对属性的存取限制
b) 代码示例:
class Person02 {
// 私有的属性
private int age = 20;
// 对age属性进行封装
public int getAge() {
return age;
}
// 在属性封装中将年龄限制在0~100之间
public void setAge(int age) {
if (age < 0 || age > 100) {
System.out.println("年龄必须在0~100之间,将使用默认值!");
} else {
this.age = age;
}
}
}
c) 使用封装好的属性:
1. 测试类:
a) 通过调用setter方法,为对象的各个属性赋值
b) 通过调用getter方法,获取对象的各个属性赋值
public class Demo002 {
public static void main(String args[]) {
// 创建“人”类对象
Person02 person = new Person02();
person.setName("张三");
// 为人类对象的属性赋值————很明显,这个值不符合实际情况:没有人的年龄会是1000,
// 而这里,因为有封装,程序不会将1000赋值给age变量
person.setAge(1000);
person.salaryInfo();
}
}
d) 使用封装,增加了数据访问限制,增强了程序的可维护性
4) 访问修饰符
a) Java访问控制符的作用是说明被声明的内容(类、属性、方法和构造方法)的访问权限
b) private是访问修饰符的一种,除了private之外,还有默认(无访问修饰符)、protected、public
c) 示例:
5) 小结
a) 封装的具体步骤
1. 修改属性的可见性限制对属性的访问
2. 为每个属性创建一对赋值方法和取值方法,用于对这些属性的访问
3. 在赋值和取值方法中,加入对属性的存取限制
b) 编程:
1. 请通过代码封装,实现如下需求:
a) 编写一个类Book,代表教材:
1) 具有属性:名称(title)、页数(pageNum),其中页数不能少于200页,否则输出错误信息,并赋予默认值200
2) 为各属性设置赋值和取值方法
3) 具有方法:detail,用来在控制台输出每本教材的名称和页数
b) 编写测试类BookTest进行测试:为Book对象的属性赋予初始值,并调用Book对象的detail方法,看看输出是否正确
2. 代码示例:
class Book {
// 名称
private String title;
// 页数
private int pageNum = 200;
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public int getPageNum() {
return pageNum;
}
//通过封装,限制页数必须大于200
public void setPageNum(int pageNum) {
if (pageNum < 200) {
System.out.println("页数不能少于200页,将使用默认值200");
this.pageNum = 200;
} else {
this.pageNum = pageNum;
}
}
// 在控制台输出每本教材的名称和页数
public void detail() {
System.out.println("名称:" + this.title + "\n页数:" + this.pageNum);
}
}
/*
* 测试类
*/
public class BookTest {
public static void main(String[] args) {
Book book = new Book();
book.setTitle("JAVA基础教程");
book.setPageNum(177);
book.detail();
}
}
知识点2:构造方法[15分钟]
1) 为什么需要构造方法
a) 只要创建对象,就一定会使用到构造方法
b) 通过以下示例来分析:
1. 开发Person类:Person04,要求:
1) 具有属性:姓名、年龄、性别、地址
2) 具有行为:自我介绍
2. 代码示例:
class Person04 {
// Person的四个属性
private String name;
private String address;
private String sex;
private int age;
// 以下是对属性的封装
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
public int getAge() {
return age;
}
// 在属性封装中将年龄限制在0~100之间
public void setAge(int age) {
if (age < 0 || age > 100) {
System.out.println("年龄必须在0~100之间,将使用默认值!");
} else {
this.age = age;
}
}
public String sayHai() {
return "大家好!我是:"+this.name+",我今年:"+this.age+"岁,性别:"+this.sex+",地址是:"+this.address;
}
}
c) 编写一个测试类,要求:
1. 实例化一个教员对象,并对其初始化
2. 在控制台输出该教员的自我介绍
3. 代码如下:
/*
* Person中有太多的属性及对应的setter方法,
* 在初始化时,很容易就忘记了
* 以下代码没有初始化地址
* 所以地址就是String类型的默认值:null
*/
public class Demo004 {
public static void main(String[] args) {
Person04 person = new Person04();
person.setName("张三");
person.setAge(23);
person.setSex("男");
System.out.println(person.sayHai());
}
}
4. 输出如下:
5. 可能出现的问题:
1) Person04中有太多的属性及对应的setter方法,在初始化时,很容易就忘记了,有没有可能简化对象初始化的代码?
d) 要简化对象初始化的代码,可以通过构造方法来解决
2) 什么是构造方法
a) 构造方法负责对象成员的初始化工作,为实例变量赋予合适的初始值
b) 构造方法必须满足以下语法规则:
1. 方法名与类名相同
2. 没有返回类型
c) 代码示例:
public class Person10 {
public String name; // 姓名
// 构造方法
public Person05 () {
name = "无名氏";
}
}
d) 使用new关键字调用构造方法
1. 代码示例:
public class Demo009 {
public static void main(String[] args) {
Person10 person = new Person10();
System.out.println(person.name);
}
}
e) 在以上代码示例中,即使没有给person对象的name属性赋值,name属性也有一个初始值:无名氏
f) 很多时间,我们希望显示地为实例变量赋予初始值:在不同的条件下创建不同的对象。所以我们需要使用带参数的构造方法
3) 带参数的构造方法
a) 通过带参数的构造方法,显式地为实例变量赋予初始值
1. 代码示例:
class Person05 {
// Person的四个属性
private String name;
private String address;
private String sex;
private int age;
//带四个参数的构造方法
public Person05(String name, String address, String sex, int age) {
this.name = name;
this.address = address;
this.sex = sex;
this.setAge(age);//调用封装的方法,以实现对年龄的限制
//this.age = age;
}
// 以下是对属性的封装
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
public int getAge() {
return age;
}
// 在属性封装中将年龄限制在0~100之间
public void setAge(int age) {
if (age < 0 || age > 100) {
System.out.println("年龄必须在0~100之间,将使用默认值!");
} else {
this.age = age;
}
}
public String sayHai() {
return "大家好!我是:"+this.name+",我今年:"+this.age+"岁,性别:"+this.sex+",地址是:"+this.address;
}
}
b) 通过调用带参数的构造方法,简化对象初始化的代码
1. 代码示例:
/*
* Person类有一个构造方法,
* 在创建对象时,将使用这个构造方法,
* 如果没有提供所需参数,就会出现编译错误
* 可以及时提醒
*/
public class Demo005 {
public static void main(String[] args) {
Person05 person = new Person05("张三","北京","男",23);
System.out.println(person.sayHai());
}
} |
|