Java面向对象

1. 面向对象简介

学习面向对象会涉及到很多专有的名词,比如类与对象、继承、抽象、接口、多态、封装等等,很多人在学习时过于关注这些名词的概念,会觉得概念很多很绕,就说面向对象很难,其实不是这样的,要与现实场景相结合来学习Java面向对象.
在这里插入图片描述

面向对象思想
首先我们来了解一下什么是面向对象思想?这里说的思想,你可以理解为解决问题的方式。比如说我想吃蛋炒饭,这是我的目的,为了实现这个目的,我们有不同的解决问题的方式。

如果我是一个勤快的人,自己动手做蛋炒饭,你需要先打鸡蛋——准备葱花——放油——在锅里翻炒——最后出锅,一碗香喷喷的蛋炒饭就做好了。以上做蛋炒饭的过程就是一种面向过程的思想,关注点在做事情的过程,中间的每一个环节都必须清清楚楚才能把事情做好。

如果你根本不会做饭,也想吃蛋炒饭怎么办呢?看下面这张图,很熟悉吧!我们可以找一个小摊,跟师傅说来一碗蛋炒饭,等一小会蛋炒饭就做好了。像这种让别人帮你做事情的思想就是一种面向对象的思想,这里的厨师就是对象,它具备帮你炒饭的能力,当你想吃饭的时候找这个厨师对象就可以了。
在这里插入图片描述

假设用以上两种方式做的蛋炒饭味道都是一样的,那么那种方式更简单一些呢?答案肯定是第二种。我们会发现面向对象的思想有下面几个特点

  • 1.面向对象让复杂的问题简单化了
  • 2.面向对象把我们从执行者变为指挥者
  • 3.面向对象可以把细节的过程隐藏
    其实生活中符合面向对象思想的例子无处不在,同学们可以放开你的脑洞想一想,你可以说:”xxx是一个对象,它具备xxx功能,当我们想做什么事情的的时候,就这个对象帮我们做事情”。

2. 类与对象

我们知道面向对象思想之后,接下来就要把这种面向对象的思想用Java语言的表达出来,怎么表达呢?

比如说我想吃饭,可以找厨师做饭,那“厨师”这个现实生活中的事物如何用Java代码来表达出来呢?要实现这个目的,咱们要引入一个重要的概念 —— 类与对象

咱们先不去想类和对象到底是什么意思?我先卖一个关子,给大家提一个问题,谁来描述一下你心目中的厨师长什么样?具备什么技能? 没猜错的话大家脑海中厨师的画面大概就是下面的样子。从图片我们发现,不管是卡通形象的厨师,还是真实形象的厨师,他们都有一些共同的属性和行为,如都穿白大褂、戴高帽子、都会做饭。我们就把符合这些相同属性和行为的事物归为一类——厨师类;而每一个符合这些属性和行为的个体称为厨师对象
在这里插入图片描述
在这里插入图片描述

再比如,下图中有一个苹果电脑、5768元,有一个华为电脑、5288元。不管是苹果电脑还是华为电脑,都有品牌和价格2个属性,那么它们也可以归为一个类——电脑类;而每一个具体的电脑个体就是电脑对象
在这里插入图片描述

综上所述

类是对具有相同属性和行为的事物的统称
对象是某一类事物的具体实例

2.1.定义类

虽然我们知道类和对象的关系了,那么类用Java代码怎么来写一个类呢?先给大家写一个格式

//类名:表示你要描述的事物(如电脑)
public class 类名{
    成员变量 //表示该事物具备的属性(如电脑有品牌、价格、颜色等)
    成员方法 //表示事物具备的行为(如电脑能打游戏、看电影等)
}
注意:类名、变量名、方法名都需要见名知意,比如我想定义一个【电脑类】我可以取类名为
【Computer/*
电脑类的属性和行为
    属性:品牌(brand)、价格(price)、颜色(color)
    行为:玩游戏(playGame)
*/
public class Computer{
    String brand; //品牌
    int price; //价格
    String color; //颜色

    //玩游戏
    public void playGame(){
        System.out.println("玩游戏");
    }

    //看电影
    public void watchMovie(){
        System.out.println("看电影");
    }
}

2.2.创建对象

Computer类定义好了之后,我们还不能够直接运行,因为还没有创建Computer对象(相当于我们设计好了图纸,还没有生产出商品来)。于是我们需要再写一个测试类,创建电脑对象,才能使用它。

怎么创建电脑对象呢?也有固定的格式。

/创建对象的格式:
类名 对象名=new 类名();
Computer com=new Computer();
//使用对象的属性:对象名.属性名
com.brand; //对象的品牌
//调用对象的行为:对象名.方法名();
com.watchMovie(); //对象的看电影功能

小技巧:这里的"."你可以理解为汉语中的“的”。
public class Demo1{
    public static void main(String[] args){
        //创建一个电脑对象
        Computer com1=new Computer();
        //给电脑贴上logo,标上价格
        com1.brand="苹果";
        com1.price=5768;
        System.out.println("品牌:"+com1.brand);
        System.out.println("价格:"+com1.price);
        //使用苹果电脑玩游戏的功能
        com1.playGame();

        System.out.println("-------------");

        //创建另一个电脑对象
        Computer com2=new Computer();
        //给另一台电脑贴上logo,标上价格
        com2.brand="华为";
        com2.price=5288;
        System.out.println("品牌:"+com2.brand);
        System.out.println("价格:"+com2.price);
        //用华为电脑玩游戏的功能
        com2.playGame();
    }
}

2.3.Java封装性概述

我们现在会定义一个类了,也会创建对象了,但是这个代码并不是很完美,我给大家演示一个在生活中不可思议的效果。改动一下代码

com1.price=-5768;

一运行,我们发现神奇的效果出来了,苹果电脑的价格是负数,也就是说到倒贴钱把电脑送给你了,这怎么得了!如果我是电脑经销商绝对不允许这样的事情出现,砸了也不卖,我必须阻止别人随意的去更改电脑的价格,即使要修改也得经过我的授权。这里提到授权这个词,让我想到“把权利装进制度的笼子里”这句话,也就是制度授予你什么权利,你才能干什么事情。
在这里插入图片描述

Java的封装性就是通过这种授权的方式来实现的。所谓封装就是把不需要让别人知道的细节隐藏,只公开一些固定的访问方式即可。

给大家举一个生活中的例子,帮助大家理解
在这里插入图片描述

你用的笔记本电脑,厂家在生产电脑时,把内部的细节用一个壳子包裹起来,你是不能够直接看到里面的东西的,但是这个壳子并没有封死,它还给我们提供了键盘、鼠标、USB接口等通用的方式与电脑进行交互。

厂家为了电脑的安全,把不需要让你知道的内部细节隐藏起来,就是一种封装。完全封死了也不行,那就是一个铁疙瘩,还需要提供公共的访问方式,键盘、鼠标、USB接口等就是给使用者提供的操作电脑的方式

类似这样封装的例子还有很多,大家可以放开脑洞想想,只要把握住两点就可以了。

1. 把不需要让别人知道的内部细节隐藏
2. 对外提供公共的访问方式

待会我们去写代码完成Java代码的封装,也就是这两步。

2.4.Java封装性实现

前面我们讲到,实现Java的封装就两个步骤
怎样隐藏内部细节呢?

使用private关键字私(私有的意思),我们可以把成员变量都用private修饰,private修饰的成员变量或者成员方法,只能在本类中被调用,我们试一下。

public class Computer{
    private String brand;
    private String color;
    private int price;
}
public class Demo1{
    public static void main(String[] args){
        Computer com=new Computer();
        //下面代码报错:Computer的成员变量被private修饰,只能在本类中被调用。
        com.name="苹果";
        com.color="白色";
        com.price=5768;
    }
}

私有的变量不能直接被外界调用,相当于被封装起来了;还需要给外界提供公共的访问方式,其他类才能够使用。

怎样提供公共的访问方式呢?很简单,照做就可以了

快捷键:alt+insert或者fn+alt+insert 自动生成getXxx和setXxx方法
public class Computer{
    private String brand;
    private String color;
    private int price;

    //给成员变量brand设置值
    public void setBrand(String brand){
        this.brand=brand;
    }
    //获取成员变量brand的值
    public String getBrand(){
        return brand;
    }
    ...其他的两个属性,也需要有对应的setXxx和getXxx方法,此处省略...
}

setXxx()和getXxx()是一种固定的写法,setXxx()是用于给成员变量设置值的方法,getXxx()是用于获取成员变量的值的方法;调用者使用公开的getXxx和setXxx方法,去访问封装好的数据即可。

public class Demo2{
    public static void main(String[] args){
        Computer com=new Computer();
        //给电脑设置品牌
        com.setBrand("苹果");
        //给电脑设置颜色
        com.setColor("白色");
        //给电脑设置价格
        com.setPrice(5788);

        //获取电脑的品牌,用brand变量保存(变量名可以改)
        String brand=com.getBrand();
        //获取电脑的颜色,用color变量保存(变量名可以改)
        String color=com.getColor();
        //获取电脑的价格,用price变量保存(变量名可以改)
        String price=com.getPrice();
    }
}

2.5.this关键字

我们发现在getXxx和setXxx方法中,有一个this关键字,这是什么意思呢?

this: 本类对象的引用
    thisComputer类中,就表示Computer对象
this.成员变量: 本类对象的成员变量
this.成员方法: 本类对象调用成员方法

一般用于在同一个类中,区分成员变量和局部变量重名的情况
我们以setBrand(String brand)为例进行讲解,其他都是一样的,看下图

在这里插入图片描述

2.6.构造方法

现在学习了在一个类中可以定义成员变量、成员方法。其实一个标准类的组成除了成员变量、成员方法还有构造方法,接下来咱们学习一下构造方法。

学习构造方法掌握下面几个要点即可

  1. 构造方法的格式
public 类名(){

}
  1. 构造方法是干什么用的?
构造方法是用来创建对象的,每次创建对象构造方法就会执行。
  1. 可以有多个构造方法
一个类可以定义多个参数不一样的构造方法,也就是说有多种创建对象的方式

接下来咱么来做一个试验,代码执行流程如下
在这里插入图片描述
我们发现,每次new对象,会根据参数的不同,来执行对应的构造方法。

2.7.类的组成

一个标准的类由 成员变量、成员方法、构造方法 组成。我们按照一个标准类的写法来编写一个学生类

写一个标准的学生类(Student)
按照前前面一个类的组成,我们在写一个标准的学生类(Student)作为练习

1.明确需求:写一个学生类
2.分析学生具备那些属性:姓名(name)、年龄(age)
    单词不会:建议备一个字典软件(金山词霸、有道词典)
3.私有化成员变量 、对外提供getXxx和setXxx方法
    Java封装的体现
4.构造方法
    用于创建对象的方式,并做一些初始化的操作。

public class Student{
    private String name;
    private int age;

    //有参数构造方法
    public Student(String name,int age){
        this.name=name;
        this.age=age;
    }

    //给成员变量name设置值
    public void setName(String name){
        this.brand=brand;
    }
    //获取成员变量brand的值
    public String getName(){
        return name;
    }
    ...其他的两个属性,也需要有对应的setXxx和getXxx方法,此处省略...
}

再写一个测试类,创建Student对象并使用

public class Demo5{
    public static void main(String[] args){
        //空参数构造方法,创建对象
        Student stu1=new Student();
        //给电脑设置品牌
        stu1.setName("小明");
        //给电脑设置颜色
        stu1.setAge(18);

        //获取学生的姓名,用name变量保存(变量名可以改)
        String name1=stu1.getName();
        //获取学生的年龄,用age变量保存(变量名可以改)
        String age1=stu1.getAge();

        System.out.println("姓名:"+name1);
        System.out.println("年龄:"+age1);

        System.out.println("----------------");

        //利用有参数构造方法创建对象,并且给成员变量赋值
        Student stu2=new Student("小强",20);
        //获取学生的姓名,用name变量保存(变量名可以改)
        String name2=stu2.getName();
        //获取学生的年龄,用age变量保存(变量名可以改)
        String age2=stu2.getAge();

        System.out.println("姓名:"+name2);
        System.out.println("年龄:"+age2);
    }
}

注意事项

如果在一个类中,一个构造方法都不写,系统将会默认送你一个空参数的构造方法(方便你创建对象)

3. 继承

接下来我们学习继承,我们从下面的这张图来入手继承.

在这里插入图片描述

从上图中我们会发现,动物和兔子都是食草动物,我们就可以把吃草的动物归为一类叫做;狮子和豹子都是食肉动物,也可以把吃肉的动物归为一类;而不管食草动物还是吃肉动物,都可以归为动物类。动物学家通过对动物进行分类,方便人类学习和研究动物的习性和特征。

Java中的继承能够让类与类之间产生关系,提高代码的复用性。如果A类和B类有一些共性的属性和行为,就可以把这些共性的属性和行为抽取到一个C类中,让A继承C,B也继承C,这样A类和B类就具备了C类的属性和行为,同时A类和B类还可以有自己特有的属性和行为。

image-20191215204505874

Animal类
描述动物类共性的行为和属性

//抽象类Animal
public abstract class Animal{
    //成员变量表示属性
    private String variety;//品种
    private String color;//颜色
    private int age;//年龄
    //空参数构造方法
    public Animal(){}
    //有参数构造方法
    public Animal(String variety,String color,int age){
        this.variety=variety;
        this.color=color;
        this.age=age;
    }
    //呼吸:我把呼吸定义成一个具体方法(ps:为了告诉你抽象类中可以有具体方法)
    public void breath(){
        System.out.println("所有动物都会呼吸");
    }
}

定义Dog类
Dog类 extends Animal类,共性的属性和行为Dog类中就不用写了。

//Dog 继承 Animal,必须复写Animal的抽象方法
public class Dog extends Animal{
    //Dog虽然继承Animal,但是创建Dog对象还是得看Dog的构造方法
    public Dog(){}
    //有参数构造方法
    public Dog(String variety,String color,int age){
        super(variety,color,age); //访问父类构造,给成员变量赋值
    }

    @Override
    public void eat(){
        System.out.println("狗吃骨头");
    }
}

定义Cat类
Cat类 extends Animal类,共性的属性和行为Dog类中就不用写了。

//Cat 继承 Animal,必须复写Animal的抽象方法
public class Cat extends Animal{
    //Cat 虽然继承Animal,但是创建Cat 对象还是得看Cat 的构造方法
    public Cat (){}
    //有参数构造方法
    public Cat (String variety,String color,int age){
        super(variety,color,age); //访问父类构造,给成员变量赋值
    }

    @Override
    public void eat(){
        System.out.println("猫吃小鱼");
    }
}

测试类
程序的入口仅用于创建对象调用方法

public class Demo2{
    public static void main(String[] args){
        //利用空参数构造创建Dog对象
        Dog dog=new Dog();
        dog.setVariety("哈士奇");//给dog对象设置品种为"哈士奇"
        dog.setColor("黑白");//给dog对象设置颜色为"黑白"
        dog.setAge(2);//给dog对象设置年龄为2岁
        //调用get方法获取dog对象的属性值
        System.out.println(dog.getVaritey()+"..."+dog.getColor()+"..."+dog.getAge());
        System.out.println("----------------------");
        //利用有参数构造创建对象,并赋值
        Cat cat=new Cat("布偶猫","白色",3);
        //如果想显示dog对象的的属性值,就调用get方法并输出
        //调用get方法获取cat对象的属性值
        System.out.println(cat.getVaritey()+"..."+cat.getColor()+"..."+cat.getAge());
    }
}

4. 抽象

接下来我们学习一下抽象,抽象这个词不太好解释,用一个例子给大家解释,还是看图吧。
在这里插入图片描述

在这张图中圆形、矩形、和三角形就是一个具体的概念,而形状就是一个抽象的概念。我们可以把形状看做是一个抽象类,形状一定能求面积,但是由于不具体所有求面积的方法也无法具体化,那么这个方法就 叫做抽象方法。

而下面的圆形、矩形、和三角形可以看做是形状的子类,这些子类也都有求面积的方法,但是它们就可以具体化了,这就是子类重写父类方法。接下来用代码来演示一下

//抽象类和抽象方法都需要被abstract修身
public abstract class Shap{
    //求形状的面积
    public abstract double getArea();
}

//圆形
public class Circle extends Shap{
    //半径
    private int r;
    //构造方法给成员变量赋值
    public Circle(int r){
        this.r=r;
    }

    @Override
    public double getArea(){
        return 3.14*r*r;
    }
}

//矩形
public class Rect extends Shap{
    //宽
    private int width;
    //高
    private int height;

    //构造方法给成员变量赋值
    public Rect(int width,height){
        this.width=width;
        this.height=height;
    }

    @Override
    public double getArea(){
        return width*height;
    }
}

//测试类

public class Demo1{
    public static void main(String[] args){
        //创建半径为5的圆形
        Circle c=new Circle(5);
        double s1=c.getArea();
        System.out.println("圆形的面积为:"+s1);

        //创建宽为5,高为10的矩形
        Rect r=new Rect(5,10);
        double s2=r.getArea();
        System.out.println("矩形的面积为:"+s2);
    }
}

抽象类有下面的几个特点

1.抽象类不能创建对象(也叫实例化)
2.抽象类中可以有抽象方法也可以有非抽象方法
3.一个具体类继承抽象类必须重写所有的抽象方法
4.一个抽象类继承抽象类可以不用重写抽象方法

5. 接口

生活中的接口

为了方便大家理解我们先从生活中的接口开始说起,再慢慢引出Java接口的相关用法。

生活中最常见的一种接口就是电脑的USB接口,在淘宝上可以买到各种USB接口的扩展设备(鼠标、键盘、U盘等),只要插到电脑上就可以直接使用。大家想一想每一种扩展设备都是不同的厂家生产的,功能以及实现原理都不一样,是怎么做到插到电脑上就能通用的呢?

1583738473025

那是因为USB是由Intel、IBM、Microsoft等计算机公司和通信公司联合制定的一种输入输出的接口规范,该规范中统一了电脑和外部设备连接和通讯的规则。 只有符合这种规范的设备才能被电脑识别。

从上面USB接口的例子不难发现,生活中的接口其实就是一种规范。像这种的例子还有很多,比如插座,耳机孔,甚至3G\4G的网络都有相关的行业规范,而设备厂家生产设备时就会严格遵守这些行业规范,否则造出来的东西就不能通用。

Java的接口

Java的接口是一些抽象方法的集合,由具体的类来实现接口中的抽象方法。

为了方便大家理解我们结合生活实例做一个比喻,Java接口中的抽象方法就相当于行业标准中的各种条款,而实现类就是按照行业标准来设计自己的产品。

1583985517126

5.1.接口的定义

Java接口使用interface关键字定义,接口名和类名的命名规则一样,采用大驼峰命名规则

/*
下面定义一个Usb接口,接口中有加载驱动和运行的功能,而且这些方法都是抽象的
*/
public interface Usb{
   public void loadDriver();
   public void run();
}

5.2.接口的实现

上写好了接口仅仅表示Usb规范必须有哪些功能,但没有具体实现。

接下来写一个U盘类就是一个具体的需要实现Usb规范的设备,必须复写Usb接口中的所有方法。

public class Uimplements Usb{
    @Override
    public void loadDriver(){
        System.out.println("加载U盘驱动程序");
    }

    @Override
    public void run(){
        System.out.println("U盘正常工作");
    }
}

同理再定义一个键盘类,让它实现Usb接口

public class UsbKeyBoard implements Usb{
    @Override
    public void loadDriver(){
        System.out.println("加载键盘驱动");
    }

    @Override
    public void run(){
        System.out.println("键盘正常工作");
    }
}

编写测试类运行

public class Demo{
    public static void main(String[] args){
        //创建U盘对象,并调用其方法
        U盘 u=new U();
        u.loadDriver();
        u.run();

        //创建键盘对象,并调用其方法
        UsbKeyBoard kb=new UsbKeyBoard();
        kb.loadDriver();
        kb.run();
    }
}

1584071263155

5.3.接口与类的关系

5.3.1.类与类
单继承关系:一个类只能继承一个父类
public class 类名 extends 父类{
    ...
}
5.3.2.类与接口
多实现关系:一个类可以实现多个接口,必须重写每一个接口中的抽象方法
public class 类名 implements 接口1,接口2{
    ...
}
5.3.3.接口与接口
多继承关系:一个接口可以继承多个接口,相当于把多个接口的抽象方法集于一身。
public interface 接口 extends 接口1,接口2{
    ...
}
5.3.4.继承和实现可以同时存在
public class 类名 extends 父类 implements 接口1,接口2{
    ...
}

5.4.接口的成员特点

在JDK7以前接口中只能定义常量和抽象方法,但是随着JDK版本的更新接口中也可以定义一些新的内容,下面我们分别对各个JDK版本中接口的成员小结一下。

JDK7以及以前的版本

- 接口中的常量:
    如在接口中定义 int a=10; 默认被public static final修饰

- 接口中的方法:
    接口中的方法全都是抽象方法,不能有方法体。默认被public abstract修饰
    【实现类必须重写接口中所有的抽象方法】

JDK8版本

- 接口中的默认方法
    默认方法用public default修饰,允许写方法体。类似于类中的普通方法
    【实现类不需要重写接口中的抽象方法,你想重写也可以重写】

- 接口中的静态方法
    默认被public static修饰。类似类中的静态方法。
    【接口中的静态方法,直接用接口名调用即可】

JDK9版本

- 接口中的私有方法
    允许使用private修饰接口中的方法
    【私有方法只能在本接口中使用】

6. 多态

多态从字面上理解就是“多种状态”。在Java语言中,接口或者抽象类的多种不同的实现方式即为多态。 允许父类接收子类对象,或者接口接收实现类对象。

6.1.接口多态

接口多态体现在,允许使用接口接收多种实现类对象。如Usb是一个接口,而UsbMouse和UsbKeyBoard是Usb接口的实现类。多态的代码如下

//接口接收实现类对象,
Usb u1=new UsbMouse();
Usb u2=new UsbKeyBoard();

6.2.抽象类多态

抽象类多态体现在,允许使用父类接收多种子类对象。如Animal是一个父类,而Dog和Cat是Animal的子类。 那么多态的代码如下

//父类接收子类对象
Animal d=new Dog();
Animal c=new Cat();

多态案例
我们以接口多态为例来看一下代码演示。

假设Usb接口规范要求必须要有loadDirver加载驱动功能,和run运行功能。

public interface Usb{
    public void loadDriver();
    public void run();
}

接下来我们写Usb接口的两个实现类UsbMouse类、UsbKeyBoard类

public class UsbMouse implements Usb{
    public void loadDriver(){
        System.out.println("加载鼠标驱动");
    }
    public void run(){
        System.out.println("鼠标运行");
    }
}
public class UsbKeyBoard implements Usb{
    public void loadDriver(){
        System.out.println("加载键盘驱动");
    }
    public void run(){
        System.out.println("键盘运行");
    }
}

接下来写一个测试类,使用多态的写法创建对象并调用方法。我们会发现执行的是各个实现类中复写的方法。

public class PolymorphismTest1{
    public static void main(String[] args){
        Usb u1=new UsbMouse();
        u1.loadDriver(); //输出:加载鼠标驱动
        ur.run(); //输出:鼠标运行

        Usb u2=new UsbKeyBoard();
        u2.loadDriver(); //输出:加载键盘驱动
        u2.run(); //输出: 键盘运行
    }
}

说到这里,可能有人会发现,不使用多态的写法,直接通过创建子类对象也能达到同样的效果呀!那多态的写法有什么好处?我们继续往下看

6.3.多态的好处

多态最核心的用法,其实是把方法的参数写成父类或者接口,那么调用方法时可以传递任意的子类对象。 这样写的好处就是,同一个方法可以处理多个不同对象的功能。

就想下图中电脑通过Usb接口,既可以处理U盘的功能,也可以处理鼠标的功能。

1583738473025

定义一个电脑类,在电脑类写一个usbFunction方法用于给电脑扩展功能。扩展功能需要符合Usb的规范。

public class Computer{
    //Usb接口作为参数,调用该方法时可以接收任意的Usb实现类对象。
    public void usbFunction(Usb usb){
        //符合Usb规范的设备,要想被电脑使用,就必须先加载驱动,然后才能运行
        usb.loadDriver();
        usb.run();
    }
}

编写测试类

public class PolymorphismTest2{
    public static void main(String[] args){
        //创建一台电脑对象
        Computer com=new Computer();
        //创建一个鼠标对象
        Usb uMouse=new UsbMouse();
        //创建一个键盘对象
        Usb uKeyBoard=new UsbKeyBoard();

        //调用电脑的扩展功能。
        com.usbFunction(uMouse);
        com.usbFunction(uKeyBoard);
    }
}

如果你能看懂以上的案例代码,就说明对于多态的理解已经完全没问题了。可能代码还不能很顺畅的敲出来,多加练习就可以了。

6.4.多态的转型

多态其实就是把子类对象用父类来接收,可以把这种现象看做是一种类型转换,子类可以转为父类,同样父类也可以转换子类。

假设Animal是父类,Dog是子类如下,Dog类中有一个特有方法lookHome()

public abstract class Animal{
    public void eat();
}
public  class Dog{
    @Override
    public void eat(){
        System.out.println("够吃骨头");
    }
    //Dog类特有方法
    public void lookHome(){
        System.out.println("狗看家");
    }
}

接下来在测试类中使用多态的写法来调用Dog类的方法

public class PolymorphismTest3{
    public static void main(String[] args){
        //多态写法:对象是Dog类型,但是使用Animal类型接收
        Animal a=new Dog();
        a.eat(); //这句话是正确的
        a.lookHome(); //这句话是错误的,你自己试一下。

        //判断a对象是否为Dog类型,如果是才能进行向下转型。
        if(a instanceof Dog){
            //把a的类型强制转换为Dog类型
            Dog dog=(Dog)a;
        }
    }
}

通过上面代码演示得出如下结论

1.多态写法本身就是一种类型转型
    Animal a=new Dog(); //向上转型:子类转换为父类
2.多态的写法只能调用子父类共性方法,不能调用子类特有方法
    a.eat(); //Animal和Dog中共性方法,可以调用
    a.lookHome(); //Dog中的特有方法,不能调用。
3.如果想调用子类特有方法,必须进行向下转型
    if(a instanceof Dog){
        Dog dog=(Dog)a; //向下转型:父类还原为子类
    }

注意事项:

    1.向下转换我用的是“还原”这个词,也就是说Dog对象向上转换为Animal,那么
    Animal向下转换只能还原成Dog,不能转换为Cat.
        Animal a=new Dog();
        Dog d=(Dog)a; //a原本就是Dog类型,可以还原为Dog.

    2.如果违背了第1项,则会出现类型转换异常(java.lang.ClassCastException)
        Animal a=new Dog();
        Cat c=(Cat)a; //a原本是Dog类型,不能转换为Cat类型

7. 修饰符

7.1.this和super

this修饰符: 本类对象的引用
    this.成员变量   调用本类成员变量
    this()   调用空参数构造方法
    this.成员方法   调用本类成员方法
    this(参数)  调用本类有参数构造方法

super修饰符: 父类对象的引用
    super.成员方法   调用父类成员方法
    super.成员变量   调用父类成员变量
    super()   调用父类空参数构造方法
    super(参数)  调用父类有参数构造方法

7.2.权限修饰符

权限修饰符作用
private只能在本类被访问
public整个项目中可以访问
protected给子类访问
默认权限(不写)在同一个包中可以访问

7.3.状态修饰符

其他修饰符作用
abstract修饰类(抽象类)和方法(抽象方法)
static被类名访问
final修饰类不能被继承,修饰方法不能被复写,修饰变量不能被修改

修饰符细节

abstract不能共存原因
abstract和finalabstract必须被子类复写,final不让复写
abstract和privateabstract必须被子类复写,private不能继承更不能复写
abstract和staticabstract必须被子类复写,static只和类有关不能被复写


到此,java面向对象已经学习完啦,如有问题评论或者私信博主都可以哦,最后大家一起加油,成为你心中最想成为的那个"猿".

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值