面向对象特征之一:封装性
1. 为什么需要封装性?
理论上:
-高内聚:类的内部数据操作细节自己完成,不允许外部干涉;
-低耦合:仅暴露少量的方法给外部使用,尽量方便外部调用。
通俗的说:把该隐藏的隐藏起来,该暴露的暴露出来。这就是封装性的设计思想。
2. 如何实现数据封装?
2.1 权限修饰符
Java规定了4种权限修饰,分别是:private、缺省、protected、public
作用
我们可以使用4种权限修饰来修饰类及类的内部成员。当这些成员被调用时,体现可见性的大小。
类:只能使用public、缺省修饰
类的内部成员:可以使用4种权限修饰进行修饰。
2.2 开发中4种权限使用频率的情况:
比较高:public、private
比较低:缺省、protected
3. 封装性的体现
场景1:私有化(private)类的属性,提供公共(public)的get和set方法,对此属性进行获取或修改
场景2:将类中不需要对外暴露的方法,设置为private.
场景3:单例模式中构造器private的了,避免在类的外部创建实例。(放到static关键字后讲)
4.案例一
package com.atguigu07.encapsulation;
public class AnimalTest {
public static void main(String[] args) {
Animal animal1 = new Animal();
animal1.name = "金蟾";
//因为legs声明为private,是私有的,出了Animal类之外就不能调用了。
// animal1.legs = 4;
// animal1.legs = -4;
//只能通过setLegs(),间接的对legs属性进行赋值。
animal1.setLegs(2);
animal1.setLegs(-2);
// System.out.println("name = " + animal1.name + ", legs = " + animal1.legs);
System.out.println("name = " + animal1.name + ", legs = " + animal1.getLegs());
animal1.eat();
}
}
class Animal{ //动物
//属性
String name; //名字
private int legs;//腿的个数
//方法
//设置legs的属性值
public void setLegs(int l){
if(l >= 0 && l % 2 == 0){
legs = l;
}else{
System.out.println("你输入的数据非法");
}
}
//获取legs的属性值
public int getLegs(){
return legs;
}
public void eat(){
System.out.println("动物觅食");
}
}
//private class AA{}
在题目中,我们给Animal的对象的legs属性赋值。在实际的常识中,我们知道legs不能赋值为负数的。但是如果
直接调用属性legs,是不能加入判断逻辑的。那怎么办呢?
将legs属性私有化(private),禁止在Animal类的外部直接调用此属性
提供给legs属性赋值的setLegs()方法,在此方法中加入legs赋值的判断逻辑if(legs >= 0 && legs % 2 ==0)
将此方法暴露出去,使得在Animal类的外部调用此方法,对legs属性赋值。
提供给legs属性获取的getLegs()方法,此方法对外暴露。使得在Animal类的外部还可以调用此属性的值。
5.案例二
EmployeeTest类
package com.atguigu07.encapsulation.exer3;
import java.util.Scanner;
public class EmployeeTest {
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
//创建Employee[]
Employee[] emps = new Employee[2];
for (int i = 0; i < emps.length; i++) {
emps[i] = new Employee();
System.out.println("----------添加第" + (i + 1) + "个员工----------");
System.out.print("姓名:");
String name = scan.next();
System.out.print("性别:");
char gender = scan.next().charAt(0);
System.out.print("年龄:");
int age = scan.nextInt();
System.out.print("电话:");
String phoneNumber = scan.next();
//给指定的employee对象的各属性赋值
emps[i].setName(name);
emps[i].setGender(gender);
emps[i].setAge(age);
emps[i].setPhoneNumber(phoneNumber);
}
//遍历员工列表
System.out.println("---------------员工列表------------------");
System.out.println("编号\t姓名\t性别\t年龄\t电话");
for (int i = 0; i < emps.length; i++) {
System.out.println((i + 1) + "\t" + emps[i].getInfo());
}
System.out.println("---------------员工列表完成------------------");
}
}
Employee类
package com.atguigu07.encapsulation.exer3;
public class Employee {
//属性
private String name;
private char gender;
private int age;
private String phoneNumber;
//提供属性的get和set方法
public void setName(String n) {
name = n;
}
public String getName() {
return name;
}
public void setGender(char g) {
gender = g;
}
public char getGender() {
return gender;
}
public void setAge(int a) {
age = a;
}
public int getAge() {
return age;
}
public void setPhoneNumber(String pn) {
phoneNumber = pn;
}
public String getPhoneNumber() {
return phoneNumber;
}
public String getInfo(){
// return name + "\t" + gender + "\t" + age + "\t" + phoneNumber;
return getName() + "\t" + getGender() + "\t" + getAge() + "\t" + getPhoneNumber();
}
}