前言
其实封装、继承和多态不仅仅是java的特性,而是所有面向对象程序的三大特性。
一、什么是封装?
封装就是对类内部的实现细节进行隐藏,然后对类外提供公开的接口。
在Java 中主要通过访问权限来实现封装, 访问权限用来控制方法或者属性能否直接在类外使用 。 Java 中提供了四种访问限定符:
封装一般就是我们把类属性加上private进行修饰,把属性进行私有化。
public class Student { private String name; private int age; private int classid; }
在这个学生类中,我们把name和age以及classid属性被设置为私有的,那么它只能被这个类访问,而不能被其他类访问,因此信息是隐藏的。为了让外部进行访问,我们还可以为每个属性提供公开的方法:Getter and Setter
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 int getClassid() { return classid; } public void setClassid(int classid) { this.classid = classid; }
因此,如果外部类想要访问类中私有成员变量的都必须使用这些getter和setter方法。
封装的优点:良好的包装可以减少耦合;类的内部结构可以自由修改;可以更精确地控制成员变量;隐藏信息和实现细节。
二、什么是继承?
在Java中,可以通过extends关键字申明一个类是从另一个类继承而来的:
class 父类 { } class 子类 extends 父类 { }
继承其实是父类对子类的共性的抽取, 实现代码的复用。
子类中访问父类的成员变量
如果访问的成员变量子类中有,优先访问自己的成员变量。
如果访问的成员变量子类中无,则访问父类继承下来的,如果父类也没有定义,则编译报错。
如果访问的成员变量与父类中成员变量同名,则优先访问自己的。
成员变量访问遵循就近原则,自己有优先自己的,如果没有则向父类中找 。
子类中访问父类的成员方法
通过子类对象访问父类与子类中不同名方法时,优先在子类中找,找到则访问,否则在父类中找,找到 则访问,否则编译报错。
通过派生类对象访问父类与子类同名方法时,如果父类和子类同名方法的参数列表不同 ( 重载 ) ,根据调用方法适传递的参数选择合适的方法访问,如果没有则报错;
如果子类中存在与父类中相同的成员时,那么在子类中访问父类相同名称的成员就需要使用super关键字。super关键字的主要作用:在子类方法中访问父类的成员。了解super可以参考这篇文章。
super和this有什么区别?-java_crazy__xieyi的博客-CSDN博客
三、什么是多态?
一个引用调用同一个方法,因为这个引用 引用的对象不一样,导致调用这个方法,所表现出来的行为不一样。这种思想就叫做多态。
在 java 中要实现多态,必须要满足如下几个条件,缺一不可:
1. 必须在继承体系下
2. 子类必须要对父类中方法进行重写
3. 通过父类的引用调用重写的方法
多态体现:在代码运行时,当传递不同类对象时,会调用对应类中的方法。
public class Animal { String name; int age; public Animal(String name, int age){ this.name = name; this.age = age; } public void eat(){ //重写了eat方法 System.out.println(name + "吃饭"); } } public class Cat extends Animal{ public Cat(String name, int age){ super(name, age); } @Override //重写了eat方法 public void eat(){ System.out.println(name+"吃鱼~~~"); } } public class Dog extends Animal { public Dog(String name, int age){ super(name, age); } @Override public void eat(){ System.out.println(name+"吃骨头~~~"); } } ///分割线// public class TestAnimal { // 编译器在编译代码时,并不知道要调用Dog 还是 Cat 中eat的方法 // 等程序运行起来后,形参a引用的具体对象确定后,才知道调用那个方法 // 注意:此处的形参类型必须时父类类型才可以 public static void eat(Animal a){ a.eat(); } public static void main(String[] args) { Cat cat = new Cat("元宝",2); Dog dog = new Dog("小七", 1); eat(cat); //元宝吃鱼 eat(dog); //小七吃骨头 } }
在上述代码中 , 分割线上方的代码是 类的实现者 编写的 , 分割线下方的代码是 类的调用者 编写的 .
当类的调用者在编写 eat 这个方法的时候 , 参数类型为 Animal ( 父类 ), 此时在该方法内部并 不知道 , 也不关注 当前的 a 引用指向的是哪个类型 ( 哪个子类 ) 的实例 . 此时 a 这个引用调用 eat 方法可能会有多种不同的表现 ( 和 a 引用的实例相关), 这种行为就称为 多态。