1.对封装的理解
需要让用户知道的才暴露出来,不需要让用户知道的全部隐藏起来,这就是封装。说的专业一点,封装就是把对象的属性和操作结合为一个独立的整体,并尽可能隐藏对象的内部实现细节。
我们程序设计要追求“高内聚,低耦合”。 高内聚就是类的内部数据操作细节自己完成,不允许外部干涉;低耦合是仅暴露少量的方法给外部使用,尽量方便外部调用。
编程中封装的具体优点:
1. 提高代码的安全性。
2. 提高代码的复用性。
3. “高内聚”:封装细节,便于修改内部代码,提高可维护性。
4. “低耦合”:简化外部调用,便于调用者使用,便于扩展和协作。
2.封装的实现—使用访问控制符
Java是使用“访问控制符”来控制哪些细节需要封装,哪些细节需要暴露的。 Java中4种“访问控制符”分别为private、default、protected、public,它们说明了面向对象的封装性,所以我们要利用它们尽可能的让访问权限降到最低,从而提高安全性。
下面详细讲述它们的访问权限问题。其访问权限范围如表5-1所示。
表5-1 访问权限修饰符
修饰符 | 同一个类中 | 同一个包中 | 子类 | 所有类 |
---|---|---|---|---|
private | √ | × | × | × |
default | √ | √ | × | × |
protected | √ | √ | √ | × |
public | √ | √ | √ | √ |
1. private 表示私有,只有自己类能访问
2. default表示没有修饰符修饰,只有同一个包的类能访问
3. protected表示可以被同一个包的类以及其他包中的子类访问
4. public表示可以被该项目的所有包中的所有类访问
3.封装的使用细节
类的属性的处理:
1. 一般使用private访问权限。
2. 提供相应的get/set方法来访问相关属性,这些方法通常是public修饰的,以提供对属性的赋值与读取操作(注意:boolean变量的get方法是is开头!)。
-
一些只用于本类的辅助性方法可以用private修饰,希望其他类调用的方法用public修饰。
public class Person { // 属性一般使用private修饰 private String name; private int age; private boolean man; // 为属性提供public修饰的set/get方法 public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public boolean isMan() {// 注意:boolean类型的属性get方法是is开头的 return man; } public void setMan(boolean man) { this.man = man; } }
4.多态、多态的三个条件
多态指的是同一个方法调用,由于对象不同可能会有不同的行为。现实生活中,同一个方法,具体实现会完全不同。 比如:同样是调用人的“休息”方法,张三是睡觉,李四是旅游,高淇老师是敲代码,数学教授是做数学题; 同样是调用人“吃饭”的方法,中国人用筷子吃饭,英国人用刀叉吃饭,印度人用手吃饭。
所谓多态就是指程序中定义的引用变量所指向的具体类型和通过该引用变量发出的方法调用在编程时并不确定,而是在程序运行期间才确定,即一个引用变量倒底会指向哪个类的实例对象,该引用变量发出的方法调用到底是哪个类中实现的方法,必须在由程序运行期间才能决定。因为在程序运行时才确定具体的类,这样,不用修改源程序代码,就可以让引用变量绑定到各种不同的类实现上,从而导致该引用调用的具体方法随之改变,即不修改程序代码就可以改变程序运行时所绑定的具体代码,让程序可以选择多个运行状态,这就是多态性
多态的要点:
1. 多态是方法的多态,不是属性的多态(多态与属性无关)。
2. 多态的存在要有3个必要条件:继承,方法重写,父类引用指向子类对象。
3. 父类引用指向子类对象后,用该父类引用调用子类重写的方法,此时多态就出现了。
public class TestPolym {
public static void main(String[] args) {
Animal a = new Animal();
animalCry(a);
Animal d = new Dog();
animalCry(d);
animalCry(new Cat());
}
static void animalCry(Animal a) {
a.shout();
}
}
class Animal {
public void shout() {
System.out.println("叫了一声!");
}
}
class Dog extends Animal {
public void shout() {
System.out.println("旺旺旺!");
}
public void seeDoor() {
System.out.println("看门中....");
}
}
class Cat extends Animal {
public void shout() {
System.out.println("喵喵喵喵!");
}
}
多态的主要优势是提高了代码的可扩展性,符合开闭原则。但是多态也有弊端,就是无法调用子类特有的功能,比如,我不能使用父类的引用变量调用Dog类特有的seeDoor()方法。
如果我们就想使用子类特有的功能,那就要用到对象的转型。
对象的转型
- 父类引用指向子类对象,我们称这个过程为向上转型,属于自动类型转换。
- 向上转型后的父类引用变量只能调用它编译类型的方法,不能调用它运行时类型的方法。这时,我们就需要进行类型的强制转换,我们称之为向下转型!
public class TestPolym {
public static void main(String[] args) {
Animal a = new Animal();
animalCry(a);
Animal d = new Dog();//自动向上转型 Dog转成Animal
Dog d2 = (Dog)d;//强制向下转型Animal转成Dog
d2.seeDoor();//转回来是为了能够使用子类的seeDoor方法,如果对d2不转回Dog无法通过编译
animalCry(d);
Animal C = new Cat();
Dog D = (Dog) C;//将Animal C强制转换成一直Dog D,虽然能通过编译但是运行会报错,因为C的本质是Cat,必须将引用变量转成真实的子类类型
}
static void animalCry(Animal a) {
a.shout();
}
}
class Animal {
public void shout() {
System.out.println("叫了一声!");
}
}
class Dog extends Animal {
public void shout() {
System.out.println("旺旺旺!");
}
public void seeDoor() {
System.out.println("看门中....");
}
}
class Cat extends Animal {
public void shout() {
System.out.println("喵喵喵喵!");
}
}
在向下转型过程中,必须将引用变量转成真实的子类类型(运行时类型)否则会出现类型转换异常ClassCastException。 为了避免出现这种异常,我们可以使用instanceof运算符进行判断。
5.final关键字
给谁加final,就表明不能被更改了,已经是最终的形态了。你可以用,但是你不能改。
final关键字的作用:
1. 修饰变量: 被他修饰的变量不可改变。一旦赋了初值,就不能被重新赋值。
2. 修饰方法:该方法不可被子类重写。但是可以被重载!
3. 修饰类: 修饰的类不能被继承。比如:Math、String等。