面向对象的三大基本特征:
- 封装
- 继承
- 多态
封装
该露的露,该藏的藏
- 我们程序设计要追求“高内聚,低耦合”,高内聚就是类的内部数据操作细节自己完成,不允许外部干涉;低耦合:仅暴露少量的方法给外部使用
封装(数据的隐藏)
- 通常,应禁止直接访问一个对象中数据的实际表示,而应通过操作接口来访问,这称为信息隐藏
记住这句话就够了:属性私有(private),get/set(私有属性只能本类才能访问,不能被外部访问,可通过get、set方法进行调用)
可以用快捷键(fn)+alt + insert 来自动生成get和set方法
封装的好处:
- 提高代码的安全性,保护数据
- 类内部的结构可以自由修改
- 隐藏代码的实现细节
- 统一接口(都通过get、set方法来调用)
- 系统可维护增加了
继承(extends)
继承就是子类继承父类的特征和行为,使得子类对象(实例)具有父类的实例域和方法,或子类从父类继承方法,使得子类具有父类相同的行为。
-
extends的意思是“扩展”。子类是父类的扩展
-
Java中类只有单继承,没有多继承。(一个儿子只能有一个父亲,而父亲可以有多个儿子)
-
继承是类和类之间的一种关系。除此之外,类和类之间的关系还有依赖、组合、聚合等
-
继承关系的两个类,一个为子类(派生类),一个为父类(基类)。子类继承父类,使用关键字extends来表示
-
子类和父类之间,从意义上将应该具有“is a”的关系
-
子类继承父类,就会拥有父类的所有方法!但是私有的东西无法被继承
-
继承有以下目的:
-
复用代码,减少类的冗余代码,减少开发工作量。
-
使得类与类之间产生关系,为多态的实现打下基础
-
//人 :父类
public class Person {
}
//student is 人 :子类
public class Student extends Person{
}
//teacher is 人 :子类
public class Teacher extends Person{
}
继承的注意事项:
- 子类不能继承父类 private 的属性、方法。
- 使用 final 关键字声明类,就是把类定义定义为最终类,不能被继承,或者用于修饰方法,该方法不能被子类重写
- 子类是不继承父类的构造器(构造方法或者构造函数)的,它只是调用(隐式或显式)。
object类
-
Object 类是所有类的父类,也就是说 Java 的所有类都默认直接或间接继承了 Object,子类可以使用 Object 的所有方法。
-
Object 类位于 java.lang 包中,编译时会自动导入,我们创建一个类时,如果没有明确继承一个父类,那么它就会自动继承 Object,成为 Object 的子类。
-
Object 类可以显示继承,也可以隐式继承,以下两种方式时一样的:
显示继承
public class Student extends Object{
}
隐式继承
public class Student {
}
- idea中的快捷键Ctrl+H:可以查看类的继承关系
super关键字
-
super 可以理解为是指向自己父(超)类对象的一个指针,而这个父类类指的是离自己最近的一个父类。
-
我们可以通过super关键字来实现对父类成员的访问,用来引用当前对象的父类。
-
只能出现在有继承关系的子类中
-
super的用法:
-
super.属性名、super.方法名(参数列表)
-
表示父类的属性和方法,和子类中的属性或方法重名时使用
-
-
super 有三种用法:
- 普通的直接引用
与 this 类似,super 相当于是指向当前对象的父类,这样就可以用 super.xxx 来引用父类的成员
例子:
执行结果:
-
子类中的成员变量或方法与父类中的成员变量或方法同名
-
引用构造函数
- super(参数):调用父类中的某一个构造函数(应该为构造函数中的第一条语句)。
- this(参数):调用本类中另一种形式的构造函数(应该为构造函数中的第一条语句)
super注意点:
- super调用父类的构造方法,必须在构造方法的第一个
- super 必须只能出现在子类的方法或者构造方法中
- super 和 this 不能同时调用构造方法
this关键字
this 是自身的一个对象,代表对象本身,指向自己的引用,可以理解为:指向对象本身的一个指针。
this 的用法在 Java 中大体可以分为3种:
-
普通的直接引用
this 相当于是指向当前对象本身。
-
形参与成员名字重名,用 this 来区分:
class Person {
private int age = 10;
public Person(){
System.out.println("初始化年龄:"+age);
}
public int getAge(int age){
this.age = age; //age指形参,this.age指成员变量
return this.age;
}
}
public class test {
public static void main(String[] args) {
Person Jay = new Person();
System.out.println("Jay's age is "+Jay.GetAge(12));
}
}
运行结果:
初始化年龄:10
Jay's age is 12
可以看到,这里 age 是 getAge 成员方法的形参,this.age 是 Person 类的成员变量。
- 引用构造函数
super与this的异同:
-
代表的对象不同:
a. this:指本身调用者这个对象
b. super:代表父类对象的应用 -
前提:
a. this:没有继承也可以使用
b. super:只能在继承条件下才可以使用 -
构造方法:
a. this():本类的构造
b. super():父类的构造 -
调用对象:
a. super() 从子类中调用父类的构造方法
b. this() 在同一类内调用其它方法。 -
super() 和 this() 均需放在构造方法内第一行
-
this 和 super 不能同时出现在一个构造函数里面
-
this() 和 super() 都指的是对象,所以,均不可以在 static 环境中使用。包括:static 变量,static 方法,static 语句块。
-
从本质上讲,this 是一个指向本对象的指针, 然而 super 是一个 Java 关键字。
方法重写
为什么需要重写?因为父类的功能,子类不一定需要,或者不一定满足
-
重写都是方法的重写,和属性无关
-
在idea中,override是重写的意思,可以用快捷键(fn)+alt+insert生成
-
需要有继承关系,子类重写父类的方法
- 子类和父类的方法名必须相同
- 参数列表必须相同(不相同的话就是方法重载)
- 修饰符:范围可以被缩小,但不能扩大:public>protected>default>private
- 重写抛出的异常:范围可以被缩小,但不能扩大
- 静态方法和非静态方法有很大区别:
(1)在静态方法中:方法的调用只和左边定义的数据类型有关,但是没有重写方法
输出结果:
(2)在非静态方法中:子类重写父类的方法
输出结果:
注意:方法重写,子类的方法和父类的方法必须一致,方法体不同!!
多态
-
即同一方法可以根据发送对象的不同而采用多种不同的行为方式
-
一个对象的实际类型是确定的,但可以指向对象的引用的类型又很多
-
面向对象的多态性,即“一个接口,多个方法”。
-
多态性体现在父类中定义的属性和方法被子类继承后,可以具有不同的属性或表现方式。
-
多态性允许一个接口被多个同类使用,弥补了单继承的不足。
-
instanceof
-
多态存在的条件:
- 有继承关系
- 子类重写父类方法
- 父类引用指向子类对象
例子
执行结果:
利用父类类型实例化,子类覆写父类的方法后,运行时,动态的再指向子类的实现,即为多态
- 多态注意事项:
- 多态是方法的多态,属性没有多态性
- 父类和子类,要有联系,否则会出现类型转换异常! ClassCastException
- 存在条件:继承关系,方法需要重写,父类引用指向子类对象! Father f1 = new Son();
多态的实现方式
方式一:方法重写:
方式二:接口
-
生活中的接口最具代表性的就是插座,例如一个三接头的插头都能接在三孔插座中,因为这个是每个国家都有各自规定的接口规则,有可能到国外就不行,那是因为国外自己定义的接口类型。
-
java中的接口类似于生活中的接口,就是一些方法特征的集合,但没有方法的实现。
方式三:抽象类和抽象方法
instanceof
instanceof 是 Java 的一个二元操作符,类似于 ==,>,< 等操作符。
作用:测试它左边的对象是否是它右边的类的实例,返回 boolean 的数据类型,例如检查两者是否存在父类和子类关系
语法:X instanceof Y
例子:
父类可以调用子类方法,但是不能调用子类中父类没有的方法,这时我们可以通过类型转换来进行调用,通过父类和子类之间的类型转换
- 父类转换子类(强制转换)
- 子类转换父类(自动转换),但是可能会丢失自己的本来的一些方法!
父类类型 对象名 = new 子类类型();