概覽
- 1. 包
- 1.1 匯入包中的類
- 1.2 靜態匯入
- 1.3 將類放到包中
- 1.4 包的訪問權限控制
- 1.5 常見的系統包
- 2. 繼承
- 2.1 語法規則
- 2.2 protected關鍵字
- 2.3 final關鍵字
- 3. 組合
- 4.多型
- 4.1 向上轉型
- 4.2 動態系結
- 4.3 方法重寫
- 4.4 向下轉型
- 4.5 super和this關鍵字
- 5. 抽象類
- 5.1 抽象方法
- 5.2 抽象類
- 5.2.1 語法規則
- 5.2.2 抽象類的作用
- 6. 介面
- 6.1 語法規則
- 6.2 Comparable介面
- 6.3 Clonable介面
- 6.4 抽象類和介面的區別
1. 包
- 包 (package) 是組織類的一種方式,
- 使用包的主要目的是保證類的唯一性,
1.1 匯入包中的類
java中提供了很多現成的類供我們使用
public class Test {
public static void main(String[] args) {
java.util.Date date = new java.util.Date();
// 得到一個毫秒級別的時間戳
System.out.println(date.getTime());
}
}
這種方式寫法比較麻煩一些,可以使用import陳述句導包
import java.util.Date;
public class Test {
public static void main(String[] args) {
Date date = new Date();
// 得到一個毫秒級別的時間戳
System.out.println(date.getTime());
}
}
如果需要使用java.util中的其他類,可以使用 import java.util.*,但有的情況下更建議顯示的指定要匯入的類名,負責容易出現沖突的狀況
import java.util.*;
import java.sql.*;
public class Test {
public static void main(String[] args) {
// util 和 sql 中都存在一個 Date 這樣的類, 此時就會出現歧義, 編譯出錯
Date date = new Date();
System.out.println(date.getTime());
}
}
// 編譯出錯
Error:(5, 9) java: 對Date的參考不明確
java.sql 中的類 java.sql.Date 和 java.util 中的類 java.util.Date 都匹配
在這種情況下使用完整的類名:
import java.util.*;
import java.sql.*;
public class Test {
public static void main(String[] args) {
java.util.Date date = new java.util.Date();
System.out.println(date.getTime());
}
}
注意:
- import 和 C++ 的 #include 差別很大,C++ 必須 #include 來引入其他檔案內容, 但是 Java 不需要,
import 只是為了寫代碼的時候更方便, import 更類似C++的namespace和using, - java.long包下的內容不需要匯入,編譯器會自動匯入,
1.2 靜態匯入
使用 import static 可以匯入包中的靜態的方法和欄位,
例如:
import static java.lang.System.*;
import static java.lang.Math.*;
public class Test {
public static void main(String[] args) {
out.println("hello");
double x = 30;
double y = 40;
//靜態匯入的方式更方便一些
// double result = Math.sqrt(pow(x, 2) + Math.pow(y, 2));
double result = sqrt(pow(x, 2) + pow(y, 2));
System.out.println(result);
}
}
1.3 將類放到包中
基本規則:
- idea中在src上右鍵->新建->Packeg ,包名需要盡量指定成唯一的名字,通常會使用公司的域名的顛倒形式,
- 包名與代碼路徑相匹配,在檔案最上方加上package陳述句指定該代碼在哪個包中,
- 如果一個類中沒有package陳述句,則該類被放到一個默認包中,
1.4 包的訪問權限控制
如下圖所示:

- private:類內部可以訪問,類外不能訪問
- 默認(也叫包訪問權限):類內部能訪問,同一個包中的類可以訪問,其他類不能訪問
- protected:類內部能訪問,子類和同一包中的類可以訪問,其他類不能訪問
- public:類內部和類的呼叫者都能訪問
1.5 常見的系統包
- java.lang:系統常用基礎類(String、Object),此包從JDK1.1后自動匯入,
- java.lang.reflect:java 反射編程包;
- java.net : 進行網路編程開發包,
- java.sql:進行資料庫開發的支持包,
- java.util:是java提供的工具程式包,(集合類等) 非常重要
- java.io:I/O編程開發包
2. 繼承
程式層面上:表達繼承的關系使用extends
意義:
- 減少代碼量,代碼復用
- 降低了代碼冗余
2.1 語法規則
基本語法:
class 子類 extends 父類 {}
派生類 基類
超類
- 使用 extends 指定父類,
- java中只支持單繼承
- 子類繼承了父類除構造方法以外所有的東西
- 一般來說不會超過三層的繼承關系
注意:
如果父類寫有有參的構造方法,則子類要顯示的呼叫super()來幫助父類來構造,并且呼叫super()必須放在第一行
代碼示例:
class Animal {
public String name;
public Animal(String name) {
this.name = name;
}
public void eat(String food) {
System.out.println(this.name + "正在吃" + food);
}
}
class Cat extends Animal {
public Cat(String name) {
// 使用 super 呼叫父類的構造方法.
// super表示對父類的參考
super(name);
}
}
class Bird extends Animal {
public Bird(String name) {
super(name);
}
public void fly() {
System.out.println(this.name + "正在飛 ︿( ̄︶ ̄)︿");
}
}
public class Test {
public static void main(String[] args) {
Cat cat = new Cat("小黑");
cat.eat("貓糧");
Bird bird = new Bird("圓圓");
bird.fly();
}
}
如果將父類屬性由public改為private,那么子類將不能訪問
2.2 protected關鍵字
- 對于類的呼叫者來說, protected 修飾的欄位和方法是不能訪問的,
- 對于類的子類和同一個包的其他類來說, protected 修飾的欄位和方法是可以訪問的,
- 同一包中的同一類、同一包中的不同類、不同包中的子類可以訪問,
2.3 final關鍵字
- 在final修飾一個變數或者欄位的時候,表示常量(不能修改),
- final關鍵字也能修飾類,此時表示被修飾的類就不能被繼承,
代碼示例:
final public class Animal {
...
}
public class Bird extends Animal {
...
}
// 編譯出錯
Error:(3, 27) java: 無法從最終com.wx.Animal進行繼承
那么由此可見,final關鍵字的功能是限制類被繼承,用final修飾的類被繼承的時候就會編譯報錯,平時用的String類就是final修飾的不能被繼承,
3. 組合
和繼承類似,組合也是一種表達類之間關系的方式,
代碼示例:
public class Student {
...
}
public class Teacher {
...
}
public class School {
public Student[] students;
public Teacher[] teachers;
}
組合并沒有涉及到extends,僅僅是將一個類的實體作為另外一個類的欄位,這是設計類的常用方式之一,
- 組合通常表示 has-a 語意
- 繼承通常表示 is-a 語意
4.多型
父類參考子類物件,通過父類參考來呼叫子類中重寫的方法,此時就會發生動態系結,也叫做多型,
4.1 向上轉型
將派生類的值賦值給基類,即父類參考參考子類物件
向上轉型的表現形式:
- 直接賦值
在上面的例子中:
Bird bird = new Bird("圓圓");
代碼也可以寫成這樣子:
Animal bird = new Bird("圓圓");
此時bird是一個父類的參考,指向一個子類(Bird)的實體,這種寫法稱為向上轉型
- 方法傳參
public class Test {
public static void main(String[] args) {
Bird bird = new Bird("圓圓");
feed(bird);//傳遞bird 使用Animal來接收
}
public static void feed(Animal animal) {
animal.eat("谷子");
}
}
// 執行結果
圓圓正在吃谷子
- 方法回傳:
public class Test {
public static void main(String[] args) {
Animal animal = findMyAnimal(); //使用Animal來接收bird
}
public static Animal findMyAnimal() {
Bird bird = new Bird("圓圓");
return bird;
}
}
4.2 動態系結
運行時多型,編譯時呼叫父類方法,運行時呼叫的是子類重寫的方法
- 父類參考,參考子類的物件
- 通過父類的參考,呼叫子類和父類重寫的那個方法
注意:
- 當父類參考子類物件的時候,只能訪問自己特有的,訪問不到子類,
- 通過參考可以呼叫方法,重點看參考型別
4.3 方法重寫
子類實作父類的同名方法,并且引數的型別和個數完全相同,這種情況稱為覆寫/重寫/覆寫(Override)
注意:
- 重寫和多載完全不一樣,不要混淆
- 普通方法可以重寫, static 修飾的靜態方法不能重寫
- 重寫中子類的方法的訪問權限不能低于父類的方法訪問權限
- 重寫的方法回傳值型別不一定和父類的方法相同(但是建議最好寫成相同, 特殊情況除外)
- 針對重寫的方法,可以使用@Override來顯示指定
多載和重寫的區別:

小結:
-
多載:在同一個類中
- 方法名相同
- 引數串列不同
- 回傳值不做要求
-
重寫:
- 方法名相同
- 引數串列 相同(引數個數、引數的型別)
- 回傳值也要相同
注意:
- 需要重寫的方法,不能是private修飾的
- 被final所修飾的方法,不能被重寫
- 需要重寫方法的,對于訪問修飾限定符,子類的訪問修飾限定符一定要大于或等于父類的訪問修飾限定符
- static修飾的靜態方法不能重寫
4.4 向下轉型
向上轉型是子類物件轉成父類物件,向下轉型就是父類物件轉成子類物件,相比于向上轉型來說,向下轉型沒那么常見,但是也有一定的用途,
- 父類物件賦值給子類參考
- 在使用之前使用instanceof 可以判定一個參考是否是某個類的實體. 如果是, 則回傳true,此時可以進行向下轉型
4.5 super和this關鍵字
- super:表示獲取到父類實體的參考
- this:表示獲取當前物件的參考
super和this的區別:

5. 抽象類
- 抽象類存在的意義就是為了被繼承
- 抽象類也可以發生向上轉型及多型
5.1 抽象方法
被abstract所修飾的方法,沒有具體的實作
5.2 抽象類
5.2.1 語法規則
abstract class Shape {
abstract public void draw();
}
5.2.2 抽象類的作用
包含抽象方法的類稱為抽象類
注意:
- 抽象類是不可以被實體化的,
- 抽象類中可以有成員方法和成員變數,比普通類多了抽象方法
- 如果一個普通類繼承了一個抽象類,那么這個普通類一定要重寫抽象類中的抽象方法
- 抽象方法一定要重寫,不能用private,final修飾
- 抽象類繼承抽象類不需要重寫抽象類的方法,如果有其他類繼承了這個抽象類,那么一定要重寫這個抽象方法
- 抽象類也可以發生向上轉型和動態系結
6. 介面
介面是抽象類的更進一步,抽象類中還可以包含非抽象方法和欄位,而介面方法中包含的方法都是抽象方法,欄位只能包含靜態常量,
6.1 語法規則
interface IShape {
void draw(); //抽象方法
}
- 使用interface定義一個介面
- 一個類只能繼承一個父類,但是可以實作多個介面
- 所有的方法默認是public abstract
- 所有的成員變數一定是public static final的
- 介面也不可以實體化
- 類和介面的關系:implements,可以實作多個介面,每個介面之間使用逗號隔開
- 介面也可以進行向上轉型,多型
- 介面之間可以繼承
JDK1.8新特性:
- 如果介面中的方法被default修飾,則這個方法可以有具體實作,
6.2 Comparable介面
對自定義型別進行排序,需要實作Comparable介面,對compareTo方法進行重寫
java中提供了關于物件的比較,有以下方式:
-
equals:所有類都具備的能力
理解:比較兩個物件代表的是不是一個實際事物,需要通過重寫equals方法才能達到 -
大小的比較
- 自然順序 Comparable compareTo( ) ,不是所有類都具備,需要通過實作Comparable介面來表明該類具備這個能力
- 外部比較 ( 比較器) Comparator,構造一個天平,不需要比較的類具備Comparable的能力
- 理解:比較傳入的兩個參考指向的物件
代碼示例1:實作Comparable介面
class Teacher implements Comparable<Teacher>{
public String name;
public int age;
public int height;
public int weight;
public Teacher(String name, int age, int height, int weight) {
this.name = name;
this.age = age;
this.height = height;
this.weight = weight;
}
@Override
public String toString() {
return "Teacher{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
//按照age進行比較
@Override
public int compareTo(Teacher o) {
return this.age-o.age;
}
}
public class ComparableTestDemo {
public static void main(String[] args) {
Teacher[] teachers = new Teacher[3];
teachers[0] = new Teacher("li",12,180,80);
teachers[1] = new Teacher("li1",15,175,67);
teachers[2] = new Teacher("li2",3,167,90);
System.out.println(teachers[0]+" "+teachers[1]+" "+teachers[2]);
Arrays.sort(teachers);
System.out.println(teachers[0]+" "+teachers[1]+" "+teachers[2]);
}
}
//運行結果:
Teacher{name='li', age=12} Teacher{name='li1', age=15} Teacher{name='li2', age=3}
Teacher{name='li2', age=3} Teacher{name='li', age=12} Teacher{name='li1', age=15}
代碼示例2:實作Comparator介面、外部比較器
class ByHeigthComparator implements Comparator<Teacher>{
@Override
public int compare(Teacher o1, Teacher o2) {
return o1.height-o2.height;
}
}
class ByWeightComparator implements Comparator<Teacher>{
@Override
public int compare(Teacher o1, Teacher o2) {
return o1.weight-o2.weight;
}
}
public class ComparatorDemo {
public static void main(String[] args) {
Teacher[] teachers = new Teacher[3];
teachers[0] = new Teacher("li",12,180,80);
teachers[1] = new Teacher("li1",15,175,67);
teachers[2] = new Teacher("li2",3,167,90);
Comparator<Teacher> byHeight = new ByHeigthComparator();
Comparator<Teacher> byweight = new ByWeightComparator();
System.out.println(teachers[0].compareTo(teachers[1]));
System.out.println(byHeight.compare(teachers[0],teachers[1]));
System.out.println(byweight.compare(teachers[0],teachers[1]));
}
}
//運行結果:
-3
5
13
6.3 Clonable介面
Object 類中存在一個 clone 方法, 呼叫這個方法可以創建一個物件的 “拷貝”,但是要想合法呼叫 clone 方法, 必須要先實作 Clonable 介面, 否則就會拋出 CloneNotSupportedException 例外,
- 空介面:標記介面,標記當前類是可以克隆的,
- 實作Clonable介面,并且重寫clone方法
代碼示例:
Person類:
class Money implements Cloneable{
public double money;
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
}
public class Person implements Cloneable{
public String name;
public Money m ;//類中有參考型別,需要將參考型別也進行拷貝
public Person(String name) {
this.name = name;
this.m =new Money();
}
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
'}';
}
@Override
protected Object clone() throws CloneNotSupportedException {
Person person = (Person)super.clone();
person.m = (Money)this.m.clone(); //需要將 m也進行克隆
return person;
}
}
Demo類:
public class Demo {
public static void main(String[] args) throws CloneNotSupportedException {
Person person1 = new Person("name");
person1.m.money = 12.5;
Person person2 = (Person) person1.clone();
System.out.println(person2);
person1.name = "lisi";
System.out.println(person2);
System.out.println(person1.m.money);
System.out.println(person2.m.money);
person1.m.money = 18;
System.out.println(person1.m.money);
System.out.println(person2.m.money);
}
}
運行結果:
12.5
12.5
18
12.5
6.4 抽象類和介面的區別
核心區別:
- 抽象類中可以包含普通方法和普通欄位, 這樣的普通方法和欄位可以被子類直接使用(不必重寫), 而介面中不能包含普通方法, 子類必須重寫所有的抽象方法,
圖示:

轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/290253.html
標籤:java
