JavaSE篇学习之路:(六)【面向对象------中】

简介: 继承是指一个对象直接使用另一对象的属性和方法;多种形态是指多种状态,编译和运行有两个不同的状态:编译期叫做静态绑定,运行期叫做动态绑定。

第一章:继承(Extexnds)



1.1什么是继承?作用?


继承:指一个对象直接使用另一对象的属性和方法


继承的作用:

基本作用:子类继承父类,代码可以得到复用。

主要(重要)作用:因为有了继承关系,才有了后期的方法覆盖和多态机制。


2.1继承相关特性


    ① B类继承A类,则称A类为超类(superclass)、父类、基类,
  B类则称为子类(subclass)、派生类、扩展类。
    class A{}
    class B extends A{}
    我们平时聊天说的比较多的是:父类和子类。
    superclass 父类
    subclass 子类
  ② java 中的继承只支持单继承,不支持多继承,C++中支持多继承,
  这也是 java 体现简单性的一点,换句话说,java 中不允许这样写代码:
    class B extends A,C{ } 这是错误的。
  ③ 虽然 java 中不支持多继承,但有的时候会产生间接继承的效果,
  例如:class C extends B,class B extends A,也就是说,C 直接继承 B,
  其实 C 还间接继承 A。
  ④ java 中规定,子类继承父类,除构造方法不能继承之外,剩下都可以继承。
  但是私有的属性无法在子类中直接访问。(父类中private修饰的不能在子类中
  直接访问。可以通过间接的手段来访问。)
  ⑤ java 中的类没有显示的继承任何类,则默认继承 Object类,Object类是 
  java 语言提供的根类(老祖宗类),也就是说,一个对象与生俱来就有 
  Object类型中所有的特征。
  ⑥ 继承也存在一些缺点,例如:CreditAccount 类继承 Account 类会导致它
  们之间的耦合度非常高,Account 类发生改变之后会马上影响到 CreditAccount 类


什么时候可以使用继承?

能使用“is a”关系可描述清楚。


3.1方法覆盖(OverRide)


什么是方法覆盖?

当子类继承父类后,继承过来的方法无法满足子类的需求,子类将这个方法进行重写。

将继承过来的方法进行覆盖,执行覆盖后的方法。


方法覆盖满足的条件:


1.两个类为继承关系。

2.重写之后的方法和之前方法具有:相同返回值类型,相同方法名,相同形参列表

3.访问权限不能更低,只能更高。

4.重写之后的方法不能比之前的方法抛出个更多异常。


注意事项:


1.方法覆盖只针对于方法,与属性无关。

2.私有方法无法覆盖

3.构造方法无法覆盖

4.方法覆盖只针对实例方法,静态方法无意义。


代码演示:


/**
 * 父类:动物类
 */
class Animal{
    private String name;
    //无参构造方法
    public Animal() {
    }
  //有参构造方法
    public Animal(String name) {
        this.name = name;
    }
    //动物具有吃东西的方法
    public void eat(){
    }
}


/**
 * 猫继承动物类  猫是动物
 */
class Cat extends Animal{
  //无参构造方法
    public Cat(){
    }
    //猫类重写父类eat()方法!
    public void eat(){
        System.out.println("猫吃猫粮!");
    }
}


/**
 * 狗继承动物类 狗是动物
 */
class Dog extends Animal{
  //无参构造方法
    public Dog(){
    }
    //狗类重写父类的eat()方法!
    public void eat(){
        System.out.println("狗吃狗粮!!");
    }
}


/**
 1. 测试类
 */
public class Demo {
    public static void main(String[] args) {
       //创建猫对象
        Cat cat=new Cat();
        //猫吃东西
        cat.eat();
       //创建狗对象
        Dog dog=new Dog();
        //狗吃东西
        dog.eat();
    }
}


第二章:多态



1.1什么是多态?


多种形态,多种状态,编译和运行有两个不同的状态。
  编译期叫做静态绑定。
  运行期叫做动态绑定。
  Animal a = new Cat();
  // 编译的时候编译器发现a的类型是Animal,所以编译器会去Animal类中找move()方法
  // 找到了,绑定,编译通过。但是运行的时候和底层堆内存当中的实际对象有关
  // 真正执行的时候会自动调用“堆内存中真实对象”的相关方法。
  a.move();
  多态的典型代码:父类型的引用指向子类型的对象。


2.1基础语法


向上转型和向下转型的概念:


  向上转型:子--->父 (upcasting)
    又被称为自动类型转换:Animal a = new Cat();
  向下转型:父--->子 (downcasting)
    又被称为强制类型转换:Cat c = (Cat)a; 需要添加强制类型转换符。
  什么时候需要向下转型?
      需要调用或者执行子类对象中特有的方法。
      必须进行向下转型,才可以调用。
  向下转型有风险吗?
      容易出现ClassCastException(类型转换异常)
  怎么避免这个风险?
        instanceof运算符,可以在程序运行阶段动态的判断某个引用指向的对象
      是否为某一种类型。
      养成好习惯,向下转型之前一定要使用instanceof运算符进行判断。
  不管是向上转型还是向下转型,首先他们之间必须有继承关系,这样编译器就不会报错。


代码演示:


public class OverrideTest05{
  public static void main(String[] args){
    // 静态方法可以使用“引用.”来调用吗?可以
    // 虽然使用“引用.”来调用,但是和对象无关。
    Animal a = new Cat(); //多态
    // 静态方法和对象无关。
    // 虽然使用“引用.”来调用。但是实际运行的时候还是:Animal.doSome()
    a.doSome();
  }
}
class Animal{
  // 父类的静态方法
  public static void doSome(){
    System.out.println("Animal的doSome方法执行!");
  }
}
class Cat extends Animal{
  // 尝试在子类当中对父类的静态方法进行重写
  public static void doSome(){
    System.out.println("Cat的doSome方法执行!");
  }
}


3.1 instanceof运算符


类型向下转型时,必须使用instanceof进行判断。

强调:


1.在运行阶段动态判断引用指向对象类型

2.语法: 引用 instanceof 类型

3.运算结果为:true 或者false

4.假设C instanceof Cat为true,则C引用指向堆内存Java对象为一个Cat,如果为False 说明不是一个Cat


代码演示:


/**
 * 父类:动物类
 */
class Animal{
    public Animal() {
    }
    //动物具有吃东西的方法
    public void eat(){
    }
}


/**
 * 猫继承动物类  猫是动物
 */
class Cat extends Animal {
    public Cat() {
    }
    //猫类重写父类eat()方法!
    public void eat() {
        System.out.println("猫吃猫粮!");
    }
    public void run(){
        System.out.println("猫在走猫步");
    }
}


/**
 * 狗继承动物类 狗是动物
 */
class Dog extends Animal{
    public Dog(){
    }
    //狗类重写父类的eat()方法!
    public void eat(){
        System.out.println("狗吃狗粮!!");
    }
    public void run(){
        System.out.println("狗仔跳墙!1");
    }
}


/**
 * 测试类
 */
public class Demo {
    public static void main(String[] args) {
        //向下转型:父类调用子类特有的方法。
        Animal animal=new Cat();
        Animal animal1=new Dog();
        //必须使用instanceof进行判断
        if(animal instanceof Cat) {
            Cat c=(Cat) animal;
            c.run();//子类特有
        }else if (animal1 instanceof Dog){
            Dog d=(Dog) animal1;
            d.run();//子类特有
        }
    }
}


4.1 super关键字


1.super能出现在实例方法和构造方法中。

2.super的语法是:“super.”、“super()”

3.super不能使用在静态方法中。、

4.super. 大部分情况下是可以省略的。

5.super() 只能出现在构造方法第一行,通过当前的构造方法去调用“父类”中的构造方法,目的是:创建子类对象的时候,先初始化父类型特征。

6.super()表示通过子类对象调用父类的构造方法

7.当一个无参构造方法第一行既没有this()也没有super()默认有一个super().

8.this()与super()不饿共存,且只在第一行.父类构造方法一定执行


什么时候super不能省略?

如果父与子类有相同的属性,想在子类中访问父类的特征。


代码演示:


//书
public class Book {
//书名
    String name;
//构造方法
    public Book(){
    super();
    }
  public Book(String name){
    super();
    this.name = name;
  }
 }


//纸质书
public class PaperBook extends Book {
//构造方法
    public PaperBook(){
      super();
    }
    public PaperBook(String name){
      super();
      this.name = name;
    }
//打印书名
    public void printName(){
      System.out.println("this.name->书名 : " + this.name);
      System.out.println("super.name->书名 : " + super.name);
    }
 }


public class BookTest {
  public static void main(String[] args) {
    PaperBook book1 = new PaperBook("零基础学 Java 卷 I");
    book1.printName();
  }
 }

2.png

2.png


通过以上内存结构图发现 this.name 和 super.name 实际上是同一块内存空间,所以它们输出结果是完全一样的。

如果在子类中加一个name属性呢?


//纸质书
public class PaperBook extends Book {
    String name; //在子类中也定义了一个 name 属性
//构造方法
    public PaperBook(){
      super();
    }
    public PaperBook(String name){
      super();
      this.name = name;//这里的 this.name 代表子类的 name
    }
//打印书名
    public void printName(){
    System.out.println("this.name->书名 : " + this.name);
    System.out.println("super.name->书名 : " + super.name);
    }
}

2.png


父类 Book 的构造方法在执行的时候给 super.name 赋值null,子类 PaperBook 的构造方法在执行的时候给 this.name 赋值“零基础学 Java 卷 I”,由于在子类 PaperBook 中定义了重名的变量 name 导致在当前对象中有两个 name,一个是从父类中继承过来的,一个是自己的,如果此时想访问父类中继承过来的 name 则必须使用 super.name,当直接访问 name 或者 this.name 都表示访问当前对象自己的 name。


相关文章
|
5月前
|
编译器 C语言 C++
C++入门第四篇----详解C++类和对象知识点(上)
C++入门第四篇----详解C++类和对象知识点(上)
39 0
|
5月前
|
编译器 C语言 C++
C++入门第四篇----详解C++类和对象知识点(下)
C++入门第四篇----详解C++类和对象知识点(下)
34 0
|
4天前
|
机器学习/深度学习 Java Python
Java面向对象知识体系---基础版
Java面向对象知识体系---基础版
|
IDE Java 编译器
【JavaSE成神之路】Java面向对象(下)
哈喽,我是兔哥呀,今天就让我们继续这个JavaSE成神之路! 这一节啊,咱们要学习的内容还是Java的面向对象。
|
存储 IDE Java
【JavaSE成神之路】Java面向对象(上)
哈喽,我是兔哥呀,今天就让我们继续这个JavaSE成神之路! 这一节啊,咱们要学习的内容是Java的面向对象。
138 1
JavaSE:第四章:面向对象上
JavaSE:第四章:面向对象上
JavaSE:第四章:面向对象上
|
存储 Java 大数据
大数据学习记录---JAVA篇---面向对象基础部分
第二部分学习面向对象相关知识,这一部分其实不太熟悉,因为也不常写,记录一些知识点,以便后续回忆。
74 1
大数据学习记录---JAVA篇---面向对象基础部分
|
存储 安全 Java
JavaSE篇学习之路:(五)【面向对象------上】
面向对象是指更符合人的思维方式,面向对象更容易接受。
JavaSE篇学习之路:(五)【面向对象------上】
|
Java C++
JavaSE篇学习之路:(七)【面向对象------下】
抽象类是指半抽象,有构造方法,单继承;接口是指完全抽象,无构造方法,多继承,一个类多个接口,只允许常量和抽象方法。
JavaSE篇学习之路:(七)【面向对象------下】
|
小程序 Java
JavaSE篇学习之路:(四)【函数or方法】
方法定义就是具有特定功能的一段 独立小程序,可以被多次使用,实现代码复用,提高复用性。