面向对象编程的三大特征:封装、继承和多态。
封装(encapsulation)
封装就是把抽象出的数据(属性)和对数据的操作(方法)聚集在一起,数据被保护在内部,程序的其他部分只有通过被授权的操作(方法),才能对数据进行操作。
封装的好处
- 隐藏实现细节
- 可以对数据进行验证,保证安全合理
1.封装的实现步骤
- )将属性进行私有化【不能直接修改属性】
- )提供一个公共(public)的set方法,用于对属性判断并赋值
public void setXxx(){ //Xxx表示某个属性
//加入数据验证的业务逻辑
属性 = 参数名;
}
- )提供一个公共(public)的get方法,用于获取属性的值
public 数据类型 getXxx(){ //权限判断,Xxx表示某个属性
return xx;
}
2.封装的使用
通过一个例子来说明封装的使用方法:
编写一个程序,查看人的年龄、工资、工作等。
要求:
①. 不能随便查看别人的年龄,工资等隐私,
②. 对设置的年龄进行合理的验证。年龄合理就给设置值,否则就给默认值。
③. 年龄必须在1-120之间,年龄工资不能直接查看,name的长度在2-6之间。
代码实现:
public class Encapsulation001{
public static void main(String[] args){
Person person = new Person();
person.setName("zywoo");
person.setAge(18);
person.setSalary(3000);
System.out.println(person.info());
}
}
public class Person{
public String name;
private int age; //年龄
private double salary; //工资
public String getName(){
return name;
}
public void setName(String name){
//加入对数据的校验
if(name.length() >=2 && name.length() <=6 ){
this.name = name;
} else {
System.out.println("名字长度不符,在2-6个字符之间。");
}
}
public int getAge(){
return age;
}
public void setAge(int age){
//判断年龄范围
if(age >= 1 && age <= 120){ //合理范围
this.age = age;
} else{
System.out.println("年龄设置不符合要求,需要在 1-120 之间");
this.age = 18; //超出范围后给默认年龄
}
}
public double getSalary(){
return salary;
}
public void setSalary(double salary){
//可以在这里增加对当前对象的权限判断
this.salary = salary;
}
//写一个方法,返回属性信息
public String info(){
return name + " 的信息为:age=" + age + " 薪水=" + salary;
}
}
Console:
zywoo 的信息为:age=18 薪水=3000.0
3.封装与构造器
还是以上一段代码为例,我在程序中加入构造器:
public class Person{
public String name;
private int age; //年龄
private double salary; //工资
//无参构造器
public Person(){
}
public Person(String name,int age,double salary){
this.name = name;
this.age = age;
this.salary = salary;
}
public String getName(){
return name;
}
public void setName(String name){
//加入对数据的校验
if(name.length() >=2 && name.length() <=6 ){
this.name = name;
} else {
System.out.println("名字长度不符,在2-6个字符之间。");
}
}
public int getAge(){
return age;
}
public void setAge(int age){
//判断年龄范围
if(age >= 1 && age <= 120){ //合理范围
this.age = age;
} else{
System.out.println("年龄设置不符合要求,需要在 1-120 之间");
this.age = 18; //超出范围后给默认年龄
}
}
public double getSalary(){
return salary;
}
public void setSalary(double salary){
//可以在这里增加对当前对象的权限判断
this.salary = salary;
}
//写一个方法,返回属性信息
public String info(){
return name + " 的信息为:age=" + age + " 薪水=" + salary;
}
}
如果我们在创建对象时,直接传参会发生什么?
public class Encapsulation001{
public static void main(String[] args){
Person person = new Person("zywoo",2000,3000);
System.out.println(person.info());
}
}
Console:
zywoo 的信息为:age=2000 薪水=3000.0
从上面的代码可以看出,如果使用构造器的话,可以直接避开set方法的保护机制,那我们要怎样防止这种情况发生?那就是直接把set方法写在构造器中,如下所示:
public Person(String name,int age,double salary){
this.setName(name);
this.setAge(age);
this.setSalary(salary);
}
这次再输出(“zywoo”,2000,3000),就会提示错误信息:
Console:
年龄设置不符合要求,需要在 1-120 之间
zywoo 的信息为:age=18 薪水=3000.0
所以,一般添加构造器后,最好把防护机制添加进构造器中,防止直接使用构造器绕过防护机制
4.封装课后练习
创建程序,在其中定义两个类:Account和AccountTest类体会Java的封装性。
- Account类要求具有属性:姓名(长度为2位3位或4位)、余额(必须 > 20)、密码(必须是六位),如果不满足,则给出提示信息,并给默认值
- 通过setXxx的方法给Account的属性赋值。
- 在AccountTest中测试
提示:
String name = " ";
int len = name.length();
代码实现:
Account类
public class Account {
private String name;
private double balance;
private String password;
public Account(){
}
public Account(String name,double balance,String password){
// this.name = name;
// this.balance = balance;
// this.password = password;
this.setName(name);
this.setPassword(password);
this.setBalance(balance);
}
public String getName() {
return name;
}
public void setName(String name) {
if (name.length() >= 2 && name.length() <= 4) {
this.name = name;
} else {
System.out.println("名字长度不符,在2-4个字符之间。");
this.name = "ccc";
}
}
public double getBalance() {
return balance;
}
public void setBalance (double balance){
if (balance>20) {
this.balance = balance;
} else {
System.out.println("余额必须大于20");
this.balance = 20;
}
}
public String getPassword(){
return password;
}
public void setPassword(String password){
if(password.length() == 6) {
this.password = password;
} else {
System.out.println("密码必须为6位");
this.password = "123456";
}
}
public String info(){
return name + " 的信息为:余额=" + balance + " 密码=" + password;
}
}
}
AccountTest类
public class AccountTest{
public static void main(String[] args){
// Account p = new Account();
// p.setName("woo");
// p.setBalance(300);
// p.setPassword("123456");
// System.out.println(p.info());
Account p = new Account("woo",300,"1234567");
System.out.println(p.info());
}
}
输出:
Console:
密码必须为6位
woo 的信息为:余额=300.0 密码=123456