Java从入门到精通 第10章 接口、继承与多态

类的继承

  • extends关键字标识继承关系
  • super()语句调用父类的构造方法,也可以使用super关键字调用父类的成员方法,但是子类没有权限调用父类private成员方法
  • 重写父类方法时,权限只能由小到大
  • 重写父类方法修改返回值类型只能是父类返回值类型的子类(JDK5)
  • 实例化子类对象时首先要实例化父类对象,无参数构造方法自动调用,有参数的构造方法不能被自动调用(需要传参数)
  • 在继承的机制中,创建一个子类对象将包含一个父类子对象,这个父类子对象与父类创建的对象是一样的,后者来源于外部,前者来源于子类对象的内部(子类对象包含父类子对象)
  • 如果使用finalize()方法对对象进行清理,需要确保子类的finalize()方法的最后一个动作是调用父类的finalize()方法,保证垃圾回收对象占用的内存时,对象的所有部分都能被正常终止
  • static方法必须重写成static方法,final方法不可重写
package ex10_Interface;

class Parent {
    public Parent() {
        System.out.println("调用父类的Parent()构造方法");
    }

    protected void doSomething() {  //父类protected方法
        //do Something
    }

    protected Parent doIt() {  //父类protected方法,返回Partent类型
        return new Parent();
    }
}

class SubParent extends Parent {
    public SubParent() {
        super();  //使用super()调用父类构造方法
        super.doSomething();  //使用super关键字调用父类成员方法
        System.out.println("调用子类的SubParent()构造方法");
    }

    public void doSomethingNew() {  //子类新增方法
        //do something new
    }

    public void doSomething() {  //重写父类方法,修改权限为public
        //do Something
    }

    public Subroutine doIt() {  //重写父类方法,返回SubParent类型
        return new Subroutine();
    }
}

public class Subroutine extends SubParent {
    public Subroutine() {  //自动调用父类构造方法
        System.out.println("调用子类的Subrountine()方法");
    }

    public static void main(String[] args) {
        Subroutine s = new Subroutine();
    }
}

Object类

  • 所有类都继承与java.lang.Object类
    • 任何类都可以重写Object类中的方法 clone(), finalize(), equals(), toString()等,getClass(), notify(), notifyAll(), wait()等方法不能被重写,因为这些方法被定义为final类型
  • getClass()方法获取当前运行的类名(上下文中获得,包含class),返回值是一个Class实例,getClass().getName()返回类名
  • toString()方法将一个对象返回字符串形式
  • equals()方法默认实现的是==比较两个对象的引用,而不是比较内容,要想实现真正的比较对象的内容,需要在自定义类中重写equals()方法
package ex10_Interface;

public class Test {
    public void myMethod(Test t) {
        System.out.println(t);
    }

    public String toString() {  //getClass()自动获取当前类名
        return "在" + getClass().getName() + "中重写toString()方法";
    }


    public static void main(String[] args) {
        Test t = new Test();
        System.out.println(t);  //自动调用toString方法
        String s1 = "123";
        String s2 = "123";
        System.out.println(s1.equals(s2));  //返回true
        Test t1 = new Test();
        Test t2 = new Test();
        System.out.println(t1.equals(t2));  //返回false,默认使用==比较引用

        //对象类型转换
        Test t3 = new Test2();
        Test2 t4 = (Test2) t3;  //向下转型
//        System.out.println(t3 instanceof Anything);  //t3不是Anthing的对象,报错

        //多态
        Test2 tt2 = new Test2();
        Test3 tt3 = new Test3();
        t1.myMethod(tt2);  //不同子类的对象调用父类的方法,向上转型
        t1.myMethod(tt3);
        tt2.myMethod(tt2);  //使用父类对象或者子类对象调用都可以
        tt2.myMethod(tt3);

    }
}

class Test2 extends Test {}

class Test3 extends Test {}

class Anything {
}

对象类型的转换

  • 向上转型
    • 子类实例化的对象可以调用父类的方法,传入子类对象,子类对象传入以父类对象为参数的方法为向上转型
    • 子类实例化的对象可以赋值给父类类型的变量(向上转型)
  • 向下转型
    • 将子类实例化的对象赋值给父类类型的变量为向上转型,必须使用强制类型转换(告知编译器这个父类就是某个子类,显式类型转换)将父类类型的变量转换为子类类型,直接赋值会报错
    • 越具体的对象具有的特性越多,越抽象的对象具有的特性越少,在做向下转型时,将特性范围小的对象转换为特性特性范围大的对象肯定会出问题,如果是父类new出来的对象赋值给子类对象,强制类型转换发生ClassCastException异常
  • 使用instanceof判断对象类型
    • 判断对象是否是子类的实例,如果是可以进行向下转型。a instanceof b; 返回布尔类型,不相关的类会报错
    • 也可以判断是否有一个类实现了某个接口

方法的重载

参数个数不同、类型不同、类型顺序不同,不定长参数...(不定长参数作为数组)

多态

子类中的各类似方法的实现只需在父类中实现一次即可,所有继承父类的子类的对象都是父类的子对象,都可以调用父类中以父类对象为参数的方法,子类对象向上转型传入参数。

抽象类和接口

  • 使用abstract关键字定义抽象类和抽象方法,抽象类不可以实例化对象,抽象方法没有方法体,因此抽象方法没有任何意义除非被重写,而承载这个抽象方法的抽象类必须被继承,因此不可能在非抽象类中定义抽象方法,抽象类除了被继承之外没有任何意义
  • 由于继承抽象类必须要实现抽象类中的所有抽象方法,但是有些子类并不需要实现其中的抽象方法,Java不能同时继承多个父类,就有了接口的概念。接口是抽象类的延伸,接口中的所有方法都没有方法体。
  • 使用interface关键字定义接口,可以像类一样使用权限修饰符,public关键字仅限用于与其同名的文件中被定义,接口中的方法必须被定义为public或abstract形式,即使不声明为public,它也是public
    • 接口中定义的任何字段都自动式static和final的
    • 实现接口时使用implements,多个接口使用逗号个卡尼
    • 接口也可以被接口继承,使用extends
package ex10_Interface;

interface drawTest {  //定义接口
    void draw();  //定义方法,省略了public和abstract,其他不被编译器认可
}

interface drawTest2 extends drawTest {
    void draw2(); //接口的继承
}

class A {
}

class B extends A implements drawTest {  //多个接口使用逗号隔开
    public void draw() {  //由于该类实现了接口需要覆盖接口定义的方法
        System.out.println("B类继承A类,实现接口drawTest,B.draw()");
    }
}

class C extends A implements drawTest {
    public void draw() {
        System.out.println("C类继承A类,实现接口drawTest,C.draw()");
    }
}


public class UseInterface {
    public static void main(String[] args) {
        System.out.println("----------------------------");
        drawTest inf = new B();  //接口也可以进行向上转型
        drawTest inf2 = new C();
        inf.draw();
        inf2.draw();
        B b = new B();  //也可以直接使用对象调用成员方法
        b.draw();
    }
}
发布了46 篇原创文章 · 获赞 0 · 访问量 1028

猜你喜欢

转载自blog.csdn.net/weixin_37680513/article/details/103382178
今日推荐