文章目錄
- 一、包
- 1. 概念
- 2. 使用方式
- 3. 靜態匯入
- 4. 創建包
- 5. 包的訪問權限
- 6. 常見的系統包
- 二、繼承
- 1. 概念
- 2. 語法規則(含 super 使用)
- 3. protected 關鍵字
- 4. 更復雜的繼承關系
- 5. final 關鍵字
- 三、組合
- 四、總結(含謎底)
一、包
1. 概念
根據定義:包是組織類的一種方式
那么為什么要組織類呢?
簡單來講就是保證類的唯一性,就比如在以后的作業中,如果大家一起開發一個專案,大家可能在自己的代碼中都寫到了一個 Test 類,而如果出現了兩個同名的類的話,就會沖突,導致代碼不能編譯通過,
用一份代碼理解下
import java.util.*; public class TestDemo{ public static void main(String[] args){ // 得到一個毫秒級的時間戳 Date date=new Date(); } }上面一份代碼,匯入了 util 包,并使用了其中的 Date 類,目的是為了得到一個毫秒級的時間戳,而如果我們再匯入一個 sql 包
import java.sql.*; import java.util.*; public class TestDemo{ public static void main(String[] args){ // 得到一個毫秒級的時間戳 Date date=new Date(); } }上述代碼就會編譯錯誤,會顯示
Reference to 'Date' is ambiguous, both 'java.sql.Date' and 'java.util.Date' match,即兩個包中都有 Date 類,不知道該和哪個匹配,稍微修改下,確定該 Date 是和誰匹配就行,修改方式如java.util.Date date=new java.util.Date();或者修改這里也行
import java.sql.*; import java.util.Date;
2. 使用方式
Java 中已經提供了很多現成的類供我們使用,如上述代碼中的 Date 類,還有我們經常使用的 Scanner 類、Arrays 類等等,
而這些類被放置在各個包中,比如 util 包中就有很多我們常用的類
雖說 Java 有這么多已經包裝好的類供我們使用,但是并不是上面有的我們就可以直接使用,
其中 lang 包中的一些類可以直接使用,如 String、Short、Byte、Float 等等(因為這些類會被自動匯入),寫一個代碼理解下
public class TestDemo{
public static void main(String[] args){
// 輸出 long 的最大值
System.out.println(Long.MAX_VALUE);
}
}
上述代碼是輸出 long 型別的最大值,其中使用了 Long 類的 Max_VALUE 方法,并且不需要手打匯入 lang 包
而其它包使用時都需要手動匯入,并且匯入一般有以下幾種方法
- 方法一(不推薦): 直接在使用時,類前加包名,如
public class TestDemo{ public static void main(String[] args){ // 得到一個毫秒級的時間戳 java.util.Date date=new java.util.Date(); } }這種寫法比較麻煩,不簡潔
- 方法二: 使用 impot 陳述句直接匯入某包中的某個類,如
import java.util.Date; public class TestDemo{ public static void main(String[] args){ // 得到一個毫秒級的時間戳 Date date=new Date(); } }注意:
匯入包時也可以直接使用**通配符 *** ,直接匯入 util 包中的所有,如
import java.util.*;但是這個并不是直接將該包中的所有類全部匯入,而是你用到哪個類就會匯入哪個類,
但是會出現匯入的兩個包都使用通配符,并且兩個包都包含同名類的話,則在使用時就會出現錯誤,如
import java.sql.*; import java.util.*; public class TestDemo{ public static void main(String[] args){ // 得到一個毫秒級的時間戳 Date date=new Date(); } }因此更推薦匯入某個指定的類
- 方法三(下面會講解,不常使用): 靜態匯入
了解到這里我們就會發現,Java 中的 import 和 C++ 中的 #include 差別很大,后者必須使用 #include 來引入其他檔案內容,但是 Java 不需要,
3. 靜態匯入
其實之前講方法那一章就提到過靜態方法,而靜態匯入跟靜態方法一樣,都通過關鍵字 static 修飾,使用 import static 匯入包,
而靜態匯入可以使我們不用寫類名,這在某些時候會更加方便,例如
import static java.util.lang.Math.*;
public class TestDemo{
public static void main(String[] args){
double x=3;
double ans=pow(x,2);
}
}
其實 pow 方法就省略了類名 Math
4. 創建包
既然理解了 Java 中的包,那么我們自己可以創建一個包嗎?因為這樣的話,我們就可以在和別人一起開發的時候,使用同一個類名了!
基本規則:
- 包中的檔案最上方要加上一個 package 陳述句,來指定該代碼在哪個包中
- 包名要和代碼路徑相匹配
- 如果一個類沒有 package 陳述句,則會被放到一個默認的包中
- 包名需要全部小寫,并盡量指定成唯一的名字(一般取名如下)
- 個人專案:pers.發起者名.專案名.模快名
- 團隊專案:pers.團隊名.專案名.模快名
- 公司專案:com.公司名.專案名.模快名
為了方便上述規則的理解,接下來讓我來手動創建一個包吧!
創建及使用步驟:
右鍵 src ,點擊new ,選擇創建一個package
創建包名,包名全部小寫
創建之后我們就可以看到這些,并且包名和代碼的路徑一致
點擊 demo1,創建一個 Java 檔案
大家發現沒,我創建了一個叫 TestDemo 的類,而這個名字在 src 中已經有了,這就是包的作用!并且這個檔案上面有
package pers.dmw.demo1;指定了該代碼的位置使用創建的類
當我們輸入 Test 的時候,它出現了兩個 TestDemo,下面哪個就是我們創建的類,按照我們以上所學的,先匯入包,再使用這個類
完成啦!

5. 包的訪問權限
之前學類時,我們學過 public 和 private,其中被 public 修飾的成員在整個工程都可以使用,而被 private 修飾成員的則只能在自己的類中使用
而都不被這兩者修飾的成員,則可以在這個包的其他類中使用,但是不能在其他包中使用
比如我們個人創建的包中定義兩個類 TestDemo1 和 TestDemo2,而 TestDemo 是其他包中的
其中 TestDemo2 代碼如下
package pers.dmw.demo1;
public class TestDemo2 {
public int a=10;
private int b=20;
int c=30;
}
Testdemo1 代碼如下
package pers.dmw.demo1;
public class TestDemo1 {
public static void main(String[] args) {
TestDemo2 testDemo2=new TestDemo2();
System.out.println(testDemo2.a);
System.out.println(testDemo2.b);
System.out.println(testDemo2.c);
}
}
其中 b 不能列印,因為 b 被 private 修飾,只能在自己的類中使用
TestDemo 代碼如下
package pers.dmw.demo1;
public class TestDemo {
public static void main(String[] args) {
TestDemo2 testDemo2=new TestDemo2();
System.out.println(testDemo2.a);
System.out.println(testDemo2.b);
System.out.println(testDemo2.c);
}
}
其中 b 和 c 都不能列印,b 是被 private 修飾的類,而 c 沒有被修飾,只能在自己的包中使用
6. 常見的系統包
包大概的知識已經介紹完了,最后讓我們來了解下那些常見的系統包吧!
java.lang:系統常用基礎類(String、Object),此包從 JDK1.1 后自動匯入,
java.lang.reflflect:java 反射編程包
java.net:進行網路編程開發包
java.sql:進行資料庫開發的支持包
java.util:是 Java 提供的工具程式包
java.io:I/O 編程開發包
二、繼承
我們知道面向物件的基本特征就是:繼承、封裝、多型
我們已經了解過封裝了,接下來就開始學習繼承
學習繼承之前我們首先回憶一下類與物件,之前我舉了一個洗衣服的例子,不記得的朋友可以去 爆肝1W字只為弄懂類和物件 這章看看
而今天我再用一個謎語更好的幫大家去理解類和物件
謎語:
年紀不大,胡子一把,客人來啦,就喊媽媽(打一動物)
謎底:
誒!?先猜,謎底我已經放到本章的最后了,猜完的小伙伴可以到下面去驗證哈
我們可以發現
- 謎語就是一種抽象
- 謎底就是一個具體
- 類就是一個事物的抽象
- 物件就是一個抽象的具體
回顧了類與物件之后,我們開始學習繼承,那么繼承是什么呢?
1. 概念
其實這里的繼承和我們生活中的繼承很類似,比如誰繼承了長輩的產業,我們也可以用這樣的比喻去寫一個代碼,
首先我們看一幅圖

圖片里有一只羊和一只狼,然后它們都屬于動物對吧,那我們可以根據動物去寫一個類
class Animal{
public String name;
public int age;
public void eat(){
System.out.println("我要睡覺啦!");
}
public void bark(){
System.out.println("我要叫啦!");
}
}
該類中,定義了動物的名字、年齡屬性以及睡覺、叫的行為,我們再繼續對狼和羊定義一個類
狼
class Wolf{
public String name;
public int age;
public void eat(){
System.out.println("我要睡覺啦!");
}
public void bark(){
System.out.println("我要叫啦!");
}
public void hunt(){
System.out.println("我要獵食啦!");
}
}
羊
class Sheep{
public String name;
public int age;
public int cleatNum;
public void eat(){
System.out.println("我要睡覺啦!");
}
public void bark(){
System.out.println("我要叫啦!");
}
}
我們發現,在羊和狼的類的定義時,由于它們都屬于動物,所以動物的一些屬性和行為它們都有,所以我們可以通過繼承,將羊和狼的類的代碼變得更加簡介
狼
class Wolf extends Animal{
public void hunt(){
System.out.println("我要獵食啦!");
}
}
羊
class Sheep extends Animal{
public int cleatNum;
}
如上述代碼中的 A extends B 就是繼承,其中
- A:叫做子類或者派生類
- B:叫做父類、基類或者超類
當子類繼承了父類之后,子類就擁有了父類的方法和屬性
因此繼承的意義就是
為了代碼的重復使用
繼承的思想就是
- 抽取共性,放到基類當中
- extends
2. 語法規則(含 super 使用)
這里我們再更加詳細的介紹繼承的語法規則,以便于解決一些疑惑的地方
語法:
class 子類 extends 父類{
}
規則:
- Java 中一個子類只能繼承一個父類(C++/python 等語言支持多繼承)
- 子類會繼承父類的所有 public 的欄位和方法
- 對于父類的 private 的欄位和方法,子類無法訪問(可以繼承)
- 子類的實體中,也包含著父類的實體,可以使用 super 關鍵字得到父類實體的參考
注意:
由于 Java 當中只能單繼承,為了解決這個問題,后面可以通過介面來實作類似于“多繼承”的關系
那么上述關鍵字 super 是什么意思呢?首先我們看這樣一段代碼
class Animal{
public String name;
public void eat(){
System.out.println(this.name + "要睡覺啦!");
}
public void bark(){
System.out.println(this.name + "要叫啦!");
}
}
class Wolf extends Animal{
public void hunt(){
System.out.println(this.name + "要獵食啦!");
}
}
public class TestDemo{
public static void main(String[] args){
Wolf wolf=new Wolf();
wolf.name="灰太狼";
wolf.eat();
wolf.bark();
wolf.hunt();
}
}
這就是一個簡單的子類繼承父類的使用,
我們知道創建一個物件分為兩步:為物件分配記憶體和呼叫構造類,當我們沒有定義構造方法時,系統會自動為我們構造一個無參的構造方法,
那如果我們在父類中主動的創建一個構造方法
class Animal{
public String name;
public Animal(Stirng name){
this.name=name;
}
public void eat(){
System.out.println(this.name + "要睡覺啦!");
}
public void bark(){
System.out.println(this.name + "要叫啦!");
}
}
那么我們要記住:子類繼承父類,需要先幫父類構造,那么怎么構造呢,就要用到 super
class Wolf extends Animal{
public Wolf(String name){
super(name); // 顯示的呼叫父類的構造方法
}
public void hunt(){
System.out.println(this.name + "我要獵食啦!");
}
}
其中 super 就是呼叫父類的構造方法,這就滿足子類繼承父類之前,要先構造父類的構造方法
再具體理解下 super:
super:表示當前物件的父類的參考(但這個說法不嚴謹,這是和 this 類比的結論)
super():呼叫父類的構造方法
super.父類屬性:呼叫父類的屬性
super.父類方法:呼叫父類的方法
注意:
- 當我們不主動創建構造方法時,但不是也有系統主動創建的構造方法嗎?因為當我們不主動創建時,系統也主動使用了 super
- super 不能和 this 一起使用,因為它們都要放在第一行
- super 不能放在被 static 修飾的方法中使用,因為它依賴于物件
- super 只會指向最直接的父類,不會指向父類的父類
3. protected 關鍵字
我們對之前學的關鍵字 public、private、默認以及即將要學的關鍵字 protected 做一個比較,就可以得到下面的表格
| num | 范圍 | private | 默認(包訪問權限) | protected | public |
|---|---|---|---|---|---|
| 1 | 同一包中的同一類 | ? | ? | ? | ? |
| 2 | 同一包中的不同類 | ? | ? | ? | |
| 3 | 不同包中的子類 | ? | ? | ||
| 4 | 不同包中的非子類 | ? |
我們發現在上述代碼中,我使用的繼承時,父類代碼的屬性都是用 public 修飾的,這樣子類就可以正常使用這些屬性,但是這就違背了“封裝”的思想,但是如果用 private 修飾,不同包的子類又不能訪問
因此出現了一個關鍵字 protected,使用它的話
- 對于不同包的非子類: protected 修飾的欄位和方法是不能訪問的
- 對于不同包的子類和同一包的其他類:protected 修飾的欄位和方法是能訪問的
學到這里,我們可以開始解決之前一些未提及的問題了:如果父類和子類都含有同一個引數,那呼叫時是使用哪個呢?我們來看下面的代碼
class Base{
public int a=1;
}
class Derieve extends Base{
public int a=3;
public void func(){
System.out.println(a);
}
}
public class TestDemo{
public static void main(String[] args){
Derieve derieve=new Derieve();
derieve.func();
}
}
// 結果為:3
也就是說,呼叫時也是依靠了一個就近原則,默認為子類中的,那么呼叫時想呼叫父類該怎么辦呢?這時我們就可以使用 super 來呼叫父類的屬性,將 Derieve 類 改成這樣即可
class Derieve extends Base{
public int a=3;
public void func(){
System.out.println(super.a);
}
}
// 結果為:1
至于方法同名的問題下章將講解!
4. 更復雜的繼承關系
以上的繼承關系都比較簡單,如果關系變得更復雜時,如這個樣子,我們該怎么辦呢?

emmm,其實一般建議是不希望超過三層的繼承關系的,如果繼承層次太多了,就需要考慮重構代碼,
而有時我們不知不覺就寫了很多的繼承關系,所以為了在語法上進行限制繼承,就可以使用關鍵字 final
5. final 關鍵字
之前我們了解過 final,它可以修飾一個變數或者欄位,使其變成常量,不可以被修改,如
final int a=10;
// a 為常量不可以被修改
而在這里,final 也能修飾類,此時被修飾的類就不能被繼承了,被叫做密封類,如
final class A{
}
此時 A 就不能被繼承了
final 也可以修飾方法,被修飾的方法叫做密封方法,至于此時 final 有什么作用,下章將會講解!
三、組合
上述重點講解了繼承相關的內容,而繼承的意義就是:使代碼可以重復使用
而組合也是一種表達類之間關系的方式,也能夠達到代碼重用的效果
顧名思義,組合就是將各種東西組合成一個東西,比如學習,學校就是由老師、學生、教學樓等等組合而成的,我們可以寫一個代碼
class Teacher{
// ...
}
class Student{
// ...
}
public class School{
public Teacher[] teachers;
public Student[] students;
}
上述代碼就是將老師和學生的類封裝成了物件,并且作為了另一個類的欄位
四、總結(含謎底)
今天這章重點講解了包和繼承相關的內容,概念比較多,自己的理解也可能很不到位,所以寫的不好,希望大家可以理解吧!最后來揭曉我們的謎底吧!
我是謎底:
其實我自己在猜的時候一直搞不懂羊為啥叫媽媽,羊不都是 miemie~ 的叫嘛,直到我想到了 giegie~
哈哈哈,艸
nal 有什么作用,下章將會講解!
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/299520.html
標籤:java






