封装性的设计思想
在程序设计的过程中,我们追求“高内聚,低耦合”
高内聚:类的内部数据操作细节自己完成,不允许外部干涉
低耦合:仅对外暴露少量的方法用于使用。
隐藏对象内部的复杂性,只对外公开简单的接口。便于外界调用,从而提高系统的可扩展性、可练护性、通俗的说,把该隐藏的隐藏起来,该是露的是露出来。这就是封装性的设计思想
问题的引入
当我们创建一个类的对象以后,我们可以通过“对象.属性”的方式,对对象的属性进行赋值。这里,赋值操作要受属性的数据类型和存储范围的制约。除此之外,没有其他制约条件。
但是,在实际问题中,我们往往需要给属性附加额外的限制条件。这个条件就不能在属性声明时体现,我们只能通过方法进行限制条件的添加(例如下面代码中的setAge()方法)。同时,我们需要避免用户再使用“对象.属性”的方式对属性进行赋值。此时需要将属性声明为私有的(private)。
此时,针对属性就体现了封装性。
class Person{
private int age;
public void setAge(int num){
age = num;
}
public int getAge(int num){
return age;
}
}
由于我们此时将属性声明为了private,我们就不能在类的外部通过“对象.属性”的方式直接获取某个属性的值。因此,在实际中,当我们将一个属性声明为private时,通常我们还会提供获取和设置属性值的公共的(public)方法,即上面代码中的getAge()、setAge()方法。
四种权限修饰符
Java一共提供了四种访问权限修饰符,按照权限从小到大依次为:private、缺省、protected、public。其具体的权限大小如下表所示:
修饰符 | 类内部 | 同一个包 | 不同包的子类 | 同一个工程 |
---|---|---|---|---|
private | Yes | No | No | No |
缺省 | Yes | Yes | No | No |
protected | Yes | Yes | Yes | No |
public | Yes | Yes | Yes | Yes |
注意:对于class的权限修饰只可以用public和default(缺省)
public类可以在任意地方被访问。
default类只可以被同一个包内部的类访问。
四种权限可以用来修饰类及类的内部结构:属性、方法、构造器、内部类。
下面进行代码测试:
工程的结果如图所示:
在一个类的内部,四种权限修饰符修饰的属性都可以直接调用
public class TestClass1 {
int age;
private double height;
public String name;
protected String gender;
public static void main(String[] args) {
TestClass1 c1 = new TestClass1();
c1.name = "Tom";
c1.age = 20;
c1.gender = "男";
c1.height = 180.5;
}
}
在同一个包下,再创建一个类Test2,在Test2中调用TestClass1 中的属性,此时发现由于“height”属性声明为了private,所以在Test2中,无法调用。其余三个属性可正常调用
package pack1;
public class Test2 {
public static void main(String[] args) {
TestClass1 c2 = new TestClass1();
c2.name = "Jerry";
c2.age = 25;
c2.gender = "女";
// c2.height = 160.0; // 会报错
}
}
在不同包下调用,此时只有声明为protected和public的属性可以被调用,其余两个属性则不能被调用。(TestClass2 继承了TestClass1 ,是TestClass1 的一个子类)
package pack2;
import pack1.TestClass1;
public class TestClass2 extends TestClass1 {
public static void main(String[] args) {
TestClass2 c2 = new TestClass2();
c2.name = "张三";
c2.gender = "男";
// c2.age = 20; // 会报错
// c2.height = 175.0; // 会报错
}
}
小Tips
有时,我们将类的某些属性声明为了private,当我们想在外部调用或者对其赋值时,需要编写相应的public方法,如前面的setAge()和getAge()方法。当private属性过多时,手写其方法过于繁琐。不过Eclipse为我们提供了自动化的方法。具体步骤为:
声明一个类及属性:
class Test{
private int age;
private double salary;
private String name;
}
然后点击Source——》Generate Getters and Setters(或者快捷键:Alt+Shift+s)
根据需要选择相应的方法:
然后点击Generate,系统就直接为我们生成了相应的方法。
class test{
private int age;
private double salary;
private String name;
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public double getSalary() {
return salary;
}
public void setSalary(double salary) {
this.salary = salary;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}