源文件声明规则
1. 一个源文件中只能有一个public
类
在一个Java源文件(.java文件)中,最多只能定义一个public
类。如果你尝试在一个源文件中定义多个public
类,编译器将会报错。这样做的目的是为了使代码结构更加清晰,并方便代码的组织和管理。
示例:
// 文件名:MyClass.java
public class MyClass {
// 类的定义内容
}
class AnotherClass {
// 非public类的定义内容
}
在上述例子中,MyClass
是一个public
类,而AnotherClass
是一个非public
类。MyClass
和AnotherClass
可以共存于一个源文件中,因为只有一个是public
类。
2. 一个源文件可以有多个非public
类
如果类没有使用public
修饰符,那么它就是默认的包访问权限(package-private),可以在同一源文件中定义多个非public
类。
示例:
// 文件名:MyClass.java
public class MyClass {
// 类的定义内容
}
class HelperClass1 {
// 非public类的定义内容
}
class HelperClass2 {
// 非public类的定义内容
}
在这个例子中,HelperClass1
和HelperClass2
都是非public
类,可以与MyClass
共存于同一个源文件中。
3. 源文件的名称应该和public
类的类名保持一致
如果源文件中定义了一个public
类,那么源文件的名称必须与该public
类的类名完全相同(包括大小写)。例如,如果public
类的名称是MyClass
,那么源文件必须命名为MyClass.java
,否则编译器会报错。
示例:
// 文件名:MyClass.java
public class MyClass {
// 类的定义内容
}
如果这个文件命名为AnotherName.java
,编译将失败,因为文件名与public
类名不一致。
4. package
语句、import
语句和类定义的顺序
在一个源文件中,代码的顺序通常为:
1. package
语句(可选):指定类所在的包。
2. import
语句(可选):导入其他包中的类。
3. 类定义:实际定义的类。
示例:
// 文件名:MyClass.java
package com.example.myapp; // package语句
import java.util.List; // import语句
public class MyClass { // 类定义
// 类的定义内容
}
在这个例子中,package
语句指定了类所在的包,import
语句导入了Java标准库中的List
类,然后定义了public
类MyClass
。
类的定义
在Java中,类的定义和访问控制符决定了类中的成员(变量和方法)的可访问范围,以及它们在不同对象和类之间的共享方式。让我们分解这些概念并结合实例说明。
1. 访问控制修饰符
Java提供了四种主要的访问控制修饰符,用于控制类和类成员的访问范围:
public
:任何类都可以访问。private
:只有在本类内部可以访问。protected
:同一个包或子类中可以访问。- 不添加修饰符(包访问权限):在同一个包中可以访问。
在定义类和类成员时,根据实际需求选择合适的访问控制修饰符。
示例代码:
public class Point {
private int x; // 私有成员变量,只能在本类内访问
private int y; // 私有成员变量
public Point(int x, int y) { // 公共构造函数,允许其他类创建Point对象
this.x = x;
this.y = y;
}
public void setX(int x) { // 公共方法,允许其他类修改x值
this.x = x;
}
public void setY(int y) { // 公共方法,允许其他类修改y值
this.y = y;
}
public int getX() { // 公共方法,允许其他类获取x值
return x;
}
public int getY() { // 公共方法,允许其他类获取y值
return y;
}
public String toString() { // 公共方法,返回对象的字符串表示
return String.format("(%d, %d)", x, y);
}
}
在上面的Point
类中,x
和y
变量是private
,只能在Point
类内部访问和修改。setX
、setY
、getX
、getY
、toString
等方法是public
,其他类可以通过这些方法访问或修改x
和y
的值。
2. 静态成员变量与静态方法
- 静态成员变量/方法:用
static
修饰。它们属于类本身,而不是某个具体的对象,因此在类中只有一份,被所有对象共享。 - 普通成员变量/方法:不使用
static
修饰。它们属于类的每个对象实例,每个对象都有自己的独立副本。
示例代码(添加静态变量):
public class Point {
private int x;
private int y;
// 静态变量count,用于统计创建的Point对象个数
private static int count = 0;
public Point(int x, int y) {
this.x = x;
this.y = y;
count++; // 每创建一个对象,count增加1
}
// 静态方法,返回创建的Point对象个数
public static int getCount() {
return count;
}
public void setX(int x) {
this.x = x;
}
public void setY(int y) {
this.y = y;
}
public int getX() {
return x;
}
public int getY() {
return y;
}
public String toString() {
return String.format("(%d, %d)", x, y);
}
}
在此代码中:
- count
是一个static
静态变量,用于统计创建的Point
对象个数。它被所有Point
对象共享,所以无论创建多少个Point
对象,count
在类中只有一份。
- getCount
是一个static
静态方法,可以在没有创建Point
对象的情况下直接调用(例如,Point.getCount()
)。
静态成员和非静态成员的调用规则:
- 静态方法只能访问静态成员变量或调用其他静态方法。无法访问非静态成员变量或调用非静态方法。
- 非静态方法既可以访问静态成员变量和调用静态方法,也可以访问非静态成员变量和调用非静态方法。
说明:
public static int getCount() {
return count; // 静态方法访问静态变量count
}
public void setX(int x) {
this.x = x; // 非静态方法访问非静态变量x
System.out.println("当前创建的Point对象个数: " + getCount()); // 非静态方法调用静态方法
}
总结
- 访问控制符决定了类成员的可见性,确保数据的封装性。
- 静态成员变量和静态方法属于类本身,而非具体对象,适合需要在所有对象间共享的数据或行为。
- 普通成员变量和方法属于具体对象,每个对象都有自己的一份,适合对象特有的属性和行为。
this关键字的用法
在Java中,this
关键字是一个引用,指向当前对象的实例。在类的方法或构造函数中,this
用于引用调用这些方法或构造函数的对象。this
关键字的主要用途包括以下几个方面:
1. 区分成员变量和局部变量
在构造函数或方法中,当方法的参数名称与类的成员变量名称相同,为了区分两者,需要使用this
来明确指定成员变量。
示例:
public class Person {
private String name;
private int age;
public Person(String name, int age) {
// 使用this来区分成员变量和构造函数参数
this.name = name;
this.age = age;
}
}
在上面的代码中,name
和age
参数与类的成员变量同名。使用this.name
和this.age
可以确保我们访问的是类的成员变量,而不是方法参数。
2. 调用当前对象的方法
在类的内部,this
可以用来调用当前对象的其他方法,确保方法调用的是属于当前对象的实例方法。
示例:
public class Calculator {
private int result;
public void add(int value) {
this.result += value;
}
public void displayResult() {
System.out.println("结果: " + this.result);
}
public void calculate() {
this.add(10); // 使用this调用当前对象的add方法
this.displayResult(); // 使用this调用当前对象的displayResult方法
}
}
在这里,this.add(10)
和this.displayResult()
显式地表示调用当前对象的add
和displayResult
方法,但通常可以省略this
,即直接调用add(10)
和displayResult()
。
3. 调用当前类的构造函数
this
可以用于在一个构造函数中调用另一个构造函数。这样可以避免重复代码并简化初始化逻辑。使用这种方式时,this
调用必须放在构造函数的第一行。
示例:
public class Rectangle {
private int width;
private int height;
public Rectangle() {
// 默认构造函数调用另一个带参数的构造函数
this(0, 0);
}
public Rectangle(int width, int height) {
this.width = width;
this.height = height;
}
}
在这个例子中,Rectangle
类的无参构造函数调用了另一个带有width
和height
参数的构造函数,以便简化初始化逻辑。
4. 作为当前对象的引用返回
this
可以用来在方法中返回当前对象的引用,常见的用法是在链式调用中使用。
示例:
public class Chain {
private int value;
public Chain setValue(int value) {
this.value = value;
return this; // 返回当前对象的引用
}
public Chain increment() {
this.value++;
return this; // 返回当前对象的引用
}
public void displayValue() {
System.out.println("Value: " + this.value);
}
}
这样,我们可以进行链式调用,如下:
public class Main {
public static void main(String[] args) {
Chain chain = new Chain();
chain.setValue(5).increment().displayValue(); // 链式调用
}
}
在这个例子中,setValue
和increment
方法返回this
,使得可以连续调用多个方法,即链式调用。
总结
- 区分成员变量和参数:当成员变量和方法参数重名时,
this
用于区分成员变量。 - 调用当前对象的方法:
this
可以在方法中调用同一个对象的其他方法。 - 调用当前类的构造函数:在一个构造函数中调用另一个构造函数,用
this()
,且只能出现在第一行。 - 返回当前对象:在方法中返回
this
,常用于链式调用。
类的继承
在Java中,继承是面向对象编程中的一种重要机制。继承可以让一个类(子类)从另一个类(父类)继承属性和方法,从而实现代码的重用和拓展。Java中的继承是单继承的,也就是说每个类只能继承一个父类。这种单继承结构使得Java的类层次结构更加简单和易于管理。
继承的关键概念
- 单继承:每个类只能继承一个直接父类(使用
extends
关键字),但一个父类可以有多个子类。 super
关键字:在子类中,可以使用super
来引用父类的构造方法或方法和变量。- 方法重写(Override):子类可以重写父类的方法,以实现特定功能。
示例讲解
在这个示例中,我们将定义一个Point
类作为父类,表示二维空间中的点。然后我们通过继承创建一个ColorPoint
子类,表示具有颜色的点。
父类 Point
public class Point {
private int x;
private int y;
public Point(int x, int y) { // 构造函数
this.x = x;
this.y = y;
}
public int getX() { // 获取x坐标
return x;
}
public int getY() { // 获取y坐标
return y;
}
public String toString() { // 返回点的字符串表示
return String.format("(%d, %d)", x, y);
}
}
在这个父类Point
中,我们定义了两个属性x
和y
,表示点的横纵坐标。Point
类有一个构造函数用于初始化坐标值,getX
和getY
方法用于返回坐标值,toString
方法返回点的字符串表示。
子类 ColorPoint
通过继承Point
类,我们可以创建一个带颜色的点——ColorPoint
,它不仅具有Point
类的坐标属性,还增加了一个color
属性来表示颜色。
public class ColorPoint extends Point {
private String color; // 新增的颜色属性
public ColorPoint(int x, int y, String color) {
super(x, y); // 调用父类的构造函数初始化x和y
this.color = color;
}
public void setColor(String color) { // 设置颜色的方法
this.color = color;
}
public String getColor() { // 获取颜色的方法
return color;
}
@Override
public String toString() { // 重写父类的toString方法,包含颜色信息
return String.format("(%d, %d, %s)", super.getX(), super.getY(), this.color);
}
}
在ColorPoint
类中:
- extends Point
:表明ColorPoint
继承自Point
类。
- 调用父类构造方法:在ColorPoint
的构造函数中使用super(x, y);
调用父类Point
的构造函数来初始化x
和y
。
- 新增属性:color
是ColorPoint
类特有的属性,用于表示颜色。
- 重写toString
方法:ColorPoint
重写了Point
类的toString
方法,输出点的坐标和颜色。
使用示例
我们可以创建ColorPoint
对象,并调用它的方法来观察继承的效果。
public class Main {
public static void main(String[] args) {
ColorPoint colorPoint = new ColorPoint(10, 20, "Red");
System.out.println(colorPoint.toString()); // 输出: (10, 20, Red)
colorPoint.setColor("Blue"); // 修改颜色
System.out.println(colorPoint.toString()); // 输出: (10, 20, Blue)
}
}
在这个示例中:
1. 创建了一个ColorPoint
对象colorPoint
,初始化坐标为(10, 20),颜色为Red
。
2. 调用toString()
方法时,输出结果包含了坐标和颜色信息,因为ColorPoint
重写了父类的toString
方法。
3. 使用setColor("Blue")
方法更改颜色,然后再次调用toString()
方法,输出结果中的颜色变为Blue
。
关键点总结
- 继承实现代码复用:
ColorPoint
继承了Point
的坐标属性和方法,使得代码更加简洁。 super
关键字:用于在子类中调用父类的构造函数和方法。在ColorPoint
中使用super(x, y)
调用父类的构造函数来初始化x
和y
。- 方法重写:子类可以重写父类的方法(如
toString
),以便实现不同的行为。 - 单继承结构:每个类只能继承一个父类,但可以通过继承链来拓展功能和属性。
构造方法
在Java中,构造方法和普通方法之间有明确的区分。构造方法的名称与类名相同,并且没有返回类型(包括void
),而普通方法通常有返回类型(如int
、String
等)或void
。
在ColorPoint
的构造函数中使用super(x, y);
时,实际上是调用父类Point
的构造方法,而不是getX
或getY
等普通方法。具体原因如下:
1. super(...)
语法只用于调用父类的构造方法
在Java中,super(...)
这种带参数的调用格式仅用于调用父类的构造方法,并且只能在子类构造函数的第一行使用。因此,super(x, y);
明确表示在调用Point
类的构造函数Point(int x, int y)
,而不是任何其他方法。
如果只是调用父类的普通方法,应该使用super.methodName(...)
的形式,例如super.getX()
或super.getY()
。这样可以确保构造方法和普通方法的调用方式不会混淆。
2. 构造方法没有返回类型,而普通方法有返回类型
在父类Point
中,构造方法Point(int x, int y)
的定义如下:
public Point(int x, int y) {
this.x = x;
this.y = y;
}
构造方法的特点是没有返回类型(即使void
也没有),它只用于创建对象时的初始化。而getX
和getY
是普通方法,有int
作为返回类型,定义如下:
public int getX() {
return x;
}
public int getY() {
return y;
}
由于语法的不同,super(x, y);
不会被识别为调用getX()
或getY()
,因为它们并没有与super(x, y);
语法相匹配的格式。
3. getX
和getY
不是构造方法
getX
和getY
方法的作用是获取x
和y
的值,它们并不负责对象的初始化,而构造方法专门用于对象的创建和初始化。因此,在子类构造函数中调用super(x, y);
时,Java编译器知道这是在调用父类的构造函数,而不是调用getX
或getY
。
实例总结
在ColorPoint
的构造函数中调用super(x, y);
时,Java会去Point
类中寻找匹配的构造方法Point(int x, int y)
。而getX
和getY
方法只是普通方法,它们和构造方法有不同的语法定义与调用方式,因而不会导致混淆。
所以,super(x, y);
只会用于构造函数的调用,且只会调用父类的构造方法。
类的多态
在Java中,多态(Polymorphism)是面向对象编程的一个重要特性,它允许我们通过父类引用来调用子类的重写方法。这种机制使得相同的代码在不同对象上表现出不同的行为,增加了程序的灵活性和可扩展性。
多态的实现方式
Java的多态主要通过方法重写(Method Overriding)实现,即子类重写父类的方法,从而允许在不同的对象中对相同的方法调用产生不同的结果。
多态的特点
- 父类引用指向子类对象:我们可以使用父类的引用来指向子类的对象。
- 调用重写的方法:当父类的引用指向子类对象时,调用的是子类重写的方法,而不是父类的方法。
示例讲解
在这个例子中,我们有一个父类Point
和一个子类ColorPoint
。ColorPoint
继承了Point
,并重写了toString
方法,从而在调用toString
方法时表现出不同的行为。
父类 Point
public class Point {
private int x;
private int y;
public Point(int x, int y) {
this.x = x;
this.y = y;
}
public int getX() {
return x;
}
public int getY() {
return y;
}
public String toString() {
return String.format("(%d, %d)", x, y);
}
}
在Point
类中,toString
方法返回点的坐标,例如(3, 4)
。
子类 ColorPoint
public class ColorPoint extends Point {
private String color;
public ColorPoint(int x, int y, String color) {
super(x, y);
this.color = color;
}
@Override
public String toString() {
return String.format("(%d, %d, %s)", super.getX(), super.getY(), color);
}
}
在ColorPoint
类中,重写了父类的toString
方法,使得返回结果包含颜色信息,例如(1, 2, red)
。
测试类 Main
public class Main {
public static void main(String[] args) {
Point point = new Point(3, 4); // 创建父类对象
Point colorPoint = new ColorPoint(1, 2, "red"); // 父类引用指向子类对象
// 调用toString方法
System.out.println(point.toString()); // 输出: (3, 4)
System.out.println(colorPoint.toString()); // 输出: (1, 2, red)
}
}
在这个例子中:
1. Point point = new Point(3, 4);
:point
是一个Point
类的对象,调用point.toString()
时,返回Point
类的toString
方法输出结果(3, 4)
。
2. Point colorPoint = new ColorPoint(1, 2, "red");
:这里colorPoint
是一个Point
类型的引用,指向了一个ColorPoint
对象。尽管引用类型是Point
,但它实际上指向一个ColorPoint
对象,因此在调用colorPoint.toString()
时,输出结果是(1, 2, red)
,这是ColorPoint
类重写的toString
方法的返回值。
解析多态行为
- 当
colorPoint.toString()
被调用时,Java会根据colorPoint
实际指向的对象类型(即ColorPoint
)来选择调用哪个toString
方法。 - 因此,尽管
colorPoint
的类型是Point
,但由于它指向一个ColorPoint
实例,实际调用的是ColorPoint
类中的toString
方法。这就是多态的表现。
多态的优势
- 代码灵活性:多态允许我们通过父类引用来操作子类对象,使代码更加灵活。
- 可扩展性:如果有新的子类,只需保证重写了父类的方法,现有代码就能处理新的子类对象,无需修改原代码。
总结
- 多态是通过父类引用调用子类的重写方法实现的。
- 子类重写了父类方法后,即使通过父类的引用,调用的仍是子类重写的方法。
- 多态使得相同的方法调用可以在不同的对象上表现出不同的行为,提升了代码的灵活性和可扩展性。
接口
在Java中,接口(interface
)是一种特殊的类型,用于定义类中必须实现的功能。接口和类类似,但接口仅仅定义方法的规范,即方法的名称和参数,并不包含方法的实现。类可以通过实现(implements
)接口来具体化接口中的方法。
接口的主要特点
- 接口用于定义规范:接口定义了类必须实现的行为,但不包含具体的实现。
- 多重实现:一个类可以实现多个接口,以实现多重继承的效果。
- 接口继承:接口可以继承其他接口,从而定义更多的规范。
示例:定义接口
7.2.1 接口的定义
定义接口时使用interface
关键字。在接口中定义的方法默认是public
且不包含具体实现,接口中的属性(常量)默认是public static final
。
例如,定义一个Role
接口:
public interface Role {
void greet(); // 方法没有实现
void move(); // 方法没有实现
int getSpeed(); // 方法没有实现
}
在这个Role
接口中:
- greet
、move
和getSpeed
都是接口中的方法声明,定义了方法的名称和参数,但没有实现。
- 接口中的方法默认是public
的,即便不加修饰符,仍然具有public
的访问权限。
实现接口
一个类可以通过implements
关键字实现一个或多个接口。在实现接口时,类必须提供接口中所有方法的具体实现。
示例:实现Role
接口
假设我们有一个Player
类,它需要具备Role
接口中的功能,即需要实现greet
、move
和getSpeed
方法。
public class Player implements Role {
private int speed;
private String name;
public Player(String name, int speed) {
this.name = name;
this.speed = speed;
}
@Override
public void greet() {
System.out.println("Hello, I'm " + name);
}
@Override
public void move() {
System.out.println(name + " is moving at speed " + speed);
}
@Override
public int getSpeed() {
return speed;
}
}
在Player
类中:
- implements Role
:表示Player
类实现了Role
接口,必须提供Role
接口中所有方法的实现。
- greet
、move
和getSpeed
方法分别提供了Role
接口中方法的实现内容。
接口的多重实现
Java中,一个类只能继承一个父类,但可以实现多个接口,这就是接口的多重实现特性。
示例:多重实现
假设我们有一个新的接口Runnable
,定义了一个run
方法:
public interface Runnable {
void run();
}
现在,我们可以让Player
类实现Role
和Runnable
接口,从而实现两个接口的功能:
public class Player implements Role, Runnable {
private int speed;
private String name;
public Player(String name, int speed) {
this.name = name;
this.speed = speed;
}
@Override
public void greet() {
System.out.println("Hello, I'm " + name);
}
@Override
public void move() {
System.out.println(name + " is moving at speed " + speed);
}
@Override
public int getSpeed() {
return speed;
}
@Override
public void run() {
System.out.println(name + " is running");
}
}
在这里,Player
类同时实现了Role
和Runnable
接口,必须实现这两个接口中的所有方法。
接口的继承
接口可以继承其他接口,从而定义出更多的规范。继承接口时,子接口继承父接口的方法声明,可以在子接口中增加新的方法声明。
示例:接口继承
public interface SuperRole extends Role {
void attack();
}
SuperRole
接口继承了Role
接口,因此任何实现SuperRole
的类也必须实现Role
接口中的方法和SuperRole
接口中的新方法。
实现SuperRole
接口
public class Warrior implements SuperRole {
private int speed;
public Warrior(int speed) {
this.speed = speed;
}
@Override
public void greet() {
System.out.println("I am a Warrior");
}
@Override
public void move() {
System.out.println("Warrior is moving at speed " + speed);
}
@Override
public int getSpeed() {
return speed;
}
@Override
public void attack() {
System.out.println("Warrior is attacking!");
}
}
在这个例子中,Warrior
类实现了SuperRole
接口,必须实现Role
和SuperRole
中的所有方法。
总结
- 接口定义:接口定义了类中必须实现的方法,不包含实现代码。
- 接口的实现:类使用
implements
关键字来实现接口,必须实现接口中所有的方法。 - 多重实现:类可以实现多个接口,从而具备多个接口的功能。
- 接口继承:接口可以继承其他接口,从而扩展规范。
在Java中,接口的继承和实现使得代码结构更具灵活性,并且可以实现多态性。让我们分解一下接口的继承、实现和多态的用法,并结合实例详细讲解。
接口的继承
Java允许一个接口继承多个其他接口,从而扩展新的功能。接口继承与类的继承不同,接口可以继承多个父接口,因为接口仅包含方法的声明,不包含实现,因此不会引起“钻石问题”。
示例:接口的继承
public interface Role {
void greet();
void move();
int getSpeed();
}
public interface Hero extends Role {
void attack(); // Hero接口扩展了Role接口,增加了attack方法
}
在这个例子中:
- Hero
接口继承了Role
接口,意味着任何实现Hero
接口的类都必须实现Role
和Hero
中的所有方法。
- Hero
接口在继承Role
接口的基础上增加了attack
方法。
接口的实现
Java中的类可以实现多个接口,从而获得多种功能。在实现接口时,类必须提供接口中所有方法的具体实现。
示例:实现接口
我们定义一个实现了Hero
接口的类Zeus
:
public class Zeus implements Hero {
private final String name = "Zeus";
@Override
public void attack() {
System.out.println(name + ": Attack!");
}
@Override
public void greet() {
System.out.println(name + ": Hi!");
}
@Override
public void move() {
System.out.println(name + ": Move!");
}
@Override
public int getSpeed() {
return 10;
}
}
在这里:
- Zeus
类实现了Hero
接口,因此必须实现Role
接口中的greet
、move
、getSpeed
方法,以及Hero
接口中的attack
方法。
- 每个方法在Zeus
类中都有具体的实现,例如attack
方法打印"Zeus: Attack!"
。
接口的多态
接口的多态性允许我们通过接口引用来调用不同实现类的实现。这种多态性可以让我们编写更通用的代码。我们可以创建多个不同的实现类,并用接口类型的变量来引用它们。这样在运行时,可以根据不同的对象调用不同的实现。
示例:多态
我们再创建一个Hero
接口的实现类Athena
,并在Main
类中演示接口的多态性:
public class Athena implements Hero {
private final String name = "Athena";
@Override
public void attack() {
System.out.println(name + ": Attack!!!");
}
@Override
public void greet() {
System.out.println(name + ": Hi!!!");
}
@Override
public void move() {
System.out.println(name + ": Move!!!");
}
@Override
public int getSpeed() {
return 10;
}
}
在这个例子中,Athena
类同样实现了Hero
接口,但提供了与Zeus
不同的实现,特别是方法输出内容有所不同。
多态性演示:Main
类
public class Main {
public static void main(String[] args) {
Hero[] heroes = {new Zeus(), new Athena()}; // 使用Hero类型数组存放不同实现类的对象
for (Hero hero : heroes) {
hero.greet(); // 多态调用,依次调用Zeus和Athena的greet方法
}
}
}
在Main
类中:
- 我们创建了一个Hero
类型的数组heroes
,存放了Zeus
和Athena
两个不同的对象。
- 使用for
循环遍历数组,通过hero.greet()
调用Hero
接口中的greet
方法。由于多态性,实际调用的是每个具体对象(即Zeus
或Athena
)的greet
实现。
- 运行结果将是不同的,因为Zeus
和Athena
各自提供了不同的greet
实现。
运行结果示例
执行Main
类时的输出:
Zeus: Hi!
Athena: Hi!!!
关键点总结
- 接口继承:接口可以继承多个接口,从而扩展方法声明。
- 接口实现:类可以实现一个或多个接口,必须提供接口中所有方法的具体实现。
- 接口多态:接口类型的变量可以引用实现该接口的不同对象,在运行时动态调用具体实现类的方法。
实例来源于y总讲义类与接口