一、封装

封装便是躲藏目标内部的复杂性,只对外揭露简略的接口。

封装的思想是你只需要知道怎么调用接口就行了,不需要去了解内部完成。

  1. 封装的表现:
  • 特点的封装
  • 办法的封装
  • 结构函数的封装(单例模式)

将类的某些信息躲藏在类的内部,不让外部程序直接拜访,而是供给操作数据的办法,这便是特点的封装性。

  1. 封装的完成:
特点的封装:运用private修饰符修饰成员变量,然后根据需求界说getter或setter办法。
办法的封装:有些办法仅仅仅仅在类的内部运用,不希望外部程序调用它,经过private修饰即可。
结构函数的封装:运用private修饰结构器,不让外部程序创立类目标,在类内部实例化目标,并供给公共接口。形如单例模式。

开发建议:在界说类的时分,一切的特点都要用private封装,封装的特点假如需要被外部操作,供给对应的getter和setter办法。

  1. 举例代码
1.
class Person{//特点封装,封装了age和name两个特点,供给了对应的getter和setter办法
    private int age;
    private String name;
    public int getAge() {
        return age;
    }
    public void setAge(int age) {
        this.age = age;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
}
2.
private void swap(int[]arr,int m, int n){  //办法的封装,只要内部办法才干调用
    int temp=arr[m];
    arr[m]=arr[n];
    arr[n]=temp;
}
3.
public class JavaTest {
    public static void main(String[] args) {
         Person p1=Person.getPersonInstance();
    }
}
class Person{
 private Person(){} //结构器的封装
 public static Person getPersonInstance(){
     return  new Person();
 } 
}
  1. 封装的优点
  • 只能经过规矩办法拜访数据
  • 躲藏类数据的完成细节
  • 便利修改完成
  • 便利加入控制句子
  • 能够修改特点的读写权限

二、承继

思考一下:为什么会有承继?

当多个类中存在相同特点和行为时,为了进步代码复用性,将这些相同的内容抽取到一个独自的类中,这些多个类无需再界说这些特点和行为,只要去承继那一个独自的类即可。

此处的多个类称为子类(派生类),独自的这个类称为父类(基类或超类)。能够理解为:“子类 is a 父类”。

承继便是子类承继父类‘一切’的特征和行为,使得子类目标(实例)具有父类的成员变量和办法,还能够在此基础上添加新办法和成员变量来满意需求。

当创立一个类时,总是在承继。Java中的类没有显现的承继任何类,则默许承继Object类,Object类是Java言语供给的根类,也便是说,一个目标与生俱来就有Object类傍边的一切特征。

留意

  • 子类具有父类的一切特点和办法是对的,只不过父类的私有特点和办法,子类是无法直接访到的。即仅仅具有,可是无法运用。(这儿不考虑Java反射机制)可是假如子类中公有的办法影响到了父类私有特点,那么私有特点是能够被子类运用到的。
  • 不能被承继的成员父类:结构办法,结构函数。可是子类能够经过super()显现父类的结构函数。
    Java之封装、继承和多态(超详细)

如上图所示,动物承继生物类,山君又承继动物类。从这个例子能够看出:越往上的类越抽象,越往下的类越具体。

承继规矩

  • Java只支撑单承继和多层承继,不允许多重承继
  • 一个类能够被多个子类承继,一个类只能承继一个父类(直接父类),运用extends关键字
  • 子父类是相对的概念
  • 子类直接承继的父类,称为直接父类;直接承继的父类称为直接父类。
  • 子类承继父类今后,就获取了直接父类以及一切直接父类中声明的特点和办法

代码实例

class Biology{ //生物类
    String name;
    int age;
}
class Animal extends Biology{//动物类承继了生物类,生物类是动物类的直接父类
}
class Plant extends Biology{//植物类承继了生物类,生物类是植物类的直接父类
}
class Tiger extends Animal{//山君类承继了动物类,动物类是山君类的直接父类,生物类是山君类的直接父类
}
class Tree extends Plant{//树类承继了植物类,植物类是树类的直接父类,生物类是植物类的直接父类
}

运用承继还会联系到办法重写和super关键字的运用,下面来介绍

办法重写

在子类中,能够根据需要对从父类中承继来的办法进行办法重写。重写今后,当子类目标调用与父类的同名同参数的办法时,优先调用子类重写的办法。

当子类调用特点和办法的时分,假如自己类里边有该特点和办法,必定先调用自己的,假如自己类里边没有,就去父类(先直接父类/再直接父类)找,一向找到Object类为止。

办法重写有如下要求:

  • 子类重写的办法有必要和父类被重写的办法具有相同的办法称号、参数列表;
  • 子类重写的办法的返回值类型不能大于父类被重写办法的返回值类型

1.父类被重写的办法的返回值类型是void,则子类重写的办法的返回值类型只能是void。

2.父类被重写的办法的返回值类型是A类型,则子类重写的办法的返回值类型能够使A类或A类的子类。

3.父类被重写的办法的返回值类型是基本数据类型(比方double),则子类重写的办法的返回值类型有必要是相同的基本数据类型。

  • 子类重写的办法运用的拜访权限不能小于父类被重写的办法的拜访权限 (能够参考这篇博客:四种权限拜访修饰符)
  • 子类办法抛出的反常不能大于父类被重写办法的反常
  • 子类能重写的都对错static的办法

思考:假如父类有个办法是private拜访权限,在子类中将此办法声明为default拜访权限,这个叫办法重写吗?达咩,当然不是。

super关键字

在Java类中,运用super调用父类中的指定操作。能够拜访父类中的结构器、特点和成员办法。

咱们需要把握的内容

  • super的三种语法格式:拜访父类结构器(有必要放结构函数中的第一行):super()或super(参数);拜访父类特点:super.特点;拜访父类办法:super.办法名()。
  • 咱们能够在子类的办法或结构器中,经过运用super.或super(),显式地调用父类中声明的特点/办法或结构器。通常情况下,咱们习惯省略‘super.’。
  • 特殊情况,若想在子类中调用父类的同名特点或被重写办法时,有必要显式地运用’super.’。
  • 子类中一切的结构器默许都会拜访父类中空参数的结构器。
  • 当父类中没有空参数的结构器时,子类的结构器有必要经过super(参数列表)句子指定父类中相应的结构器,有必要放在结构器的首行。意图在于在创立子类目标的时分,先初始化父类。
  • 假如类里边有n个结构器,那么能够调用n-1次,至少1次是调父类的。
  • this()与super()不能一起出现,在结构器中,有必要二选一,且只能出现在第一行。

定论:在java言语中,不管new什么目标,最终Object类中的无参结构办法是一定会履行的。

代码举例:

public class JavaTest {
    public static void main(String[] args) {
        Chinese cn=new Chinese();
        cn=new Chinese("I 'm Chinese!");
        cn=new Chinese("I 'm Chinese!",18);
        cn.sout();
    }
}
class Person{
   int id=431234566;
   String name;
    public Person(){}
    Person (String name){
        this.name=name;
    }
    public void sout(){
        System.out.println("这是父类中的输出办法1");
    }
}
class Chinese extends Person{
    public Chinese(){
        super(); //调用父类无参结构办法,这个子类每个结构器都会默许调用的,可不写
    }
    public Chinese(String name){
     super(name);//调用父类有参结构办法
    }
    public Chinese(String name,int age){
        this(name);//经过this去调用结构器中的super办法
        System.out.println("父类中的id"+super.id);//调用父类的特点
    }
    @Override
    public void sout() {
        System.out.println("这是子类中的输出办法!");
        super.sout();//调用父类的sout办法
    }
}

输出结果

Java之封装、继承和多态(超详细)

super与this的区别

  • super()函数在子类结构函数中调用父类的结构函数时运用,而且有必要要在结构函数的第一行。
  • this()函数调用本类中另一种构成的结构函数。this()只能用在结构函数中,而且也只能在第一行。
  • super()和this()都指的是目标,不能一起出现在结构函数里,只能二选一,均不可在static环境中运用。
  • super:引证当时目标的父类中的成员。语法格式:super.特点名/办法名()
  • this:代表当时目标名。this是目标的躲藏特点 (实质便是一个普通的成员变量),和其他non-static 特点一样,在创立目标的时分会为每个新目标分配该目标的专属成员变量(this便是其间一个),this这个成员变量存储在堆内存中,该变量的值是所属目标在堆内存的地址。
  • this代表本类目标的引证,super代表父类的内存空间的标识。

从实质上来讲,this是一个面向目标的指针,然后super是一个Java关键字。

承继的优点:

  • 进步代码复用性,削减代码冗余
  • 便于功能扩展
  • 为多态性的运用,供给了条件

承继也存在一些缺点,承继的类与类之间的耦合度十分高,不利于代码的扩展。

三、多态

多态是办法或目标具有多种形态。多态不适用于特点。

简略解释一下:

即同一办法能够根据发送目标的不同而选用多种不同的行为办法。一个目标的实践类型是确认的,但能够指向目标的引证的类型有许多(父类,有联系的类)。

所谓多态便是指一个引证变量到底会指向哪个类的实例目标,该引证变量发出的办法调用到底是哪个类中完成的办法,在编译时并不确认,有必要在程序运转期才确认。

多态的条件:

  • 需要存在承继或完成联系
  • 有办法的重写
  • 父类引证指向子类引证(也叫向上转型)

注:能够直接应用在抽象类和接口上。

多态的总结

  • 一个目标的编译类型和运转类型能够不一致。编译类型是在界说目标时,就确认了,不能改动;运转类型是能够改变的。
  • 编译类型看界说时=左面,运转类型看=右边。
  • 多态特点:能够调用父类中一切成员(需恪守拜访权限),不能调用子类中特有成员;最终运转作用要看子类的具体完成。
  • 当运用多态办法调用办法时,首先检查父类中是否有所调用的办法,假如没有,则编译错误;假如有,再去调用子类(运转类型)中的重写办法。
  • 想调用子类中一切的成员,能够进行向下转型,语法:子类类型 引证名=(子类类型) 父类引证。一般引荐运用instanceof 去判断一下。
  • 目标 instanceof 类名,用于判断目标的运转类型是否为类型或类型的子类型。
  • java动态绑定机制:当调用目标办法时,该办法会和目标的内存地址/运转内存绑定;调用特点时,没有绑定机制,哪里声明哪里运用。
  • 目标类型转换:向上转型:父类引证指向子类目标,目标多态性;向下转型:子类引证指向父类目标,有必要强转。

代码举例:

public class JavaTest {
    public static void main(String[] args) {
      A a=new B();
        System.out.println(a.sum());
        System.out.println(a.sum1());
    }
}
class A{//父类
     int  i=10;
     public int sum(){
         return getI()+10;
     }
     public int sum1(){
         return i+10;
     }
     public int getI(){
         return i;
     }
}
class B extends A{//子类
    int i=20;
    public int getI(){
        return i;
    }
}

猜猜答案是多少,猜对了就阐明你真正意义上知道动态绑定机制了。答案是30 20

多态作用

进步了代码的通用性,常称作接口重用。

最终再烦琐一句:面向目标编程的实质是:以类的办法安排代码,以目标的安排(封装)数据。