Java:面对对象
This commit is contained in:
parent
40c1ce9229
commit
66ca768836
665
docs/开发/Java/面对对象.md
Normal file
665
docs/开发/Java/面对对象.md
Normal file
@ -0,0 +1,665 @@
|
|||||||
|
---
|
||||||
|
id: 面对对象
|
||||||
|
title: 面对对象
|
||||||
|
sidebar_position: 4
|
||||||
|
data: 2022年4月27日
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
在 Java 中,**万事万物都是对象**。 Java 也是面对对象的高级编程语言,面对对象语言具有如下特征
|
||||||
|
|
||||||
|
- 面对对象是一种常见的思想,比较符合人们的思考习惯;
|
||||||
|
- 面对对象可以将复杂的业务逻辑简单化,增强代码复用性;
|
||||||
|
- 面对对象具有抽象、封装、继承、多态等特性;
|
||||||
|
|
||||||
|
## 类
|
||||||
|
|
||||||
|
类——相当于是一系列对象的抽象。具体就比如自动车一样,车的长、宽、高是车的**数据**;车的骑行,喇叭是车的**方法**。
|
||||||
|
|
||||||
|
### 定义
|
||||||
|
|
||||||
|
```java
|
||||||
|
class ClassName{
|
||||||
|
// body
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### 创建
|
||||||
|
|
||||||
|
```java
|
||||||
|
ClassName classname = new ClassName();
|
||||||
|
```
|
||||||
|
|
||||||
|
### 构造
|
||||||
|
|
||||||
|
在 Java 类中,通过构造方法在对象**创建时期调用一次**来确保每个对象都被**初始化**。构造方法比较特殊,没有参数类型和返回值,构造方法名称务必和类名保持一致,并且一个类可以拥有多个构造方法。
|
||||||
|
|
||||||
|
```java
|
||||||
|
class Apple {
|
||||||
|
int sum;
|
||||||
|
String color;
|
||||||
|
|
||||||
|
public Apple(){}
|
||||||
|
public Apple(int sum){}
|
||||||
|
public Apple(String color){}
|
||||||
|
public Apple(int sum,String color){}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// 创建对象
|
||||||
|
class createApple {
|
||||||
|
public static void main(String[] args) {
|
||||||
|
Apple apple1 = new Apple();
|
||||||
|
Apple apple2 = new Apple(1);
|
||||||
|
Apple apple3 = new Apple("red");
|
||||||
|
Apple apple4 = new Apple(2,"color");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
如果类中没有定义任何构造方法,那么 JVM 会自动生成一个默认构造方法。
|
||||||
|
|
||||||
|
## 面对对象
|
||||||
|
|
||||||
|
### 封装
|
||||||
|
|
||||||
|
封装(英语:Encapsulation)是指一种将抽象性函式接口的实现细节部份包装、隐藏起来的方法。封装可以被认为是一个保护屏障,防止该类的代码和数据被外部类定义的代码随机访问。要访问该类的代码和数据,必须通过严格的接口控制。
|
||||||
|
|
||||||
|
#### 数据
|
||||||
|
|
||||||
|
数据也可以被称为属性,数据可以是任意类型的对象,也可以是基本数据类型。
|
||||||
|
|
||||||
|
```java
|
||||||
|
Class A{
|
||||||
|
int a;
|
||||||
|
Apple apple;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 方法
|
||||||
|
|
||||||
|
方法(函数)通过封装多行代码的实现,用来**简化代码**、**利于维护**、**重复调用**、**模块化编程**和**提高开发效率**。
|
||||||
|
|
||||||
|
```java
|
||||||
|
修饰符 返回值类型 方法名(参数类型 参数名){
|
||||||
|
...
|
||||||
|
方法体
|
||||||
|
...
|
||||||
|
return 返回值;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
- **修饰符:**定义方法的访问类型。
|
||||||
|
- **返回值类型 :**定义方法返回值类型。如果方法没有返回值,返回值类型是关键字 **void**。
|
||||||
|
- **函数名:**调用方法的实际访问名称。
|
||||||
|
- **参数类型:**方法调用时,限定传递参数类型。
|
||||||
|
- **参数名:**方法调用时,传递的实际参数。方法定义时,限定的形式参数。
|
||||||
|
- **方法体:**定义方法的功能
|
||||||
|
|
||||||
|
#### 权限
|
||||||
|
|
||||||
|
![访问权限](https://static.7wate.com/img/2022/04/27/46262496c680a.png)
|
||||||
|
|
||||||
|
#### 实例
|
||||||
|
|
||||||
|
```java
|
||||||
|
public class EncapTest{
|
||||||
|
|
||||||
|
private String name;
|
||||||
|
private String idNum;
|
||||||
|
private int age;
|
||||||
|
|
||||||
|
public int getAge(){
|
||||||
|
return age;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getName(){
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getIdNum(){
|
||||||
|
return idNum;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAge( int newAge){
|
||||||
|
age = newAge;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setName(String newName){
|
||||||
|
name = newName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setIdNum( String newId){
|
||||||
|
idNum = newId;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### 继承
|
||||||
|
|
||||||
|
继承就是子类继承父类的特征和行为,使得子类对象(实例)具有父类的实例域和方法,或子类从父类继承方法,使得子类具有父类相同的行为。从而减少重复代码,提高维护性,代码也更佳简洁,提高代码的复用性。
|
||||||
|
|
||||||
|
![继承图示例](https://static.7wate.com/img/2022/04/27/4439d9883fb7a.jpg)
|
||||||
|
|
||||||
|
#### 类型
|
||||||
|
|
||||||
|
Java 不支持多继承,但支持多重继承。
|
||||||
|
|
||||||
|
![继承类型](https://static.7wate.com/img/2022/04/27/75c38968a30e6.png)
|
||||||
|
|
||||||
|
#### 特性
|
||||||
|
|
||||||
|
- 子类拥有父类非 private 的属性、方法。
|
||||||
|
- 子类可以拥有自己的属性和方法,即子类可以对父类进行扩展。
|
||||||
|
- 子类可以用自己的方式实现父类的方法。
|
||||||
|
- Java 的继承是单继承,但是可以多重继承,单继承就是一个子类只能继承一个父类,多重继承就是,例如 A 类继承 B 类,B 类继承 C 类,所以按照关系就是 C 类是 B 类的父类,B 类是 A 类的父类,这是 Java 继承区别于 C++ 继承的一个特性。
|
||||||
|
- 提高了类之间的耦合性(继承的缺点,耦合度高就会造成代码之间的联系越紧密,代码独立性越差)。
|
||||||
|
|
||||||
|
#### 关键字
|
||||||
|
|
||||||
|
- **extends:**类的继承是单一继承,一个子类只能拥有一个父类。
|
||||||
|
- **implements:**变相的使 java 具有多继承的特性,使用范围为类继承接口的情况,可以同时继承多个接口(接口跟接口之间采用逗号分隔)。
|
||||||
|
- **super:**通过 super 关键字来实现对父类成员的访问,用来引用当前对象的父类。
|
||||||
|
- **this:**指向自己的引用。
|
||||||
|
- **final:**类定义为不能继承的,即最终类;或者用于修饰方法,该方法不能被子类重写。
|
||||||
|
|
||||||
|
#### 实例
|
||||||
|
|
||||||
|
```java
|
||||||
|
class 父类 {
|
||||||
|
}
|
||||||
|
|
||||||
|
class 子类 extends 父类 {
|
||||||
|
}
|
||||||
|
|
||||||
|
// 单一继承
|
||||||
|
|
||||||
|
public class Animal {
|
||||||
|
private String name;
|
||||||
|
private int id;
|
||||||
|
|
||||||
|
public Animal(String myName, String myid) {
|
||||||
|
//初始化属性值
|
||||||
|
}
|
||||||
|
public void eat() { //吃东西方法的具体实现 }
|
||||||
|
public void sleep() { //睡觉方法的具体实现 }
|
||||||
|
}
|
||||||
|
|
||||||
|
public class Penguin extends Animal{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// 继承多个接口
|
||||||
|
|
||||||
|
public interface A {
|
||||||
|
public void eat();
|
||||||
|
public void sleep();
|
||||||
|
}
|
||||||
|
|
||||||
|
public interface B {
|
||||||
|
public void show();
|
||||||
|
}
|
||||||
|
|
||||||
|
public class C implements A,B {
|
||||||
|
}
|
||||||
|
|
||||||
|
// super 与 this 关键字
|
||||||
|
|
||||||
|
class Animal {
|
||||||
|
void eat() {
|
||||||
|
System.out.println("animal : eat");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class Dog extends Animal {
|
||||||
|
|
||||||
|
void eat() {
|
||||||
|
System.out.println("dog : eat");
|
||||||
|
}
|
||||||
|
|
||||||
|
void eatTest() {
|
||||||
|
this.eat(); // this 调用自己的方法
|
||||||
|
super.eat(); // super 调用父类方法
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class Test {
|
||||||
|
public static void main(String[] args) {
|
||||||
|
Animal a = new Animal();
|
||||||
|
a.eat();
|
||||||
|
Dog d = new Dog();
|
||||||
|
d.eatTest();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// final 关键字
|
||||||
|
|
||||||
|
final class 类名 { /*方法体*/ }
|
||||||
|
|
||||||
|
[public / private / default / protected] final 返回值类型 方法名(){ /*方法体*/ }
|
||||||
|
```
|
||||||
|
|
||||||
|
### 重写与重载
|
||||||
|
|
||||||
|
#### 重写
|
||||||
|
|
||||||
|
重写与重载虽然名字相似,但却是完全不同的东西。方法重写的描述是对**子类和父类**之间的。
|
||||||
|
|
||||||
|
- 子类中重写的方法必须与父类保持一致,包括返回值类型、方法名、参数列表。
|
||||||
|
- 子类中重写的方法可以使用 @Override 注解来标识。
|
||||||
|
- 子类中重写方法的访问权限不能低于父类中方法的访问权限。
|
||||||
|
|
||||||
|
```java
|
||||||
|
class Fruit {
|
||||||
|
|
||||||
|
public void eat(){
|
||||||
|
System.out.printl('eat fruit');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class Apple extends Fruit{
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void eat(){
|
||||||
|
System.out.printl('eat apple');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 重载
|
||||||
|
|
||||||
|
相同的方法名拥有独一无二的参数列表,其中包括参数的类型、顺序、数量等构成了方法重载的必要条件。
|
||||||
|
|
||||||
|
- **方法名称必须相同。**
|
||||||
|
- **参数列表必须不相同(类型、顺序、数量不同等)。**
|
||||||
|
- 返回类型不同不构成方法重载。
|
||||||
|
- 重载是在编译时,具体由编译器确定使用那个方法。
|
||||||
|
|
||||||
|
**即外壳不变,核心重写!**
|
||||||
|
|
||||||
|
```java
|
||||||
|
public class Apple {
|
||||||
|
int sum;
|
||||||
|
String color;
|
||||||
|
|
||||||
|
public Apple(){}
|
||||||
|
public Apple(int sum){}
|
||||||
|
|
||||||
|
public int getApple(int num){
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getApple(String color){
|
||||||
|
return "color";
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 重写与重载的区别
|
||||||
|
|
||||||
|
| 区别点 | 重载方法 | 重写方法 |
|
||||||
|
| :------: | :------: | :--------------------------------------------: |
|
||||||
|
| 参数列表 | 必须修改 | 一定不能修改 |
|
||||||
|
| 返回类型 | 可以修改 | 一定不能修改 |
|
||||||
|
| 异常 | 可以修改 | 可以减少或删除,一定不能抛出新的或者更广的异常 |
|
||||||
|
| 访问 | 可以修改 | 一定不能做更严格的限制(可以降低限制) |
|
||||||
|
|
||||||
|
方法的重写(Overriding)和重载(Overloading)是 java 多态性的不同表现,重写是父类与子类之间多态性的一种表现,重载可以理解成多态的具体表现形式。
|
||||||
|
|
||||||
|
1. 方法重写是在子类存在方法与父类的方法的名字相同,而且参数的个数与类型一样,返回值也一样的方法,就称为重写(Overriding)。
|
||||||
|
2. 方法重载是一个类中定义了多个方法名相同,而他们的参数的数量不同或数量相同而类型和次序不同,则称为方法的重载(Overloading)。
|
||||||
|
3. 方法重载是一个类的多态性表现,而方法重写是子类与父类的一种多态性表现。
|
||||||
|
|
||||||
|
![区别图例](https://static.7wate.com/img/2022/04/27/4fdd076693397.png)
|
||||||
|
|
||||||
|
### 多态
|
||||||
|
|
||||||
|
多态是同一个行为具有多个不同表现形式或形态的能力。
|
||||||
|
|
||||||
|
多态就是同一个接口,使用不同的实例而执行不同操作,如图所示:
|
||||||
|
|
||||||
|
![多态图例](https://static.7wate.com/img/2022/04/27/ac5f133d3c528.png)
|
||||||
|
|
||||||
|
#### 优点
|
||||||
|
|
||||||
|
- 消除类型之间的耦合关系
|
||||||
|
- 可替换性
|
||||||
|
- 可扩充性
|
||||||
|
- 接口性
|
||||||
|
- 灵活性
|
||||||
|
- 简化性
|
||||||
|
|
||||||
|
#### 多态存在的三个必要条件
|
||||||
|
|
||||||
|
- 继承
|
||||||
|
- 重写
|
||||||
|
- 父类引用指向子类对象
|
||||||
|
|
||||||
|
#### 多态的实现方式
|
||||||
|
|
||||||
|
- 重写
|
||||||
|
|
||||||
|
- 接口
|
||||||
|
|
||||||
|
- 抽象类和抽象方法
|
||||||
|
|
||||||
|
## 抽象
|
||||||
|
|
||||||
|
在面向对象的概念中,所有的对象都是通过类来描绘的,但是反过来,并不是所有的类都是用来描绘对象的,如果一个类中没有包含足够的信息来描绘一个具体的对象,这样的类就是抽象类。
|
||||||
|
|
||||||
|
由于抽象类不能实例化对象,所以抽象类必须被继承,才能被使用。也是因为这个原因,通常在设计阶段决定要不要设计抽象类。
|
||||||
|
|
||||||
|
父类包含了子类集合的常见的方法,但是由于父类本身是抽象的,所以不能使用这些方法。在 Java 中抽象类表示的是一种继承关系,一个类只能继承一个抽象类,而一个类却可以实现多个接口。
|
||||||
|
|
||||||
|
- 抽象类不能被实例化(初学者很容易犯的错),如果被实例化,就会报错,编译无法通过。只有抽象类的非抽象子类可以创建对象。
|
||||||
|
- 抽象类中不一定包含抽象方法,但是有抽象方法的类必定是抽象类。
|
||||||
|
- 抽象类中的抽象方法只是声明,不包含方法体,就是不给出方法的具体实现也就是方法的具体功能。
|
||||||
|
- 构造方法,类方法(用 static 修饰的方法)不能声明为抽象方法。
|
||||||
|
- 抽象类的子类必须给出抽象类中的抽象方法的具体实现,除非该子类也是抽象类。
|
||||||
|
|
||||||
|
### 类
|
||||||
|
|
||||||
|
```java
|
||||||
|
// 抽象类
|
||||||
|
public abstract class Employee {
|
||||||
|
private String name;
|
||||||
|
private String address;
|
||||||
|
private int number;
|
||||||
|
|
||||||
|
public Employee(String name, String address, int number) {
|
||||||
|
System.out.println("Constructing an Employee");
|
||||||
|
this.name = name;
|
||||||
|
this.address = address;
|
||||||
|
this.number = number;
|
||||||
|
}
|
||||||
|
|
||||||
|
public double computePay() {
|
||||||
|
System.out.println("Inside Employee computePay");
|
||||||
|
return 0.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void mailCheck() {
|
||||||
|
System.out.println("Mailing a check to " + this.name
|
||||||
|
+ " " + this.address);
|
||||||
|
}
|
||||||
|
|
||||||
|
public String toString() {
|
||||||
|
return name + " " + address + " " + number;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getAddress() {
|
||||||
|
return address;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAddress(String newAddress) {
|
||||||
|
address = newAddress;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getNumber() {
|
||||||
|
return number;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 继承抽象类
|
||||||
|
|
||||||
|
public class Salary extends Employee {
|
||||||
|
private double salary; //Annual salary
|
||||||
|
|
||||||
|
public Salary(String name, String address, int number, double salary) {
|
||||||
|
super(name, address, number);
|
||||||
|
setSalary(salary);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void mailCheck() {
|
||||||
|
System.out.println("Within mailCheck of Salary class ");
|
||||||
|
System.out.println("Mailing check to " + getName()
|
||||||
|
+ " with salary " + salary);
|
||||||
|
}
|
||||||
|
|
||||||
|
public double getSalary() {
|
||||||
|
return salary;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSalary(double newSalary) {
|
||||||
|
if(newSalary >= 0.0) {
|
||||||
|
salary = newSalary;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public double computePay() {
|
||||||
|
System.out.println("Computing salary pay for " + getName());
|
||||||
|
return salary/52;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 实例化 Salary 对象
|
||||||
|
|
||||||
|
public class AbstractDemo {
|
||||||
|
public static void main(String [] args) {
|
||||||
|
Salary s = new Salary("Mohd Mohtashim", "Ambehta, UP", 3, 3600.00);
|
||||||
|
Employee e = new Salary("John Adams", "Boston, MA", 2, 2400.00);
|
||||||
|
|
||||||
|
System.out.println("Call mailCheck using Salary reference --");
|
||||||
|
s.mailCheck();
|
||||||
|
|
||||||
|
System.out.println("\n Call mailCheck using Employee reference--");
|
||||||
|
e.mailCheck();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### 方法
|
||||||
|
|
||||||
|
如果你想设计这样一个类,该类包含一个特别的成员方法,该方法的具体实现由它的子类确定,那么你可以在父类中声明该方法为抽象方法。同时抽象方法必须遵守如下约定:
|
||||||
|
|
||||||
|
- 如果一个类包含抽象方法,那么该类必须是抽象类。
|
||||||
|
- 任何子类必须重写父类的抽象方法,或者声明自身为抽象类。
|
||||||
|
|
||||||
|
```java
|
||||||
|
// 抽象方法
|
||||||
|
public abstract class Employee {
|
||||||
|
private String name;
|
||||||
|
private String address;
|
||||||
|
private int number;
|
||||||
|
|
||||||
|
/*
|
||||||
|
Abstract 关键字同样可以用来声明抽象方法,抽象方法只包含一个方法名,而没有方法体。
|
||||||
|
抽象方法没有定义,方法名后面直接跟一个分号,而不是花括号。
|
||||||
|
*/
|
||||||
|
|
||||||
|
public abstract double computePay();
|
||||||
|
//其余代码
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## 接口
|
||||||
|
|
||||||
|
接口(英文:Interface),在JAVA编程语言中是一个抽象类型,是抽象方法的集合,接口通常以interface来声明。一个类通过继承接口的方式,从而来继承接口的抽象方法。
|
||||||
|
|
||||||
|
接口并不是类,编写接口的方式和类很相似,但是它们属于不同的概念。类描述对象的属性和方法。接口则包含类要实现的方法。
|
||||||
|
|
||||||
|
接口无法被实例化,但是可以被实现。一个实现接口的类,必须实现接口内所描述的所有方法,否则就必须声明为抽象类。
|
||||||
|
|
||||||
|
### 特性
|
||||||
|
|
||||||
|
- 接口中每一个方法也是隐式抽象的,接口中的方法会被隐式的指定为 **public abstract**(只能是 public abstract,其他修饰符都会报错)。
|
||||||
|
- 接口中可以含有变量,但是接口中的变量会被隐式的指定为 **public static final** 变量(并且只能是 public,用 private 修饰会报编译错误)。
|
||||||
|
- 接口中的方法是不能在接口中实现的,只能由实现接口的类来实现接口中的方法。
|
||||||
|
|
||||||
|
**接口与类相同点**
|
||||||
|
|
||||||
|
- 一个接口可以有多个方法。
|
||||||
|
- 接口文件保存在 .java 结尾的文件中,文件名使用接口名。
|
||||||
|
- 接口的字节码文件保存在 .class 结尾的文件中。
|
||||||
|
- 接口相应的字节码文件必须在与包名称相匹配的目录结构中。
|
||||||
|
|
||||||
|
**接口与类不同点**
|
||||||
|
|
||||||
|
- 接口不能用于实例化对象。
|
||||||
|
- 接口没有构造方法。
|
||||||
|
- 接口中所有的方法必须是抽象方法。
|
||||||
|
- 接口不能包含成员变量,除了 static 和 final 变量。
|
||||||
|
- 接口不是被类继承了,而是要被类实现。
|
||||||
|
- 接口支持多继承。
|
||||||
|
|
||||||
|
### 实例
|
||||||
|
|
||||||
|
```java
|
||||||
|
// 接口声明
|
||||||
|
[可见度] interface 接口名称 [extends 其他的接口名] {
|
||||||
|
// 声明变量
|
||||||
|
// 抽象方法
|
||||||
|
}
|
||||||
|
|
||||||
|
// 接口定义
|
||||||
|
interface Animal {
|
||||||
|
public void eat();
|
||||||
|
public void travel();
|
||||||
|
}
|
||||||
|
|
||||||
|
// 接口实现
|
||||||
|
...implements 接口名称[, 其他接口名称, 其他接口名称..., ...] ...
|
||||||
|
|
||||||
|
// 继承实例
|
||||||
|
public class MammalInt implements Animal{
|
||||||
|
|
||||||
|
public void eat(){
|
||||||
|
System.out.println("Mammal eats");
|
||||||
|
}
|
||||||
|
|
||||||
|
public void travel(){
|
||||||
|
System.out.println("Mammal travels");
|
||||||
|
}
|
||||||
|
|
||||||
|
public int noOfLegs(){
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void main(String args[]){
|
||||||
|
MammalInt m = new MammalInt();
|
||||||
|
m.eat();
|
||||||
|
m.travel();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
重写接口中声明的方法时,需要注意以下规则:
|
||||||
|
|
||||||
|
- 类在实现接口的方法时,不能抛出强制性异常,只能在接口中,或者继承接口的抽象类中抛出该强制性异常。
|
||||||
|
- 类在重写方法时要保持一致的方法名,并且应该保持相同或者相兼容的返回值类型。
|
||||||
|
- 如果实现接口的类是抽象类,那么就没必要实现该接口的方法。
|
||||||
|
|
||||||
|
在实现接口的时候,也要注意一些规则:
|
||||||
|
|
||||||
|
- 一个类可以同时实现多个接口。
|
||||||
|
- 一个类只能继承一个类,但是能实现多个接口。
|
||||||
|
- 一个接口能继承另一个接口,这和类之间的继承比较相似。
|
||||||
|
|
||||||
|
### 多继承
|
||||||
|
|
||||||
|
在Java中,类的多继承是不合法,但接口允许多继承。
|
||||||
|
|
||||||
|
在接口的多继承中extends关键字只需要使用一次,在其后跟着继承接口。 如下所示:
|
||||||
|
|
||||||
|
```java
|
||||||
|
public interface Hockey extends Sports, Event
|
||||||
|
```
|
||||||
|
|
||||||
|
## 包
|
||||||
|
|
||||||
|
为了更好地组织类,Java 提供了包机制,用于区别类名的命名空间。
|
||||||
|
|
||||||
|
一个包(package)可以定义为一组相互联系的类型(类、接口、枚举和注释),为这些类型提供访问保护和命名空间管理的功能。
|
||||||
|
|
||||||
|
- **package:**定义包
|
||||||
|
|
||||||
|
```java
|
||||||
|
package pkg1[.pkg2[.pkg3…]];
|
||||||
|
|
||||||
|
// 定义
|
||||||
|
// 路径是 net/java/util/Something.java
|
||||||
|
package net.java.util;
|
||||||
|
public class Something{
|
||||||
|
...
|
||||||
|
}
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
- **import:**导入包
|
||||||
|
|
||||||
|
```java
|
||||||
|
import package1[.package2…].(classname|*);
|
||||||
|
|
||||||
|
// 定义
|
||||||
|
package payroll;
|
||||||
|
|
||||||
|
public class Boss {
|
||||||
|
public void payEmployee(Employee e) {
|
||||||
|
e.mailCheck();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// 通配符
|
||||||
|
import payroll.*;
|
||||||
|
|
||||||
|
// 引入 Employee 类
|
||||||
|
import payroll.Employee
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
### 作用
|
||||||
|
|
||||||
|
1. 把功能相似或相关的类或接口组织在同一个包中,方便类的查找和使用。
|
||||||
|
|
||||||
|
2. 如同文件夹一样,包也采用了树形目录的存储方式。同一个包中的类名字是不同的,不同的包中的类的名字是可以相同的,当同时调用两个不同包中相同类名的类时,应该加上包名加以区别。因此,包可以避免名字冲突。
|
||||||
|
|
||||||
|
3. 包也限定了访问权限,拥有包访问权限的类才能访问某个包中的类。
|
||||||
|
|
||||||
|
Java 使用包(package)这种机制是为了防止命名冲突,访问控制,提供搜索和定位类(class)、接口、枚举(enumerations)和注释(annotation)等。
|
||||||
|
|
||||||
|
### 实例
|
||||||
|
|
||||||
|
```java
|
||||||
|
// 在 animals 包中加入一个接口(interface)
|
||||||
|
|
||||||
|
/* 文件名: Animal.java */
|
||||||
|
package animals;
|
||||||
|
|
||||||
|
interface Animal {
|
||||||
|
public void eat();
|
||||||
|
public void travel();
|
||||||
|
}
|
||||||
|
|
||||||
|
package animals;
|
||||||
|
|
||||||
|
/* 文件名 : MammalInt.java */
|
||||||
|
public class MammalInt implements Animal{
|
||||||
|
|
||||||
|
public void eat(){
|
||||||
|
System.out.println("Mammal eats");
|
||||||
|
}
|
||||||
|
|
||||||
|
public void travel(){
|
||||||
|
System.out.println("Mammal travels");
|
||||||
|
}
|
||||||
|
|
||||||
|
public int noOfLegs(){
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void main(String args[]){
|
||||||
|
MammalInt m = new MammalInt();
|
||||||
|
m.eat();
|
||||||
|
m.travel();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
Loading…
Reference in New Issue
Block a user