面向对象三大特征
一、封装
将数据连同函数捆绑在一起,形成新的类型,这被称为封装。
java语言中,对象就是对一组变量和相关方法的封装,其中变量表明了对象的状态,方法表明了对象具有的行为。
通过对象的封装,实现了模块化和信息隐藏。通过对类的成员施以一定的访问权限,实现了类中成员的信息隐藏。
程序设计追求“高内聚,低耦合”,高内聚就是类的内部数据操作细节自己完成,不允许外部干涉;低耦合:仅暴露少量的方法给外部使用。
封装(数据的隐藏),通常,应禁止直接访问一个对象中数据的实际表示,而应通过操作接口来访问,这称为信息隐藏
二、继承
继承性是面向对象程序设计语言的另一基本特征,通过继承可以实现代码的复用。继承而得到的类为子类,被继承的类为父类(超类),父类包括所有直接或间接被继承的类。
Java中不支持多重继承,java支持单一的继承。一个子类只能有一个直接的父类
继承是类和类之间的一种关系。除此之外,类和类之间的关系还有依赖、组合、聚合等。
子类无法继承父类的私有方法
1、object类
在Java中,所有的类,都默认直接或者间接继承object类
2、extends关键字
子类可继承父类中的变量及方法,也可定义其自身特有的变量及方法。
继承关系的两个类,一个为子类(派生类),一个是父类(基类)。子类继承父类,使用关键字extends来表示。
子类中不需要再重复定义共有属性,对象实例化后可以直接调用父类中的变量及方法
3、super关键字
this用来标记对象属性
super用来标记父类中的属性
子类构造方法执行的时候,默认先执行了父类无参构造方法
public class Student extends Person{
public Student() {
super();//默认隐藏,调用了父类的无参构造方法;调用父类无参构造方法,必须要在子类构造方法的第一行(不存在同时调用父类无参和有参构造器)
System.out.println("子类构造执行");
}
}
//若父类中,没有无参构造器(只存在有参构造器时,无参构造默认不存在),子类无法创建无参构造器。因此需要手动将隐藏的super();更改成有参构造器
public class Student extends Person{
public Student() {
super("xiaoming");
System.out.println("子类构造执行");
}
}
4、super VS this
代表对象不同:
this:本身调用者这个对象
super:代表父类对象的应用
前提:
this:没有继承也可以使用
super:只能在继承条件下才可以使用
构造方法:两者都需要在构造器的第一行,因此不能同时出现在构造器中
this():本类的构造
super():父类的构造
5、final关键字
final在类之前 表示该类是最终类,表示该类不能再被继承。
final在方法之前 表示该方法是最终方法,该方法不能被任何派生的子类覆盖。(不能被重写)
final在变量之前 表示变量的值在初始化之后就不能再改变;相当于定义了一个常量。
6、重写
需要有继承关系,子类重写父类的方法!
①方法名必须相同
②参数列表必须相同
③修饰符:范围可以扩大(public>protected>Default>private)
④方法体不同
不同于方法的重载
为什么需要重写?
①父类的功能,子类不一定需要,或者不一定满足!
三、多态
即同一方法可以根据发送对象的不同而采用多种不同的行为方式
一个对象的实际类型是确定的,但可以指向对象的引用的类型有很多
多态是方法的多态,属性没有多态性
多态存在的条件:
①有继承关系
②子类重写父类方法
③父类引用指向子类对象
1、上转型对象(上溯)
在现实世界中我们说 ”老虎是哺乳动物” ,若哺乳类是老虎类的父类,这样说当然正确,但当你说老虎哺乳动物时,老虎将失掉老虎独有的属性和功能。
如果A类是B类的父类,当我们用子类创建对象,并把这个对象的引用放到父类的对象中时:称父类对象a是子类对象b的上转型对象。
上转型对象的实体是子类负责创建的,所以上转型对象失去原对象一些属性和功能
public class Test {
public static void main(String[] args) {
//一个对象的实际类型是确定的 new B();
//可以指向的引用类型就不确定了,父类的引用指向子类
A a = new B();//上转型对象(上溯)
B b = new B();
Object c = new B();//上转型对象(上溯)
b.son();
b.father();
b.pub();
System.out.println("==================");
a.father();//上溯之后,继承的方法依旧可以使用
//a.son();//上溯之后,失去了子类独有的方法
a.pub();//上溯之后,继承的方法依旧可以使用
//若子类重写了父类的方法,则执行子类的方法
System.out.println("==================");
//c.son();//上溯之后,失去了子类独有的方法
//c.father();//上溯之后,失去了子类独有的方法
//c.pub();//上溯之后,失去了子类独有的方法
}
}
2、下溯
可以将对象的上转型对象再强制转换到一个子类对象,这时,该子类对象又具备了子类所有属性和功能;(即下溯)
不可以将父类创建的对象的引用赋值给子类声明的对象(不能说”哺乳动物是老虎”);
下溯不可以下溯到其他子类,只能下溯到上溯的子类
public class Test {
public static void main(String[] args) {
A a = new B();//上转型对象(上溯)
B b = new B();
Object c = new B();//上转型对象(上溯)
a.father();//
((B)a).son();//上溯之后,若继续使用子类独有的方法,则需要强制类型转化(下溯)
a.pub();
System.out.println("==================");
((B)c).son();//上溯之后,若继续使用子类独有的方法,则需要强制类型转化(下溯)
((B)c).father();//上溯之后,若继续使用子类独有的方法,则需要强制类型转化(下溯)
((B)c).pub();//上溯之后,若继续使用子类独有的方法,则需要强制类型转化(下溯)
}
}
3、Java绑定原理(因为有了动态绑定机制才能实现Java中的多态行为)
①静态绑定(前期绑定)
编译期间进行的绑定(静态绑定或者前期绑定) 对象的属性以及对象的类方法与变量的声明类型进行绑定叫做前期绑定
//静态绑定(前期绑定):对象的属性以及对象的类方法与变量的声明类型进行绑定叫做前期绑定
//前期绑定看对象左边,具体绑定了什么方法属性,看类的说明
b.son();
b.father();
b.pub();
"========================================================================="
//父类A和Object,都没有B类中特有的方法,因此不能访问子类新增
a.father();//上溯之后,继承的方法依旧可以使用
//a.son();//上溯之后,失去了子类独有的方法
a.pub();//上溯之后,继承的方法依旧可以使用
//若子类重写了父类的方法,则执行子类的方法
//c.son();//上溯之后,失去了子类独有的方法
//c.father();//上溯之后,失去了子类独有的方法
//c.pub();//上溯之后,失去了子类独有的方法
②动态绑定
Java在运行时动态决定实例方法的调用叫做后期绑定(late binding) 根据具体引用的实体来决定实例方法的调用叫运行期绑定
//后期期绑定看对象右边,具体运行哪个方法的实现,要具体new的是谁,new的是谁就看那个类
a.pub();//上溯之后,由于子类重写了父类中的方法,调用的是子类中的重写方法
4、instanceof关键字
用来判断两个类之间是否存在父子关系
public class Application {
//object>String
//object>Person>Teacher
//object>Person>Student
//X instanceof Y,X所指向的实际类型,是否为Y的子类型
public static void main(String[] args) {
Object object = new Student();
System.out.println(object instanceof Student);//true
System.out.println(object instanceof Person);//true
System.out.println(object instanceof Object);//true
System.out.println(object instanceof Teacher);//false
System.out.println(object instanceof String);//false
System.out.println("======================");
Person person = new Student();
System.out.println(person instanceof Student);//true
System.out.println(person instanceof Person);//true
System.out.println(person instanceof Object);//true
System.out.println(person instanceof Teacher);//false
//System.out.println(person instanceof String);编译错误
System.out.println("======================");
Student student = new Student();
System.out.println(student instanceof Student);//true
System.out.println(student instanceof Person);//true
System.out.println(student instanceof Object);//true
//System.out.println(student instanceof Teacher);编译错误
//System.out.println(student instanceof String);编译错误
}
}
5、抽象类
//abstract抽象类
//抽象类的所有方法,继承了它的子类,都必须要实现它的方法(重写)
public abstract class Action {
//abstract抽象方法,只有方法名,没有方法的实现
public abstract void doSomething();
}
//若子类依然为抽象类,则子子类必须重写父类方法,以此类推
抽象类不能被直接实例化。它只能作为其它类的超类,这一点与最终类(final类)正好相反。(不能new这个抽象类,只能靠子类去实现它)
定义了抽象方法的类必须是抽象类,抽象类中可以存在非抽象的方法
6、接口
接口(interface)就是方法定义和常量值的集合。从语法上讲,接口是一种特殊的抽象类,这种抽象类中只包含常量和方法的定义,而没有方法的实现。
通过接口可以实现不相关类的相同行为,而不需要考虑这些类之间的层次关系。
通过接口可以指明多个类需要实现的方法。
通过接口可以了解对象的交互界面,而不需了解对象所对应的类。
接口可以多继承,若要继承该接口,就要重写接口中定义的方法
package com.gok.demo02;
//接口中的方法和常量必须是public的。
public class UserServiceImpl implements UserService,TimeService{
//多继承只需要逗号隔开,并重写方法
@Override
public void add(String name) {
}
@Override
public void delete(String name) {
}
@Override
public void update(String name) {
}
@Override
public void query(String name) {
}
@Override
public void timer() {
}
}
7、Java 8接口新特性
Java 8允许我们给接口添加一个非抽象的方法实现,并且有方法体,只需要使用 default或static关键字即可,这个特征又叫做扩展方法
public interface MyInterface{
int a = 10;
void draw(int i);
default void method(){
System.out.println("default修饰");
}
static void d(){
System.out.println("static修饰");
}
}
子类继承的多个接口中同时存在同名,同参数的静态方法 。子类在调用父类的静态方法时,需要用父接口名.静态方法名。若该静态方法如果在子类中也定义了,它是不算被重写的。
如果两个接口里的方法名和参数相同都是default方法,里面的方法体不同,在类中需要重写该方法。
如果两个接口中方法名,参数都相同的方法,一个接口是抽象方法,另一个是default修饰有方法体。这是该类也必须重写该方法。
{
System.out.println(“default修饰”);
}
static void d(){
System.out.println(“static修饰”);
}
}
> 子类继承的多个接口中同时存在同名,同参数的静态方法 。子类在调用父类的静态方法时,需要用父接口名.静态方法名。若该静态方法如果在子类中也定义了,它是不算被重写的。
>
> 如果两个接口里的方法名和参数相同都是default方法,里面的方法体不同,在类中需要重写该方法。
>
> 如果两个接口中方法名,参数都相同的方法,一个接口是抽象方法,另一个是default修饰有方法体。这是该类也必须重写该方法。
>
> 如果一个类实现一个接口的默认方法,同时又继承了另外一个类的方法。 那么子类的方法优先跟父类的方法行为一致。