Java:继承和多态(2)

一 super关键词

在 Java SE 中,super 是一个非常重要的关键字,用于引用父类(超类)的构造方法、字段或方法。

1.调用父类的构造方法

public class Animal {
    public String name;
    public int age;
    public Animal(String name,int age){
        this.name=name;
        this.age=age;
        System.out.println("animal");
    }

public class Dog extends Animal{
    static {
        System.out.println("静态代码块-Dog");
    }
    {
        System.out.println("实例代码块-Dog");
    }

    public Dog(String name,int age){
        super(name,age);
        System.out.println("gou");
    }
    public Dog(){
        super("大黄",10);
    }
    public void bark(){
        System.out.println(this.name+"正在汪汪叫");
    }
}

2. 访问父类的成员变量和方法

class Base{
    public int a=1;
    public int b=2;
    public void testBase(){
        System.out.println("testBase().........");
    }
    public void testA(){
        System.out.println("testA(). Base........");
    }
}
class Derived extends Base{
    public int c=3;
    public int a=11;
    public void testDerived(){
        System.out.println("testDerived().........");
    }
    public void testA(){
        System.out.println("testA(). Derived........");
    }
    public void test(){
        testA();
        super.testA();

        testBase();
        testDerived();
    }
    public void test1(){
        System.out.println(this.a);
        System.out.println(super.a);
        System.out.println(a);
        System.out.println(b);
    }
}
public class TEST {
    public static void main(String[] args) {
        Derived derived=new Derived();
        derived.test();
        derived.testA();
        System.out.println("----------");
        derived.test1();
        derived.test();
    }
}

 注:

  • super() 必须是子类构造方法中的第一条语句。如果父类构造函数有参数,则必须用 super(参数) 进行显式调用,否则 Java 会尝试调用父类的无参构造函数。

  • super 只能在子类中使用,不能用于普通方法中去直接引用父类。

  • 当父类方法被 private 修饰时,子类无法通过 super 来调用它,因为 private 方法对子类是不可见的。

二 super和this的关系

在 Java SE 中,superthis 是两个非常重要的关键字,用于处理类的继承、构造方法、方法调用以及变量访问。它们虽然有一些相似之处,但各自有不同的使用场景和语法规则。

1. superthis 的定义

  • super:用来引用当前对象的父类(超类)。它可以用来调用父类的构造方法、父类的字段或父类的方法。
  • this:用来引用当前类的对象实例。它可以用来调用当前类的构造方法、当前类的字段或当前类的方法。

2. superthis 的用途对比

2.1. 调用构造方法
  • super():用于调用父类的构造方法。必须是构造方法中的第一条语句。
  • this():用于调用当前类的其他构造方法(构造方法重载时)。同样必须是构造方法中的第一条语句。
public class Animal {
    public String name;
    public int age;

    public Animal(String name,int age){
        this.name=name;
        this.age=age;
    }
}
public class Bird extends Animal {
    public Bird(String name ,int age){
        super(name, age);
    }
}

2.2. 访问成员变量

  • super.变量名:用于访问父类的成员变量。如果子类定义了与父类同名的变量,super 可以区分出父类的变量。
  • this.变量名:用于访问当前类的成员变量。
class Parent {
    String name = "Parent Name";
}

class Child extends Parent {
    String name = "Child Name";
    
    void printName() {
        System.out.println(super.name);  // 访问父类的成员变量
        System.out.println(this.name);   // 访问当前类的成员变量
    }
}

public class Main {
    public static void main(String[] args) {
        Child child = new Child();
        child.printName();
    }
}

三 初始化及运行顺序

class Person {
public String name;
public int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
System.out.println("构造方法执行");
}
{
System.out.println("实例代码块执行");
}
static {
System.out.println("静态代码块执行");
}
}
public class TestDemo {
public static void main(String[] args) {
Person person1 = new Person("vvv",1);
System.out.println("============================");
Person person2 = new Person("hhh",2);
}
}

执行顺序

四 protected关键词

1. protected 修饰字段或方法

protected 修饰符通常用于定义类的成员变量和方法,这样它们不仅可以被同包中的类访问,还可以被不同包中的子类继承和访问。

public class TESTprotected {
    protected int a=100;

}

public class test extends TESTprotected {
    public void test(){
        System.out.println(super.a);
    }

    public static void main(String[] args) {
        test test=new test();
        System.out.println(test.a);
        test.test();
    }
}

在相同包中的类可以直接访问 protected 字段和方法

注:protected 设计的初衷是允许继承和包内部访问,同时隐藏类的实现细节。它比 public 更加封装,比 private 更具灵活性,特别适合于框架开发和继承设计中的类层次结构。 

五 继承方法

继承(Inheritance)是面向对象编程(OOP)中非常重要的概念。通过继承,子类可以继承父类的属性和方法,从而实现代码复用、扩展类功能和增强灵活性。

1.单继承

2.多继承

 3.不同类继承同一个类

六 final 关键字

在 Java 中,final 关键字有多种用途,它可以用来修饰方法变量。每种用途都有不同的含义和作用。 

1. final 修饰变量

final 修饰一个变量时,意味着这个变量只能被赋值一次,值一旦确定就不能再更改。

由一个变量变成一个常量。

public class Test {
    public static void main(String[] args) {
        final int a=10;
        a++;
        System.out.println(a);

    }
}

 

2.final 修饰引用类型

对于引用类型,final 修饰的变量只能指向一个特定的对象,不能再指向其他对象,但对象内部的属性可以修改。

 3.final 修饰成员变量

final 成员变量在类实例化时必须被初始化(可以在声明时初始化,也可以在构造方法中初始化),否则会导致编译错误。

必须在声明时或者构造方法中赋值,并且不能改变,否则编译错误。

public class Test {
    final int a;
    public Test(){
        a=1;
    }
public class Test {
    final int a=1;
    public Test(){
        
    }

4.final 修饰方法(密封方法)

final 修饰一个方法时,表示该方法不能被子类重写。这是为了防止子类改变父类的行为,确保该方法的实现不会被修改。

public class Test {
    public final void eat(){

    }//表示这个方法无法重写

5.final 修饰类

final 修饰一个类时,表示该类不能被继承。这通常用于确保类的实现不能被改变,防止其他类通过继承来修改或扩展该类的行为。

public final class Test {  //表示这个类无法被继承
    public String name;
    int age;
    

七 继承和组合

1. 继承(Inheritance)

通过它,一个类(子类)可以继承另一个类(父类)的属性和方法,从而实现代码的重用和扩展。 

class B {
        public int num = 1;
        public B() {
                func();
        }
        public void func() {
                System.out.println("B.func()");
        }
}
class D extends B {

        @Override
        public void func() {
                System.out.println("D.func() "+ num);
        }
}

public class TEST {
        public static void main(String[] args) {
                D d = new D();
        }
}

继承的特点

  1. 单继承:在 Java 中,一个类只能继承一个父类,但可以通过接口实现多重继承的效果。
  2. is-a 关系:继承表示子类与父类有 is-a 的关系,例如“子类是父类的一种”,如 Dog 继承 Animal,即狗是动物的一种。
  3. 方法重写:子类可以重写父类的方法以提供特定实现。
  4. 代码复用:子类自动拥有父类的属性和方法。

2. 组合(Composition)

组合是通过在类中包含其他类的对象来实现功能的复用。与继承不同,组合强调的是 has-a 关系,即一个类“拥有”另一个类的实例。

public class Cycle extends Shape{
    public void draw(){
        System.out.println("画一个“圆” ");
    }
}
public class Square extends Shape{
    public void draw(){
        System.out.println("画一个“正方形” ");
    }
}
public class Trapezoid extends Shape{
    public void draw(){
        System.out.println("画一个“矩形” ");
    }
}
public class Triangle extends Shape{
    public void draw(){
        System.out.println("画一个“三角形” ");
    }
}

public class Shape {
    public void draw(){
        System.out.println("画一个形状");
    }
}


//测试类
public class Test2 {
    public static void drawShape(Shape shape){
        shape.draw();
    }

    public static void main3(String[] args) {
        Trapezoid trapezoid=new Trapezoid();
        Triangle triangle=new Triangle();
        Square square=new Square();
        Cycle cycle=new Cycle();
        Shape[] shapes={trapezoid,triangle,square,cycle};
        for (Shape s:shapes) {
            s.draw();
        }
    }
    public static void main2(String[] args) {
        Trapezoid trapezoid=new Trapezoid();
        Triangle triangle=new Triangle();
        Square square=new Square();
        Cycle cycle=new Cycle();

        String[] strings={"cycle","square","triangle","trapezoid"};
        for (String s:strings) {
            if(s.equals("cycle")){
                cycle.draw();
            }else if(s.equals("trapezoid")){
                trapezoid.draw();
            }else {
                triangle.draw();
            }
        }
    }
    public static void main1(String[] args) {
        Trapezoid trapezoid=new Trapezoid();
        Triangle triangle=new Triangle();
        Square square=new Square();
        Cycle cycle=new Cycle();
        drawShape(trapezoid);
        drawShape(triangle);
        drawShape(cycle);
        drawShape(square);
    }
}

组合的特点

  1. has-a 关系:组合表示类与类之间有 has-a 的关系,例如“汽车有引擎”,这强调类之间的组合关系,而不是继承关系。
  2. 灵活性:组合是一种更灵活的关系,类的行为可以通过组合不同的对象来扩展或改变。
  3. 动态组合:组合可以在运行时决定类与类之间的关系,而继承是在编译时决定的。

八 多态

在 Java SE 中,多态(Polymorphism)是面向对象编程的一个重要概念。它允许一个对象以多种形式出现,即基于对象的实际类型,可以调用同名但行为不同的函数。多态使得代码更加灵活和可扩展,是实现代码复用的关键特性之一。

1.多态的实现条件

  1. 一定要是继承,子类继承父类。
  2. 子类要对父类的方法进行重写。
  3.  通过父类的引用调用重写的方法。
public class Animal {
    public String name;
    public int age;

    public Animal(String name,int age){
        this.name=name;
        this.age=age;
    }
    public void eat(){
        System.out.println(this.name+"正在吃饭。。。。。。。。");
    }
}
public class Bird extends Animal {
    public Bird(String name ,int age){
        super(name, age);
    }
    public void eat(){
        System.out.println(this.name+"正在吃鸟粮。。。。。。。");
    }
    public void fly(){
        System.out.println(this.name+"正在飞。。。。。。。");
    }
}
public class Dog extends Animal{
    public Dog(String name ,int age){
        super(name, age);
    }
    public void eat(){
        System.out.println(this.name+"正在吃狗粮。。。。。。。");
    }
    public void bark(){
        System.out.println(this.name+"正在汪汪叫。。。。。。。");
    }
}

public class Test {
    //动态绑定方法
    public static void fun1(Animal animal){
        animal.eat();
    }

    public static void main(String[] args) {
        Animal animal=new Dog("旺财",12);
        animal.eat();
        System.out.println("----");
        Dog dog=(Dog) animal;
        dog.bark();
        Animal animal1=new Dog("小白",2);
        if (animal1 instanceof Bird){
            Bird bird =(Bird) animal1;
            bird.fly();
        }else {
            System.out.println("animal1 instanceof Bird not");
        }
    }

    public static void main2(String[] args) {
        Dog dog=new Dog("旺财",12);
        fun1(dog);
        System.out.println("-------");
        Bird bird=new Bird("小白",1);
        fun1(bird);

    }
    public static void main1(String[] args) {
        Animal animal=new Dog("旺财",12);
        animal.eat();
    }
}

2.方法的重写

  1.  不能是一个静态方法。
  2. 被final修饰的方法不能被重写。
  3. 被private修饰的方法是无法被重写的。
  4. 如果子类重写父类的方法,子类的修饰权限要大于父类。

权限等级 

 

//父类的的方法    
public void eat(){
        System.out.println(this.name+"正在吃饭。。。。。。。。");
    }


//子类的方法
public void eat(){
        System.out.println(this.name+"正在吃鸟粮。。。。。。。");
    }
public Dog(String name ,int age){
        super(name, age);
    }
public class Test {
    //动态绑定方法
    public static void fun1(Animal animal){
        animal.eat();
    }
    public static void main(String[] args) {
        Dog dog=new Dog("旺财",12);
        fun1(dog);
        System.out.println("-------");
        Bird bird=new Bird("小白",1);
        fun1(bird);

    }
}


3.向上转移和向下转型 

 在 Java SE 中,向上转型(Upcasting)和向下转型(Downcasting)是两种类型转换的方式,通常在继承层次结构中使用,它们在多态(Polymorphism)的实现中扮演了重要角色。它们都涉及将子类对象与父类引用进行关联,但使用方式和目的不同。

3.1向上转型

向上转型是指将子类对象的引用赋给父类类型的引用变量。由于子类对象拥有父类的所有特性和方法,所以向上转型是自动且安全的。向上转型是多态的基础,允许父类引用指向子类对象。

子类的方法和成员变量给到父类

父类引用只能访问父类中声明的方法和属性,不能直接访问子类特有的方法和属性,但可以通过重写的方法实现多态。

向上转型的三种使用:

1.直接赋值
  public static void main2(String[] args) {
        Dog dog=new Dog("旺财",12);
        fun1(dog);
        System.out.println("-------");
        Bird bird=new Bird("小白",1);
        fun1(bird);

    }
2.方法传参(形参为父类型引用,可以接收任意子类的对象 )
        public static void eat(Animal animal){
                animal.eat();
        }
}
    public static void drawShape(Shape shape){
        shape.draw();
    }
3.方法的返回(返回任意子类的对象)
public static Animal buyAnimal(String var){
if("狗".equals(var) ){
return new Dog("狗狗",1);
}else if("猫" .equals(var)){
return new Cat("猫猫", 1);
}else{
return null;
}
}
public static void main2(String[] args) {
        Trapezoid trapezoid=new Trapezoid();
        Triangle triangle=new Triangle();
        Square square=new Square();
        Cycle cycle=new Cycle();

        String[] strings={"cycle","square","triangle","trapezoid"};
        for (String s:strings) {
            if(s.equals("cycle")){
                cycle.draw();
            }else if(s.equals("trapezoid")){
                trapezoid.draw();
            }else {
                triangle.draw();
            }
        }
    }

3.2 向下转型(Downcasting) 

将一个子类对象经过向上转型之后当成父类方法使用,再无法调用子类的方法,但有时候可能需要调用子类特有的 方法,此时:将父类引用再还原为子类对象即可,即向下转换。

 

    public static void main(String[] args) {
        Animal animal=new Dog("旺财",12);
        animal.eat();
        System.out.println("----");
        Dog dog=(Dog) animal;
        dog.bark();
        Animal animal1=new Dog("小白",2);
        if (animal1 instanceof Bird){
            Bird bird =(Bird) animal1;
            bird.fly();
        }else {
            System.out.println("animal1 instanceof Bird not");
        }
    }

希望对大家有所帮助!!!!!!! 

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值