当前位置: 首页 > news >正文

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 {@Overridepublic 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");}}

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

 

 

 

 


http://www.mrgr.cn/news/28019.html

相关文章:

  • Zabbix Server More than 75% used in the configuration cache
  • 动态内存管理(c语言)
  • C# 操作Excel的多种方式
  • C语言第13节:指针(3)
  • 【Redis】Redis的一些应用场景及使用策略
  • 《TCP/IP网络编程》学习笔记 | Chapter 10:多进程服务器端
  • matlab边缘点提取函数
  • 106、解析Java中1000个常用类:Timer类,你学会了吗?
  • 猫头虎分享:Python库 SQLAlchemy 的简介、安装、用法详解入门教程
  • 合并RAR分卷压缩包
  • Oracle(127) 如何使用闪回事务(Flashback Transaction)?
  • 如何用python做一个计算器
  • 如何快速查看Docker镜像的环境变量?
  • 从架构到业务:实现企业一致性与合规性的价值流优化方案
  • 元宇宙工作室招人及创斯人工智能
  • PyTorch详解-优化模块
  • 软考高级:存储系统 DAS、NAS、SAN 区别 - AI 解读
  • 【Spinalhdl】Scala编程之伴生对象
  • 内存dump文件分析
  • MS SQL Server 实战 排查多列之间的值是否重复
  • linux进程间通信——学习与应用命名管道, 日志程序的使用与实现
  • 全方位解读信息架构:从挑战到解决方案,推动企业数字化转型的全面指南
  • 【详细原理】蒙特卡洛树搜索
  • 【机器学习-监督学习】朴素贝叶斯
  • k8s的NodeIP、PodIP、ClusterIP、ExternalIP
  • 【RabbitMQ】工作模式