直播网站可以做毕设吗,电子产品网站建设分析的摘要,wordpress多站点 主题,让人家做网站需要问什么问题1 多态
1.1 多态
1.1.1 多态的意义
一个类型的引用在指向不同的对象时会有不同的实现。依然借助前面案例中的 Person类、Student类和 Teacher 类举例#xff0c;看如下的代码#xff1a;
Person p1 new Student();
Person p2 new Teacher();
p1.schedule();
p2.schedul…1 多态
1.1 多态
1.1.1 多态的意义
一个类型的引用在指向不同的对象时会有不同的实现。依然借助前面案例中的 Person类、Student类和 Teacher 类举例看如下的代码
Person p1 new Student();
Person p2 new Teacher();
p1.schedule();
p2.schedule();
同样声明为 Person 类型的变量 p1和p2当指向不同的对象时可以有不同的表现。这种现象在 Java中被称为多态。
多态是面向对象的三大基本特征之一包含
个体多态行为多态
1.1.2 什么是多态
多态的定义计算机程序运行时相同的消息可能会送给多个不同的类别之对象而系统可依据对象所属类别引发对应类别的方法而有不同的行为。
这个定义很晦涩可以从两个方面理解
1、个体多态
父类型定义的变量引用的子类型个体是多种多样的如Person变量可以引用Student、Teacher、Worker对象等个体多态是用向上造型实现的
2、行为多态
父类型变量引用子类型实例后执行方法时候可以得到多种结果如Person变量分别引用Student、Teacher、Worker对象时候执行schedule方法得到的结果不同行为多态是利用方法重写实现的
1.1.3 为什么需要多态
比如有类关系如下图所示 如何使用多态呢首先多态的前提是继承在有继承关系存在时候才能使用多态其次是要对子类型进行统一处理比如所以人员都要执行计划。具体在实际开发中可以先不要考虑多态先按照具体类型编程当发现各种子类型都需要相同处理时候再重构代码提升到父类型统一进行处理这样就是多态处理了。比如学生要执行计划schedule教师要执行计划schedule工人也要执行计划schedule就统一装到Person数组中用循环调用schedule方法一起执行计划。
1.1.4【案例】多态的基础应用示例
在上一个案例的基础上测试行为多态。
案例示意代码如下
public class PolyDemo1 {public static void main(String[] args) {// 使用父类引用指向子类对象 - 子类向上造型Person p1 new Student(Tom, 12);Person p2 new Teacher(Andy, 28);Person p3 new Worker(Jerry, 28);// 父类引用调用抽象方法实际执行子类实现的方法// - 行为多态p1.schedule();p2.schedule();p3.schedule();// 父类引用仅能访问父类中声明的成员// 父类应用无法访问子类中声明的成员// p1.study(); // 编译错误无法访问}
}
1.1.5【案例】多态的扩展应用示例
在上一个案例的基础上使用数组存储多个对象统一执行其 schedule() 方法。
案例示意代码如下
package oop_04.polymorphic;
public class PolyDemo2 {public static void main(String[] args) {// 多态数组Person[] array {new Student(Tom, 12),new Teacher(Andy, 28),new Worker(Jerry, 28)};for(int i0;iarray.length;i) {test(array[i]);}Student s1new Student(Lucy,15);// 子类类型的对象也可以传入该方法test(s1);}/*** 方法的参数为父类形态* 该父类的任意子类对象均可以传入该方法* param person*/public static void test(Person person){person.schedule();}
}
2 接口 interface
2.1 什么是接口
2.1.1 多继承问题
讨论接口之前先看一个物品归类的生活实例 查看这个商品分类可看出
1、相同类别的商品具有相似特征且属性类似比如“新鲜水果“类、”海鲜水产“类
2、同类标签便于管理统一存储和调度
3、也存在跨类别的分类标签比如“地方特产“、”国际美食“
4、跨类别的分类标签体现了一个物品属于多种类型的现象这种现象称为“多继承”
如果用 Java 代码来表现上述情况会发现Java的继承可以实现树形分类但是无法处理跨类别标签 不过Java提供了接口解决了跨类型的继承问题。
2.1.2 什么是接口
接口在JAVA编程语言中是一个抽象类型通常以interface来声明。
从面向对象编程的角度可以将接口理解为对不同类型的事物的共同的行为特征的抽象。例如鹰和飞机属于不同类型的事物但是都有飞行的行为特征。 可以把接口看成是特殊的抽象类。
2.1.3 接口和抽象类
抽象类和接口都属于抽象的概念它们有一些区别可以从同类别和跨类别的角度来考虑
同一种类别的公共行为和属性可以抽取到抽象类中。抽象类用于表示一种具有共性的类可以包含实现的方法和具体的属性。比如对于喜鹊和老鹰这两种鸟类它们都属于鸟类的范畴可以将它们共同的行为和属性抽象到一个抽象类如Bird中以实现代码的重用和扩展。不同种类的公共行为可以抽取到接口中。接口用于定义一组相关的方法用于表示某种能力或行为。比如喜鹊、老鹰和飞机都具有起飞和着陆的功能但它们并不属于同一种类此时可以将与飞行相关的共同行为抽取到一个接口如Flyable中不同类别的对象可以通过实现该接口来具备飞行的能力。
根据以上原则对于喜鹊来说它可以继承自抽象类Bird以获取鸟类的共性属性和行为并且还可以实现接口Flyable以具备飞行的能力。
抽象类和接口的设计原则
将所有子类共有的方法抽象化到父类中可以使用抽象类。将部分子类中的公共方法抽象化到接口中适用于不同类别但具有相似行为的对象。
通过合理地使用抽象类和接口可以实现代码的复用和扩展并且更好地表示对象之间的关系和行为。选择使用抽象类还是接口取决于具体的设计需求和对象之间的关系。
2.2 接口的语法
2.2.1 接口的语法
使用interface定义接口
1、接口中只能定义常量和方法
可以省略常量的修饰词 public static final可以省略抽象方法修饰词 public abstract
2、接口不能实例化创建对象,
3、接口只能被继承作为父类型被子类型实现
比如定义飞行接口
包含常量ID包含 3 个抽象方法
代码结构示意如下 2.2.2 实现接口
子类使用implements实现接口必须实现该接口中所有的抽象方法。
具体语法如下所示 一个类可以实现多个接口实现的接口直接用逗号分隔。
具体语法如下所示 2.2.3【案例】接口的示例
定义接口 Flyable 和类 Bird并类 Plane实现接口Flyable以及类 Eagle 继承Bird并实现Flyable编写代码测试接口的用法。
案例示意代码如下所示
package oop_04.interface01;
/*** 飞行接口*/
public interface Flyable {int ID 1;/*** 起飞*/void takeOff();/*** 飞行*/void fly();/*** 着陆*/void land();
}
package oop_04.interface01;
public class Plane implements Flyable{Overridepublic void takeOff() {System.out.println(Plane takeOff...);}Overridepublic void fly() {System.out.println(Plane fly...);}Overridepublic void land() {System.out.println(Plane land...);}
}
package oop_04.interface01;
public class Bird {public void eat(){System.out.println(eat...);}public void sleep(){System.out.println(sleep...);}
}
package oop_04.interface01;
public class Eagleextends Bird implements Flyable{Overridepublic void takeOff() {System.out.println(Eagle takeOff...);}Overridepublic void fly() {System.out.println(Eagle fly...);}Overridepublic void land() {System.out.println(Eagle land...);}
}
package oop_04.interface01;
public class InterfaceDemo1 {public static void main(String[] args) {// Flyable flyablenew Flyable(); // 接口不可被实例化System.out.println(Flyable.ID); // 接口中定义的是静态常量Flyable eagle new Eagle(); // 接口类型引用指向实现类的对象eagle.fly(); // 实际执行实现类重写的方法逻辑Flyable plane new Plane(); // 接口类型引用指向实现类的对象plane.fly(); // 实际执行实现类重写的方法逻辑// eagle.eat(); // 无法访问实现类特有的方法}
}
2.3 接口与多继承
2.3.1 接口的继承
在Java中接口之间也可以进行继承这被称为接口的继承或接口的扩展。
接口的继承允许一个接口继承另一个接口的方法签名。通过继承子接口可以获得父接口定义的方法签名并且可以在子接口中添加新的方法签名。子接口继承了父接口的方法签名后必须提供这些方法的具体实现。
接口的继承使用关键字extends后面跟着要继承的父接口名称。一个接口可以继承多个接口多个父接口之间使用逗号分隔。
下面是一个接口继承的示例
interface Shape {void draw();
}
interface Circle extends Shape {double getRadius();
}
interface Colorable {void setColor(String color);
}
interface ColoredCircle extends Circle, Colorable {void rotate();
}
在上面的示例中接口Circle继承了接口Shape表示Circle接口扩展了Shape接口的方法签名。接口ColoredCircle继承了接口Circle和Colorable表示ColoredCircle接口扩展了这两个父接口的方法签名并且可以在子接口中添加新的方法签名rotate()。
接口的继承使得接口之间可以建立层次结构从而实现方法签名的复用和组合。通过继承我们可以定义更具体和特定的接口以满足不同的需求和功能。
2.3.2 接口与多继承
接口与多继承的关系是一个常见的面试话题。在Java中类只能继承自一个父类这是单继承的限制。然而一个类可以实现多个接口这就允许了多继承的实现。
多继承的概念意味着一个类可以从多个父类继承属性和方法。然而在Java中类只能继承一个父类。这就是为什么Java引入接口的原因以实现多继承的效果。通过实现多个接口一个类可以获得多个接口定义的行为和功能实现了类的多继承。
如下图所示 在这个示例中有三个接口Person人、Flyable可飞行和Swimmable可潜水。
钢铁侠类实现了Person接口并且还实现了Flyable和Swimmable接口。这意味着钢铁侠类具有Person接口定义的人的行为和属性同时也具有Flyable接口定义的飞行行为和Swimmable接口定义的潜水行为。
通过实现多个接口钢铁侠类获得了多个接口定义的行为和功能实现了类的多继承效果。钢铁侠类可以同时表现出人的特征、飞行的能力和潜水的能力。
接口的多继承使得类可以在不受单继承限制的情况下获得多个接口定义的功能提供了更大的灵活性和可扩展性。
2.3.3 经典面试题目接口和抽象类的区别
面试时候可以尝试从语法层面回复这个问题
接口和抽象类在语法上有一些区别主要涉及以下几个方面
声明方式抽象类使用 abstract 关键字进行声明使用 class 关键字定义类。接口使用 interface 关键字进行声明。
继承关系抽象类通过使用 extends 关键字继承其他类或抽象类。一个类只能继承一个抽象类。接口通过使用 implements 关键字实现一个或多个接口。一个类可以实现多个接口。
方法实现抽象类可以包含实现的方法和抽象的方法。接口只能包含抽象的方法不包含具体的方法实现。所有的方法都隐式地被声明为抽象方法不需要使用 abstract 关键字。实现接口的类必须提供方法的具体实现。Java 8 引入了接口中的静态方法和默认方法使得接口具备了一定的实现能力。
2.3.4 经典面试题目Java如何实现多继承的
在Java中类是单继承的即一个类只能继承自一个父类。然而通过接口的使用Java可以实现多继承的效果。类可以实现多个接口中的方法从而获得多个接口定义的行为和功能。这种机制提供了灵活性和可扩展性使得Java在面对多继承需求时能够更好地满足设计和开发的需要。 3 造型
3.1 向上造型
3.1.1 向上造型
向上造型Upcasting是指将一个子类对象赋值给父类引用变量的过程。通过向上造型可以将一个子类对象视为其父类类型实现多态性的体现。
向上造型的特点
子类对象可以赋值给父类引用变量但是父类对象不能赋值给子类引用变量。向上造型是自动进行的不需要额外的转换操作。通过向上造型可以调用父类中声明的方法但无法调用子类中特有的方法。
向上造型的优势
实现多态性通过向上造型可以将不同子类的对象视为父类类型统一对待实现多态性的效果。灵活性和扩展性通过向上造型可以在不改变父类引用的情况下使用不同的子类对象使程序具备更大的灵活性和可扩展性。
3.1.2 【案例】向上造型示例
示例代码
class Person {private String name;public Person(String name) {this.name name;}public String getName() {return name;}public void printInfo() {System.out.println(Person: name);}
}
class Student extends Person {private int studentId;public Student(String name, int studentId) {super(name);this.studentId studentId;}public int getStudentId() {return studentId;}public void printInfo() {System.out.println(Student: getName() , Student ID: studentId);}
}
class Teacher extends Person {private String subject;public Teacher(String name, String subject) {super(name);this.subject subject;}public String getSubject() {return subject;}public void printInfo() {System.out.println(Teacher: getName() , Subject: subject);}
}
public class Main {public static void main(String[] args) {Person person1 new Student(Alice, 123);Person person2 new Teacher(Bob, Math);person1.printInfo(); // 输出: Student: Alice, Student ID: 123person2.printInfo(); // 输出: Teacher: Bob, Subject: Math// 向上造型Person person3 new Student(Carol, 456);Person person4 new Teacher(David, Science);person3.printInfo(); // 输出: Student: Carol, Student ID: 456person4.printInfo(); // 输出: Teacher: David, Subject: Science}
}
在上述示例中Person是一个基类Student和Teacher是其子类。我们可以将Student和Teacher对象向上造型为Person类型并将它们赋值给Person引用变量person3和person4。通过向上造型我们可以使用Person引用变量调用Person类中的方法和属性。在调用printInfo()方法时由于方法被子类重写实际上会根据对象的实际类型调用相应的子类方法。
这样做的好处是我们可以使用统一的Person类型处理不同类型的对象实现了多态性。通过向上造型我们可以灵活地处理不同类型的子类对象使代码更具扩展性和可维护性。
3.2 向下造型
3.2.1 向下造型
向上造型中有个特性“无法调用子类中特有的方法”如果调用子类行特有的方法呢这个就需要使用向下造型了。
向下造型Downcasting是指将一个已经向上造型Upcasting的对象重新转回其原始的子类类型。它允许我们在需要的时候访问和调用子类特有的方法和属性。
3.2.2【案例】向下造型示例
在 Java 中向下造型需要使用强制类型转换操作符(子类类型)来实现但在进行向下造型之前需要先确保对象实际上是指定的子类对象。否则如果尝试对一个不兼容的对象进行向下造型将会抛出ClassCastException异常。
以下是一个示例演示了向下造型的使用
/*** 演示向下转型*/
public class Demo02 {public static void main(String[] args) {Person person1 new Student(Alice, 123);Person person2 new Teacher(Bob, Math);// 直接使用类型引用调用子类特有的方法会编译错误// person1.getStudentId(); // 编译错误// person2.getSubject(); // 编译错误// 向下转型Student student (Student) person1;Teacher teacher (Teacher) person2;System.out.println(student.getStudentId()); // 输出: 123System.out.println(teacher.getSubject()); // 输出: Math// 向下转型时如果类型不匹配会抛出ClassCastException// Teacher teacher2 (Teacher) person1; // 抛出ClassCastException}
}
需要注意的是在进行向下造型之前我们需要确保对象实际上是指定的子类对象。否则如果尝试对一个不兼容的对象进行向下转型将会导致运行时异常。
向下转型的使用需要谨慎应确保转型操作的合法性和正确性。如果不确定对象是否适合进行向下转型可以使用instanceof运算符进行类型检查以避免可能的异常。
3.2.3 instanceof 运算
instanceof 运算符用于检测对象是否是指定类型的实例。它经常与向下造型一起使用以实现类型安全的转换避免类型转换异常的发生。
instanceof 运算符的语法如下
对象 instanceof 类型
其中对象是要检测的对象类型是要检测的类名或接口名。
instanceof 运算符返回一个布尔值如果对象是指定类型的实例则返回 true否则返回 false。
下面是一个示例演示了instanceof 运算符的使用
Person person1 new Student(Alice, 123);
Person person2 new Teacher(Bob, Math);
// 使用instanceof运算符判断对象是否是某个类的实例
System.out.println(person1 instanceof Student); // 输出: true
System.out.println(person1 instanceof Person); // 输出: true
System.out.println(person1 instanceof Teacher); // 输出: false
System.out.println(person2 instanceof Student); // 输出: false
在上述示例中我们创建了一个 Person 类的实例 person1它实际上是一个 Student 对象。使用 instanceof 运算符可以判断 person1 是否是 Student 类的实例结果为 true。同样地我们也可以判断 person1 是否是 Person 类的实例结果同样为 true。然而由于 person1 并不是 Teacher 类的实例所以返回 false。
使用 instanceof 运算符可以帮助我们在进行类型转换之前先进行类型检测确保转换的安全性。这样可以避免类型转换异常的发生并在需要时选择执行相应的操作。
3.2.4使用instanceof保护造型
使用 instanceof 运算符可以保护向下造型避免 ClassCastException 异常的发生从而减少程序中的运行错误。
在使用 instanceof 运算符进行向下造型时可以先使用 instanceof 进行类型检测以确保对象的类型与要转型的类型匹配。如果匹配成功就可以进行转型操作否则可以选择执行其他逻辑或抛出异常。
下面是一个示例演示了如何使用 instanceof 运算符保护向下造型
if (person1 instanceof Student) {Student student (Student) person1;System.out.println(student.getStudentId()); // 输出: 123
}
在上述示例中我们先使用 instanceof 运算符检测 person1 是否是 Student 类的实例。如果匹配成功我们就可以将 person1 强制转型为 Student 类型并调用 getStudentId() 方法。这样可以避免在转型过程中发生 ClassCastException 异常。
此外Java 17 引入了 instanceof 模式匹配的新特性可以进一步简化向下转型的编码
if (person1 instanceof Student student) {System.out.println(student.getStudentId()); // 输出: 123
}
在上述示例中我们使用 instanceof 模式匹配将匹配成功的结果直接绑定到 student 变量上省去了显式的类型转换操作。这样可以更加简洁地实现向下转型并且代码更加清晰易读。
使用 instanceof 运算符和 instanceof 模式匹配可以提高程序的健壮性确保类型转换的安全性减少潜在的运行时错误。
4 内部类
4.1 内部类概述
4.1.1 内部类概述
内部类顾名思义就是声明在一个外部类内部的类。内部与外部是一个相对的说法外部类是指内部类所在的类。
内部类一般有以下4种分类
局部内部类声明在外部类的局部位置上有类名成员内部类声明在外部类的成员位置上有类名无static修饰静态内部类声明在外部类的成员位置上有类名有static修饰匿名内部类在一行代码上继承父类并且创建出子类实例的语法无类名
如下图所示 上述4种内部类中匿名内部类在日常开发中较为常见将在本节中进行介绍。其他的内部类在基础的开发中较为少见在一些特定的设计模式和框架中有所应用将在后续的课程中进行介绍。
4.2 匿名内部类
4.2.1 什么是匿名内部类
如果在一段程序中需要创建一个类的对象通常这个类需要实现某个接口或者继承某个类而且对象创建后这个类的价值也就不存在了这个类可以不必命名称之为匿名内部类。
利用匿名内部类可以写出简洁明快的代码在实际开发中应用非常广泛。
语法示例如下 4.2.2 使用匿名内部类
匿名内部类的语法在一行代码上完成了两个功能继承父类创建子类行对象所以要有1个前提条件有一个可以被继承的父类型 这个父类型可以是类、抽象类、接口。如下所示 利用匿名内部类可以在一行代码上继承父类并且创建出子类实例。这样可以使用最简洁的代码实现最多的功能。由于利用匿名内部类可以写出简洁明快的代码在实际开发中应用非常广泛。
比如存在一个父类Bird 如果需要创建一个子类重写其move方法对比一下普通类和匿名内部类的区别 显然匿名内部类显得更加简洁方便。匿名内部类简洁地省略类子类类名也因为没有类名造成不能再复用类名创建更多地对象。在使用匿名内部类时候要注意
1、如果只是简洁地继承父类并且只需要创建一个子类对象就采用匿名内部类。
2、如果子类需要反复使用创建一组子类对象就采用普通的子类。
3、匿名内部类一定是子类一定需要有父类型时候才能使用。
4、匿名内部类的最大优点就是语法简洁在一行上继承子类并且创建类了子类对象。