专栏首页网络技术联盟站JAVA基础 | java基础4(JAVA继承、JAVA多态、抽象类、接口)

JAVA基础 | java基础4(JAVA继承、JAVA多态、抽象类、接口)

JAVA继承

继承是由子对象完全继承父对象的数据和操作,“is”的关系。

  • 被继承的类被称为父类(superclass),也叫基类、超类。
  • 继承后的类称为子类(subclass),也叫派生类。

java支持单继承,使用关键字extends

语法:

子类 extends 父类

例:定义一个Animal类,再创建一个Dog类,继承Animal类。

class Dog extends Animal{
    .....
}


public class Person {
    public String name;
    public String sex;
    protected int age;
    public Person() {
        super();
    }
    public Person(String name, String sex, int age) {
        super();
        this.name = name;
        this.sex = sex;
        this.age = age;
    }   
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public String getSex() {
        return sex;
    }
    public void setSex(String sex) {
        this.sex = sex;
    }
    public int getAge() {
        return age;
    }
    public void setAge(int age) {
        this.age = age;
    }
}
public class Employee extends Person{    private String comName;      public Employee() {        super();        // TODO Auto-generated constructor stub    }    public Employee(String name, String sex, int age,String comName) {        super.name=name;        super.sex=sex;        super.age=age;        this.comName = comName;    }    public Employee(String comName) {        super();        this.comName = comName;    }    public String getComName() {        return comName;    }    public void setComName(String comName) {        this.comName = comName;    }    }
  • 子类若要引用父类的同名变量。要用super关键字,即super.变量名。
  • 子类若要引用父类的构造函数,通过super()调用。
this关键字:

表示当前对象,可以用于: 1.引用自身对象的成员变量 this.age;

2.引用自身对象的成员方法 this.display();

3.调用自身的构造方法 this("Jack",Male,10);

super 关键字

super 表示使用它的类的父类。super 可用于: 1.引用父类对象的成员变量 super.age;

2.引用父类对象的成员方法 super.display();

3.调用父类的构造方法 super("Jack",Male,10);

在java中,每一个类都默认具有null、this、super三个域,因此在任何类中都可以直接引用。

注意: 1.构造方法使用this或super时,必须位于方法体的第一条。 2.this不能用于static 3.构造方法不能被继承 4.当通过子类不含参数的构造函数创建子类对象时,先执行父类不含参数的构造函数,再执行子类不含参数的构造函数。 5.如果定义一个;类,没有调用extends,则它的父类是:java.lang.Object

形参和实参
  • 定义方法的参数是形式参数
  • 调用方法的参数是实在参数
  • 调用方法时要求参数个数相同,类型兼容
对象的比较—— ==和equals()
==
  • 比较两个基本类型变量的值是否相等
  • 比较两个引用类型的值即内存地址是否相等,即是否指向同一对象。
equals()
  • 比较两个对象的内容是否相等

JAVA多态(polymorphism)

多态是指同一个方法可作用于不同的对象,从而执行不同的方法代码并获得不同的结果。

1.多态是继封装、继承之后,面向对象的第三大特性。

2.多态现实意义理解:

现实事物经常会体现出多种形态,如学生,学生是人的一种,则一个具体的同学张三既是学生也是人,即出现两态。 Java作为面向对象的语言,同样可以描述一个事物的多种形态。如Student类继承了Person类,一个Student的对象便既是Student,又是Person。

3.多态体现为父类引用变量可以指向子类对象。

4.前提条件:必须有子父类关系。

注意:在使用多态后的父类引用变量调用方法时,会调用子类重写后的方法。

5.多态的定义与使用格式 定义格式:

父类类型 变量名=new 子类类型();
多态中成员的特点

1.多态成员变量:编译运行看左边

Fu f=new Zi();System.out.println(f.num);//f是Fu中的值,只能取到父中的值

2.多态成员方法:编译看左边,运行看右边

Fu f1=new Zi();System.out.println(f1.show());//f1的门面类型是Fu,但实际类型是Zi,所以调用的是重写后的方法。

java支持两种多态:动态多态和静态多态。

  • 静态多态性:在编译时,就可以被系统识别,也称为编译时多态、静态联编、静绑定。 方法重载(overload)采用的是静态联编的方法实现。
  • 动态多态性:在编译时不能被系统识别,而是在运行时才能被系统识别,也称为运行时多态,也称动态联编,也称动绑定。 方法覆盖(override)[也叫方法重写]、抽象方法和接口采用动态联编的方法实现。
方法重载:

在同一个类中,方法名相同,参数列表不同,与返回值无关。

public class MethodOverload {
    public static void main(String args[]) {
        int a = 51, b = -98, c = 8, d = 191;
        double u = 25.1, v = -29.8, x = 3.1, y = 89.98;
        System.out.println("51、-98、8、191四数的最大值是:" + max(a, b, c, d));
        System.out.println("25.1、-29.8、3.1、89.98四数的最大值是:" + max(u, v, x, y));
    }

    static int max(int a, int b, int c, int d) {
        int x, y;
        x = a > b ? a : b;
        y = c > d ? c : d;
        return x > y ? x : y;
    }

    static double max(double a, double b, double c, double d) {
        double x, y;
        x = a > b ? a : b;
        y = c > d ? c : d;
        return x > y ? x : y;
    }
    /*
     * 如果一个类中有两个同名方法,其参数列表完全一样,仅仅返回值类型不同,则编译时会产生错误
     */
    /*
        static double max(int a, int b, int c, int d) {
            int x, y;
            x = a > b ? a : b;
            y = c > d ? c : d;
            return x > y ? x : y;
        }
    */
}

####### 方法重写(方法覆盖):

在子类继承父类的关系中,子类的方法名和父类的方法名相同,参数列表相同,返回值类型相同。

class Sup {
    public int x, y;
    Sup(int a, int b) {
        x = a;
        y = b;
    }

    public void display() {
        int z;
        z = x + y;
        System.out.println("add=" + z);
    }
}

class Sub extends Sup {
    Sub(int a, int b) {
        super(a, b);
    }

    public void display() {
        int z;
        z = x * y;
        System.out.println("product=" + z);
    }
}

//diaplay()在编译时不能被系统识别,而是在运行时才被系统识别,也称为运行时多态,也称为动态联编,也称为动绑定。
public class ResultDemo extends Sub
{   ResultDemo(int x,int y)
    {   super(x,y);
    }
    public static void main(String args[ ])
    {   Sup num1=new Sup(7,14);
        Sub num2=new Sub(7,14);
        ResultDemo num3=new ResultDemo(7,14);
        num1.display( );
        num2.display( );
        num3.display( );
        num1=num2;
        num1.display();
        num1=num3;
        num1.display();
    }
}

多态有三个条件:

1.有继承关系 2.方法重写 3.父类的声明指向子类的引用

例1:

class Animal{
    int age = 10;
    public void shout(){
        System.out.println("叫了一声");
    }
}

class Dog extends Animal{
    int age = 28;
    public void shout(){
        System.out.println("汪汪汪");
    }
    public void gnawBone(){
        System.out.println("我在啃骨头");
    }
}

class Cat extends Animal{
    int age = 18;
    public void shout(){
        System.out.println("喵喵喵");
    }
}
public class TestPolym{
    public static void main(String[] args){
        Animal animal = new Dog();//向上可以自动转型
        System.out.println(animal.age);//属性调用时,仍然是基类的属性,属性没有多态!

        animalCry(new Dog());
        //传的具体是哪一个类就调用哪一个类的方法,大大提高了程序的可扩展性。
        //如果没有多态,这里需要写很多的重载方法,如果增加一种动物,就需要重载一种动物的喊叫方法,非常麻烦。
        //有了多态,只需要增加这个类继承Animal基类就可以了。
        animalCry(new Cat());

        Dog dog = (Dog) animal;//编写程序时,如果想要调用运行时类型的方法,只能进行类型转换,不然通不过编译器的检查。
        dog.gnawBone();
    }
}
多态的转型:

分为向上转型和向下转型。

  • 向上转型: 多态本身就是向上转型的过程。

格式:

父类类型 变量名 = new 子类类型

适用场景:当不需要面对子类类型时,通过提高扩展性,或者使用父类的功能就能完成相应的操作。

public class Animal {
    public void eat(){
        System.out.println("animal eatting...");
    }
}

public class Cat extends Animal{
    public void eat(){
        System.out.println("猫吃鱼");
    }
}

public class Dog extends Animal{
    public void eat(){
        System.out.println("狗吃骨头");
    }

    public void run(){
        System.out.println("我会跑");
    }
}

public class Main {
    public static void main(String[] args) {
        Animal animal = new Dog();//向上转型
        animal.eat();
    }
}


输出:狗吃骨头

上面的就是向上转型, Animal animal = new Dog();就是将子类对象Dog转化为父类对象Animal。这时animal这个引用调用的方法是子类方法。

向上转型注意点:

1.向上转型时,子类单独定义的方法会丢失,比如上面的Dog类中定义的run方法,当animal引用指向Dog类实例是访问不到run方法的,animal.run();会报错。 2.子类不能指向父类对象。Dog d = (Dog) new Animal这样是不行的。

向上转型好处: 1.减少重复代码 2.提高系统扩展性

  • 向下转型: 一个已经向上转型的子类对象可以使用强制类型转换的格式,将父类对象转为子类对象。

格式:

子类类型 变量名=(子类类型) 父类类型的变量;

适用场景:当要使用子类特有功能时。

以上面的例子来说:

//还是上面的animal和cat dog
Animal a = new Cat();
Cat c = ((Cat) a);
c.eat();
//输出  我吃鱼

Dog d = ((Dog) a);
d.eat();
// 报错 :java.lang.ClassCastException:com.wr.animal.Cat cannot be cast to com.wr.animal.Dog

Animal a1 = new Animal();
Cat c1 = ((Cat) a1);
c1.eat();
// 报错 :java.lang.ClassCastException:com.wr.animal.Animal cannot be cast to com.wr.animal.Cat

为什么第一段代码不报错呢,因为a本身就是Cat对象,所以当然可以转型为Cat,因为是Cat所以不能转为Dog。 而a1是Anmail对象,它不能向下转型Wie任何子类对象。比如发现一个古生物化石,知道它是一种动物,但你不能直接说他是猫或者他是狗。

向下转型注意点:

1.向下转型的前提是父类对象指向的是子类对象(也就是说,在向下转型之前,它得先向上转型) 2.向下转型只能转型为本类对象(猫是不能变成狗的)。

instanceof关键字

有一个场景:江苏人包含:淮安人、盐城人、扬州人…. 淮安人、盐城人、扬州人一定都是江苏人; 反过来,江苏人不一定都是淮安人。

父类和子类的对象之间转换:
  • java允许在父类和子类的对象之间进行转换: 1.自动转换 2.强制类型转换

子类和父类之间存在着“is a”的关系,所以子类转换为父类对象时,是自动转换。 当父类对象转换为子类对象时,必须要强制类型转换。

强制类型转换的格式:
if(父类对象名 instanceof 子类名){    子类对象名  = (子类名)父类对象名;}else{}
Fu f1=new Zi();Fu f2=new Son();if(f1 instanceof Zi){    System.out.println("f1是Zi的类型");}else{    System.out.println("f1是Son的类型");}

final关键字

用来修饰变量、方法、类。

  • 修饰变量:变量一旦初始化就不能改变,相当于定义了常量 final int x = 3;
  • 修饰方法:final方法在子类不能被重写(覆盖) final void eat(){}
  • 修饰类:final类不能被任何类继承(最终类) final class Person{}

抽象类

抽取子类共有的属性和方法。

设计S 和S1的时候发现S 和S1有共有的属性和方法 就将S 和S1的共有属性和方法抽象出来成为一个新的类叫做抽象类 abstract修饰的类就是抽象类

抽象类:

1、抽象类不能实例化,只能通过之类实例化 2、抽象类中可以有抽象方法,可以有实例方法,可以有实例变量 实例方法:有方法的声明 有方法的实现 抽象方法:只有方法的声明没有方法的实现,不能存在于普通类,就是用来被重写 3、如果一个类继承了一个抽象类必须重写所有抽象父类中所有的抽象方法,否则这个也是抽象类 4、抽象类是重构的结果

abstract class Animal{
    abstract void shout();//抽象方法没有方法体!
}

class Dog extends Animal{
    void shout(){//必须重写父类的抽象方法否则编译通不过
        System.out.println("汪汪汪!");
    }
}

接口

怎么理解?

  • 接口其实就是比“抽象类”还“抽象”的“抽象类”,实现规范和具体实现的分离。
  • 接口就是规范,定义的是一组规则,体现了现实世界中“如果你是。。则必须能的。。。”的思想。如果你是好人,则必须能干掉坏人。
  • 接口的本质是契约,就想现实中的法律一样,制定好后大家就要遵守。
  • 开发往往就是面向接口编程。

接口(interface)是一组方法集,接口中包含的方法都是抽象方法,定义方法体的任务留给实现该接口的类去完成。

接口的要点:

1.接口是java中的一种复合数据类型,使用interface关键字来定义的。 2.接口是一种特殊的“类”,一种特殊的“抽象类”。 3.接口中所有的方法都默认是public abstract的,并且只有方法头和参数列表,没有方法体。 4.接口中所有的变量都默认是public static final的。 5.接口中没有构造方法。 6.接口可以继承,并且可以多继承。 7.一个类可以实现多个接口。

注意点:

1.一个类可以继承一个类的同时实现多个接口,必须重写父类们的所有的抽象方法; 2.接口不能实例化,只能通过子类实例化。

普通类、抽象类、接口的区别?
  • 普通类:class修饰的 有成员变量、成员方法、构造函数
  • 抽象类:abstract class 修饰 有成员变量、成员方法、抽象方法、构造函数(只能被子类调用)
  • 接口:interface修饰 只有public final static修饰的变量和public abstract修饰的方法
接口和抽象类的区别:

1、抽象类和接口都不能直接实例化,如果要实例化,只能通过子类进行实例化。 2、抽象类要被子类继承,接口要被类实现。 3、接口所有的方法都是抽象方法,抽象类中可以可以有抽象方法也可以有实例方法。 4、接口里定义的变量只能是公共的静态的常量,抽象类中的变量是普通变量。 5、抽象类里的抽象方法必须全部被子类所实现,如果子类不能全部实现父类抽象方法, 那么该子类只能是抽象类。同样,一个实现接口的时候,如不能全部实现接口方法,那么该类也只能为抽象类。 6、抽象方法只能声明,不能实现,接口是设计的结果 ,抽象类是重构的结果 7、抽象类里可以没有抽象方法 8、抽象方法要被实现,所以不能是静态的,也不能是私有的。 9、接口可继承接口,并可多实现接口,但抽象类只能单根继

定义接口:
[public] [interface] 接口名称 [extends 父接口名列表]{    //静态常量    [public] [static] [final] 数据类型 变量名 = 常量名;    //抽象方法    [public] [abstract] [native] 返回值类型 方法名(参数列表);}

接口可以继承,而且可以多继承

interface IA{..}interface IB{..}interface IB{..}interface ID extends IA,IB,IC{..}
实现接口:
[修饰符] class 类名 [extends 父类名] [implements 接口A,接口B,...]{    类的成员变量和成员方法;    为接口A中的所有方法编写方法体,实现接口A;    为接口A中的所有方法编写方法体,实现接口B;    ...}
[修饰符] class A implements IA{...}[修饰符] class B extends A implements IB,IC{..}
interface IExample{
    void method1();
    void method2();
}
abstract class Example1 implements IExample{
    public void method1(){
        //.. ..
    }
}

//因为只实现了一个方法,所以类Example1需要定义成抽象类。

接口代码:

public interface Flyer{
    public void takeOff();
    public void land();
    public void fly();
}

public class Bird extends Animal implements Flyer{
    public void takeOff()[
        ....
    ]
    public void land(){
        ....
    }
    public void fly(){
        ....
    }
    public void buildNest(){
        ....
    }
    public void layEggs(){
        ....
    }
    public void eat(){
        ....
    }

}

本文分享自微信公众号 - 网络技术联盟站(it666lmz)

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2019-10-12

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 华为路由交换技术 | 虚拟网关冗余协议VRRP(Virtual Router Redundancy Protocol)介绍

    VRRP:虚拟网关冗余协议 Virtual Router Redundancy Protocol.三层网关冗余技术。对用户的网关做冗余。

    网络技术联盟站
  • 网络工程师从入门到精通-通俗易懂系列 | GRE V**入门,包教包会!

    通用路由封装协议GRE协议,它提供了将一种协议的报文封装在另一种协议报文中的机制,使报文能够在tunnel(隧道)中传输。

    网络技术联盟站
  • Maven教程,一篇带你走入“内行”!

    简介:通过热部署配置,可以便捷地把本地项目发布到远程的 tomcat (发布会不用重启 tomcat 就能看到效果)

    网络技术联盟站
  • 第十天 面向对象-继承抽象类【悟空教程】

    奋斗蒙
  • AS3.0中类初始化的顺序

    父类--静态变量 子类--静态变量 父类--变量 父类--构造器 子类--变量 子类--构造器

    meteoric
  • JavaSE(五)JAVA对象向上转型和向下转型

    今天做了一个测试的题目,发现自己还是很多问题没有静下心来做。很多问题是可以自己解决的但是自己一是没有读清题意,二是自己心里太急躁了。所以这个要自己应以为鉴!  ...

    用户1195962
  • Java Review (十、面向对象----继承)

    使用继承,人们可以基于已存在的类构造一个新类。继承已存在的类就是复用(继承)这些类的方法和域。在此基础上,还可以添加一些新的方法和域, 以满足新的需求。这是 J...

    三分恶
  • Java|继承学习总结

    继承指一个类(通常称为子类),去继承另一个类(通常称为父类)的属性和方法,通过继承子类可以使用父类的属性和方法.

    算法与编程之美
  • JavaSE 基础学习之三 —— Java 的继承与接口

    版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/...

    剑影啸清寒
  • NLP应该如何学、如何教?斯坦福大学大牛Dan Jurafsky教授专访

    AI 科技评论按:自然语言处理是一个高度跨学科的领域,包含了语言学、计算机科学、统计学等等许多传统学科的内容。在课堂中,自然语言处理的教师者们要根据课程长度、学...

    AI科技评论

扫码关注云+社区

领取腾讯云代金券