一、类的封装
类的封装是指将类的属性和方法进行封装,形成一个不可分割的整体,以达到保护数据的目的,同时只提供对外的相应接口,调用者只知道作用而不知道具体的实现细节
二、类的封装的实现
1、一个私有的域成员变量
2、一个公有的域访问器方法
3、一个公有的域更改器方法
以下则对people类的age、name属性做了封装
public class People
{
private String name; //私有的域成员
private int age; //私有的域成员
/*
* 公有的域访问器方法
*/
public int getAge()
{
return this.age;
}
/*
* 公有的域更改器方法
*/
public void setAge(int age)
{
this.age=age;
}
/*
* 公有的域访问器方法
*/
public String geName()
{
return this.name;
}
/*
* 公有的域更改器方法
*/
public void setAge(String name)
{
this.name=name;
}
}
三、为什么要用封装?
1)当类成员结构修改变化时,只需修改更改器或访问器方法,而不用修改调用代码,减少修改次数
当未使用封装时,如果我要修改age属性为String,需要修改4处地方,若对象越多,那么修改的地方越多
public class Test
{
public int age; //需修改成public String age
public String name;
public static void main(String[] args)
{
Test a = new Test();
a.age = 20; //需修改成a.age="20";
a.name = "张三";
Test b = new Test();
b.age = 22; //需修改成a.age="22";
b.name = "李四";
Test c = new Test();
c.age = 25; //需修改成a.age="25";
c.name = "王五";
}
}
使用封装时,若修改age属性为String,那么只需要修改属性类型、域更改器、域访问器方法即可,其余调用代码处都不用修改
public class People
{
private String name; // 私有的域成员
private int age; // 私有的域成员 ----修改成String类型
/*
* 公有的域访问器方法
*/
public int getAge()
{
return this.age; //需修改成return Integer.valueOf(this.age) 不改变返回类型
}
/*
* 公有的域更改器方法
*/
public void setAge(int age)
{
this.age = age; // 需要修改成 this.age = age+""; 代表了String类型
}
/*
* 公有的域访问器方法
*/
public String geName()
{
return this.name;
}
/*
* 公有的域更改器方法
*/
public void setName(String name)
{
this.name = name;
}
public static void main(String[] args)
{
People a = new People();
a.setAge(20); //不用修改
a.setName("张三");
People b = new People();
a.setAge(22); //不用修改
a.setName("李四");
People c = new People();
a.setAge(25);
a.setName("王五"); //不用修改
}
}
由此可见,当类的属性需要修改时,那么使用封装可以减少修改次数,提高工作效率(一般属性结构是不会轻易变化,但是万一项目写到几十万行时,领导要修改,那么不使用封装的后果就是加班到半夜修改N个调用的地方)
2)、可以对类成员进行更加细致的控制,以减少错误情况产生
若不适用封装,赋值时不小心的输错了,后果可能就无法想象,例如张三的age,输入成了200,李四的age输入成了-20.人类中就多了两个怪物。这是不允许的,有的人想程序会自动检测,但是200和-20都是int型范围内,因此程序检测是可以通过的
public class Test
{
public int age;
public String name;
public static void main(String[] args)
{
Test a = new Test();
a.age = 200;
a.name = "张三";
Test b = new Test();
b.age = -20;
b.name = "李四";
Test c = new Test();
c.age = 25;
c.name = "王五";
}
}
若使用了封装,那么我们可以在域更改器方法中对赋值进行检测,以减少上述错误的产生
public class People
{
private String name; // 私有的域成员
private int age; // 私有的域成员
/*
* 公有的域访问器方法
*/
public int getAge()
{
return this.age;
}
/*
* 公有的域更改器方法
*/
public void setAge(int age) throws Exception
{
if (age < 0 || age > 120) //检测年龄,若输入的值小于0或者大于120岁,那么我们就抛出问题,这个时候程序员就知道了该处有问题,不能这样设置
{
throw new Exception("年龄的值有问题");
}
this.age = age;
}
/*
* 公有的域访问器方法
*/
public String geName()
{
return this.name;
}
/*
* 公有的域更改器方法
*/
public void setName(String name)
{
this.name = name;
}
public static void main(String[] args) throws Exception
{
People a = new People();
a.setAge(200);
a.setName("张三");
People b = new People();
a.setAge(-20);
a.setName("李四");
People c = new People();
a.setAge(25);
a.setName("王五");
}
}
控制台运行结果如下:
3) 隐藏实现细节(调用者只知道会产生什么结果,不用关心实现细节)--即方法的作用
其实方法的作用就是隐藏实现细节,类的方法都可以称是对类的封装,例如A需要生成一个随机数,B需要生成一个随机数那么是A和B都写一遍随机数的生成方法吗?这样太过效率低下,因此可以把生成随机数的方法抽取出来命名为c,然后放置在一个类中。那么A和B就只用实例化含有方法c的类,然后调用方法c即可,因此减少了重复代码数量,提高了效率
4)减少耦合性--这点暂时没有深刻理解,暂时不提