一、緒論
主要參考
-
視頻教程尚硅谷Java入門視頻教程(在線答疑+Java面試真題)_嗶哩嗶哩_bilibili
-
檔案教程C語言中文網:C語言程式設計門戶網站(入門教程、編程軟體) (biancheng.net)
-
書籍《JAVA學習筆記》
-
《JAVA核心技術卷1》
1.問題匯總
Q:JAVA和C++有什么區別
A:
解答1:
(18條訊息) c++與java的應用區別_藍黑墨水的博客-CSDN博客_c++和java區別
解答2:
Java和C/C++到底有什么關系?它們有什么區別? (biancheng.net)
發展歷程:C -> C++ -> Java ,Java 是由 C++發展而來的,保留了 C++ 的大部分內容,其編程方式類似于 C++,但 Java 的句法更清晰、規模更小、更易學,Sun 公司曾對多種程式設計語言進行分析研究,取其精華去其糟粕,最終推出了 Java,Java 從根本上解決了 C++ 的固有缺陷,形成了新一代面向物件的程式設計語言,
解答3:
C/C++和Java確實不太一樣,C語言和C++,尤其是C++,語言密度更細,機制多,性能雖然高,但是就語言本身來說,包獄太重,所以也就稱之為“造輪子”的語言,但是也正是因為他性能好,密度細,所以什么都能做,而Java本身是服務于互聯網軟體開發(后端開發、客戶端開發)的語言,他有一個明顯的生態圈的概念,所以應用領域非常清晰,因為Java是純應用層的,所以相對而言學習C++更加困難一些,對于程式員能力的要求要更高一些,C/C++的主場在系統底層;(PS:現在JAVA也很少用來做瀏覽器客戶端的互動了,取代applet(使用JAVA撰寫的應用程式)的是JS和Flash等腳本語言;當然不管是C++還是JAVA都別用來寫前端界面!!!)
解答4:(基于作者學過的一些語言對比)
后端邏輯使用JAVA或者Node.js(JS本身是做前端邏輯的,但是node.js是可以寫后端的,但應該沒多少人會這么瘋狂)做都可以,C/C++更適合做底層系統相關的東西,python因為簡單輕量有很多現成完善的庫可以直接呼叫(自己寫小工具也很方便)

解答5:
(19條訊息) c面向物件 java_c++面向物件和java面向物件的區別?_weixin_39584571的博客-CSDN博客
Q:為什么要學JAVA?
A:因為我想知道有關軟體開發和桌面應用等知識點,我學JAVA并不是需要會用這門語言,而是需要知道這門語言和我學習中會接觸到的大量知識盲區的關系,所以學習程序中不要特別在于語法條件之類的,著重看重JAVA特性和用途;
Q:為什么JAVA的專案名和什么型別這么麻煩?一旦不對應似乎整個程式都會崩潰????
A:因為JAVA是一門非常嚴謹的語言,任何規則都必須遵守(有句話很有意思“C++更加靈活,JAVA更加嚴謹”),正是因為其語法的嚴謹特性,所以還有一句話是“C++動不動就崩潰,JAVA想寫崩潰都難”;
2.JAVA概述
按應用范圍,Java 可分為 3 個體系,即 Java SE、Java EE 和 Java ME
- JAVA SE:Java SE(Java Platform Standard Edition,
Java 平臺標準版)以前稱為 J2SE,它允許開發和部署在桌面、服務器、嵌入式環境和實時環境中使用的 Java 應用程式,Java SE 包含了支持 Java Web 服務開發的類,并為 Java EE 提供基礎,如 Java 語言基礎、JDBC 操作、I/O 操作、網路通信以及多執行緒等技術,適合開發桌面級應用如QQ、微信; - JAVA EE:Java EE(Java Platform Enterprise Edition,
Java 平臺企業版)以前稱為 J2EE,企業版本幫助開發和部署可移植、健壯、可伸縮且安全的服務器端 Java 應用程式,Java EE 是在 Java SE 基礎上構建的,它提供 Web 服務、組件模型、管理和通信 API,可以用來實作企業級的面向服務體系結構(Service Oriented Architecture,SOA)和 Web 2.0 應用程式,適合Web應用程式開發; - Java ME(Java Platform Micro Edition,
Java 平臺微型版)以前稱為 J2ME,也叫 K-JAVA, Java ME 為在移動設備和嵌入式設備(比如手機、PDA、電視機頂盒和列印機)上運行的應用程式提供一個健壯且靈活的環境,Java ME 包括靈活的用戶界面、健壯的安全模型、豐富的內置網路協議以及對可以動態下載的聯網和離線應用程式,基于 Java ME 規范的應用程式 只需撰寫一次就可以用于許多設備,而且可以利用每個設備的本機功能,適合開發移動端的應用程式;
JAVA主要有以下特性:
- 簡單性:JAVA是C++的“純凈版本”
- 面向物件
- 網路技能:JAVA可以讓socket通信等變得非常簡單
- 健壯性:JAVA采用的指標模型可以消除重寫記憶體和損壞資料的可能性
- 安全性:JAVA的網路環境絕對安全
- 體系結構中立:JAVA編譯器生成與作業系統無關的位元組碼實作
- 可移植性:JAVA的基本資料型別大小是固定的,不依賴具體實作
- 解釋型
- 高性能
- 多執行緒:JAVA實作多執行緒非常簡單
- 動態性:C#與JAVA在這方面類似,可以自由在庫中增加方法和實體變數
3.核心機制
3.1 JAVA虛擬機
JVM是一個虛擬的計算機,具有指令集并使用不同的存盤區域,負責執行指令,管理資料、記憶體、暫存器,對于不同的平臺,有不同的虛擬機,只有某平臺提供了對應的java虛擬機,java程式才可在此平臺運行,

Java虛擬機機制屏蔽了底層運行平臺的差別,實作了“一次編譯,到處運行”;
3.2 垃圾回識訓制
C/C++中需要程式員手動釋放無用記憶體;
Java 語言消除了程式員回收無用記憶體空間的責任:它提供一種系統級執行緒跟蹤存盤空間的分配情況,并在JVM空閑時,檢查并釋放那些可被釋放的存盤空間,垃圾回收在Java程式運行程序中自動進行,程式員無法精確控制和干預;
盡管JAVA擁有自動垃圾回識訓制,但是有時候我們寫的程式可能存在問題仍將導致自動回識訓制無法識別垃圾進而造成記憶體泄漏(某些物件申請記憶體沒有被釋放,一直占用)和記憶體溢位(程式所需的記憶體大于系統所能提供的最大記憶體);
4.JAVA環境
JDK(Java Development Kit Java開發工具包)JDK是提供給Java開發人員使用的,其中包含了java的開發工具,也包括了JRE,所以安裝了JDK,就不用在單獨安裝JRE了,
-
開發工具包括編譯工具(javac.exe)打包工具(jar.exe)等(
開發工具用于撰寫代碼); -
JRE(Java Runtime Environment Java 運行環境)包括
Java虛擬機(JVM Java Virtual Machine)和Java 程式所需的核心類別庫等,如果想要運行一個開發好的Java程式,計算機中只需要安裝JRE即可(JRE用于運行Java程式);

(非常幸運的是在之前安裝爬蟲appinum的時候安裝Andriod SDK時順便就安裝了JDK環境,所以我們省略了安裝JDK的步驟,教程參考(18條訊息) JDK下載與安裝教程_墨笙弘一的博客-CSDN博客_jdk安裝教程)
PS:按照網上的JDK安裝教程并沒有配置安裝JRM所以可能目錄環境和B站老師講的不太一樣,先將就用著,期間有什么問題做記錄寫下來記錄即可
-
報錯解決:(18條訊息) 關于解決 錯誤: 找不到或無法加載主類 原因: java.lang.ClassNotFoundException 的方法_是我,Zack的博客-CSDN博客
-
Eclipse安裝:(19條訊息) eclipse官網下載超時解決方法_一起來見證奇跡啊的博客-CSDN博客
-
Eclipse漢化:(19條訊息) eclipse漢化教程(官方漢化包,傻瓜式操作,附帶中英文快捷切換方式)_Zeromes的博客-CSDN博客_eclipse漢化
5.JAVA標準格式
我們這里給出一個基本的JAVA程式的模板,并簡單解釋下相關的引數,在之后還會詳細介紹
public class HelloJava {
public static void main(String[] args){
System.out.println(""!我的第一個 Java程式!");
}
}
- JAVA程式中可以有多個類,但只能有一個public類,且主檔案名必須與這個公開類的的名稱相同;
- main()是JAVA程式的入口,程式的執行從入口開始,main()一定是public成員這樣它才可以在執行環境中被呼叫,同時main()必須是個static成員這樣它才能在不產生物件的情況下被執行;
- 括號中的String[] args可以在執行程式時取得使用者指定的命令列引數,盡管現在用不著但仍然要書寫;
- 每一條陳述句的結束要用分號;
- println()輸出的字串后自動換行,print()輸出字串后程式并不會自動換行;
JAVA中main()方法是應用程式的入口方法,main()方法與其他方法存在很大差別:
- 訪問控制權限是公有的(public),
- main() 方法是靜態的,如果要在 main() 方法中呼叫本類中的其他方法,則該方法也必須是靜態的,否則需要先創建本類的實體物件,然后再通過物件呼叫成員方法,
- main() 方法沒有回傳值,只能使用 void,
- main() 方法具有一個字串陣列引數,用來接收執行 Java 程式的命令列引數,命令列引數作為字串,按照順序依次對應字串陣列中的元素,
- 字串中陣列的名字(代碼中的 args)可以任意設定,但是根據習慣,這個字串陣列的名字一般和 Java 規范范例中 main() 引數名保持一致,命名為 args,而方法中的其他內容都是固定不變的,
- main() 方法定義必須是“public static void main(String[] 字串陣列引數名)”,即main()方法的格式必須固定不變,
- 一個類只能有一個 main() 方法,這是一個常用于對類進行單元測驗(對軟體中的最小可測驗單元進行檢查和驗證)的技巧,
二、JAVA基礎
1.JAVA注釋
- 單行注釋
//注釋文字
- 多行注釋
/*注釋文字*/
- 檔案注釋(JAVA特有)
/**
@author 指定 java 程式的作者 **
@version 指定源檔案的版本 **
*/
檔案注釋的內容可以被JDK提供的工具javadoc決議(包、公有類和介面、公有的和受保護的方法、公有的和受保護的域)生成一套以網頁檔案形式體現該程式的說明檔案
javadoc -d 檔案夾名 -author -version 檔案名
檔案注釋一般用在類、方法和變數上面,用來描述其作用,注釋后,滑鼠放在類和變數上面會自動顯示出我們注釋的內容
關于JAVA檔案注釋的更多訊息可以參考Javadoc(檔案注釋)詳解 (biancheng.net)也可以參考《JAVA技術卷1》P137、Java注釋:類、方法和欄位注釋 (biancheng.net)
2.JAVA運行流程
Java程式的運行程序(執行流程)分析 (biancheng.net)

JAVA中的所有東西都會屬于某個類,我們寫的源檔案經過編譯后會得到類檔案(.class,存盤的位元組碼),被VM執行的實際是類 - 執行程式就表示命令JVM加載HelloJava這個類并開始執行它的main(),直到main的所有程式代碼結束為止;
3.JAVA常量
常量是指在程式的整個運行程序中值保持不變的量,
注意:常量和常量值是不同的概念,常量值是常量的具體和直觀的表現形式,常量是形式化的表現,通常在程式中既可以直接使用常量值,也可以使用常量
3.1 常量值
3.1 常量值
常量值又稱字面常量,通過資料直接表示,可分為:
- 整型常量值:整型(int)常量默認在記憶體中占 32 位,是具有整數型別的值,當運算程序中所需值超過 32 位長度時,可以把它表示為長整型(long)數值,長整型型別則要在數字后面加 L 或 1, 如 697L,表示一個長整型數,它在記憶體中占 64 位
- 實型常量值:Java 實型常量默認在記憶體中占 64 位,是具有雙精度型(double)的值,如果考慮到需要節省運行時的系統資源,而運算時的資料值取值范圍并不大且運算精度要求不太高的情況,可以把它表示為單精度型(float)的數值,單精度型數值一般要在該常數后面加 F 或 f,如 69.7f,表示一個 float 型實數,它在記憶體中占 32 位
- 布爾型常量:false true
- 字符型/字串常量:Java 字串常量值中的單引號和雙引號不可混用,單引號表示字符型常量,雙引號表示字串常量;
3.2 常量
JAVA中的常量名一般使用大寫
- 宣告常量
final dataType variableName = value
final 是定義常量的關鍵字(實際上JAVA也有const關鍵字但沒使用),dataType 指明常量的資料型別,variableName 是常量的名稱,value 是初始值
常量分為:
- 靜態全域常量
public static final double PI = 3.14;
在 final 之前 public static 修飾,public static 修飾的常量作用域是全域的,不需要創建物件就可以訪問它
- 成員常量
- 區域常量
3.3 final修飾符
final 應用于類、方法和變數時意義是不同的,但本質是一樣的,都表示不可改變;
使用 final 關鍵字宣告類、變數和方法需要注意以下幾點:
- final 用在變數的前面表示變數的值不可以改變(不是不可以賦值,而是不可以改變!!!),此時該變數可以被稱為
常量;- 當使用 final 修飾基本型別變數時,不能對基本型別變數重新賦值,因此基本型別變數不能被改變;
- 對于參考型別變數而言,它保存的僅僅是一個參考,final 只保證這個參考型別變數所參考的地址不會改變,即一直參考同一個物件,但這個物件完全可以發生改變(使用 final 修飾的參考型別變數不能被重新賦值,但可以改變參考型別變數所參考物件的內容);
- final 用在方法的前面表示方法
不可以被重寫(子類中如果創建了一個與父類中相同名稱、相同回傳值型別、相同引數串列的方法,只是方法體中的實作不同,以實作不同于父類的功能,這種方式被稱為方法重寫,又稱為方法覆寫,重寫不等于多載); - final 用在類的前面表示該類不能有子類,即該類
不可以被繼承;
4.JAVA變數
JAVA中的每一個變數都屬于一種型別,宣告變數時一定要宣告變數所屬型別;
4.1 變數
- 宣告變數
DataType identifier;//每個宣告以分號結束(因為宣告是一條完整的陳述句)
DataType identifier=value;//宣告變數的同時初始化變數
- DataType:變數型別,如 int、string、 char 和 double 等;
- identifier:識別符號,也叫變數名稱;
- value:宣告變數時的值;
C/C++中int i=10是定義一個變數,extern int i是宣告一個變數,但是JAVA中并不區分變數的宣告和定義;
4.2 變數作用域
變數根據作用域的不同可以分為:
- 成員變數:定義在方法體和陳述句塊之外,不屬于任何一個方法,作用域是整個類(我們在后面也叫它域)
- 全域變數(實體變數)
- 靜態變數(類變數)
- 區域變數:在方法或者方法代碼塊中定義的變數,其作用域是其所在的代碼塊
- 方法引數變數(形參):在整個方法內有效
- 方法區域變數(方法內定義的變數):從定義這個變數開始到方法結束這一段時間內有效
- 代碼塊區域變數(代碼塊內定義的變數):從定義這個變數開始到代碼塊結束這一段時間內有效(比如for回圈中的回圈計數器i)
成員變數和區域變數的主要不同點就在于,必須明確的初始化區域變數才能使用,而成員變數假如沒有初始化則自動初始化為默認值(0、false、null)
JAVA面向物件的概念中并不存在全域變數的概念;
5.JAVA資料型別
資料型別是指編譯器存盤在變數中的數值應當具有適當的資料型別,JAVA是一種強資料型別的語言,必須為每一個變數宣告一種型別,JAVA資料型別分為基本資料型別和參考資料型別

5.1 基本資料型別
- JAVA沒有任何無符號型別;
- 浮點型別用于表示有小數部分的數值,千萬不要將浮點型別用在金融計算中(這將引發騷亂);
- 'A'是編碼為65對應的字符常量,"A"是包含A的字串,建議不要在程式中使用char型別(JAVA的Unicode字符集比較特殊);
- JAVA中的布爾型和整型不能相互轉換,C++中數值或指標可以代替布林值;

5.2 參考資料型別
參考資料型別建立在基本資料型別的基礎上,包括陣列、類和介面,參考資料型別是由用戶自定義,用來限制其他資料的型別(這一點其實非常類似C++的復合資料型別),另外,Java 語言中不支持C++中的指標型別、結構型別、聯合型別(型別別、列舉型別),
6.JAVA流程控制
程式設計主要有三種流程結構:順序結構、選擇結構和回圈結構,系統默認是自上而下以順序結構執行;
6.1 JAVA陳述句
Java 中,陳述句是最小的組成單位,每個陳述句必須使用分號作為結束符
按照陳述句的組成部分,可將JAVA中的陳述句分為如下三類
6.1.1 空陳述句
;
空陳述句就是一個分號,在程式中什么也不做,主要用于做慷訓圈體;
6.1.2 運算式陳述句
pi = 3.1415926;
output(pi); // 將pi的值傳遞到output()函式中作為引數
sum = (a+b)/2;
printf("%f",sum); // 將sum的值傳遞到printf()函式輸出
temp = x*y*z-y+(20-x); // 將運算式的值保存到temp變數中
一般運算式陳述句應該能完成一個操作,如修改變數的值或者作為函式引數等
6.1.3 復合陳述句
{
statement-list // 陳述句串列
}
復合陳述句(代碼塊/陳述句塊)是很多陳述句的組合,將一個代碼塊/陳述句塊看作一個陳述句;
6.2 選擇結構
選擇結構(也叫分支結構)解決了順序結構不能判斷的缺點,可以根據一個條件判斷執行哪些陳述句塊;
JAVA支持兩種選擇陳述句(使用選擇陳述句實作選擇結構):if 陳述句和 switch 陳述句,這些陳述句允許只有在程式運行時才能知道其狀態的情況下,控制程式的執行程序
- if 陳述句使用布爾運算式或布林值作為分支條件來進行分支控制;
- switch 陳述句則用于對多個整型值進行匹配,從而實作分支控制;
6.3 回圈結構
回圈陳述句能夠使程式代碼重復執行,適用于需要重復一段代碼直到滿足特定條件為止的情況;
JAVA中采用的回圈陳述句與C語言中的回圈陳述句相似,主要有 while、do-while 和 for、for-each 回圈陳述句,for-each 回圈是 for 回圈的變形,它是專門為集合遍歷而設計的;
6.3.1 for-each陳述句
- 格式
for(型別 變數名:集合) {
陳述句塊;
}
- 舉例
// 宣告并初始化陣列
int[] numbers = { 43, 32, 53, 54, 75, 7, 10 };
System.out.println("----for----");
// for陳述句
for (int i = 0; i < numbers.length; i++) {
System.out.println("Count is:" + numbers[i]);
}
// 宣告并初始化int陣列
int[] numbers = { 43, 32, 53, 54, 75, 7, 10 };
System.out.println("----for each----");
// for-each陳述句
for (int item : numbers) {
System.out.println("Count is:" + item);
}
foreach 回圈和普通回圈不同的是,它無須回圈條件,無須回圈迭代陳述句,這些部分都由系統來完成,foreach 回圈自動迭代陣列的每個元素,當每個元素都被迭代一次后,foreach 回圈自動結束;
6.3.2 退出回圈
可以使用return結束回圈(本質上是終止函式的執行或退出類的方法并將控制權回傳給方法的擁有者),JAVA中提供break專門用于強制退出回圈;
我們下面介紹break的特殊用途 —— 退出深層回圈,要知道在C/C++中要退出多層回圈是沒有簡單方法的,JAVA提供了一種帶標簽的break陳述句,實作goto的功能,可以明確指定從何處重新開始執行
- 格式
break label;
label 是標識代碼塊的標簽,當執行這種形式的 break 陳述句時,控制權被傳遞出指定的代碼塊,用標簽(label)可以指定一個代碼塊,標簽可以是任何合法有效的 Java 識別符號,后跟一個冒號,加上標簽的代碼塊可以作為 break 陳述句的物件,使程式在加標簽的塊的結尾繼續執行;
- 被加標簽的代碼塊必須包圍 break 陳述句,但是它不需要直接包圍 break 的塊,也就是說,可以使用一個加標簽的 break 陳述句來退出一系列的嵌套塊,但是不能使用 break 陳述句將控制權傳遞到不包含 break 陳述句的代碼塊;
- 標簽陳述句必須和回圈匹配使用,使用時書寫在對應的回圈陳述句的上面,標簽陳述句以冒號結束,如果需要中斷標簽陳述句對應的回圈,可以采用 break 后面跟標簽名的方式;
- 舉例
public class GotoDemo {
public static void main(String[] args) {
label: for (int i = 0; i < 10; i++) {
for (int j = 0; j < 8; j++) {
System.out.println(j);
if (j % 2 != 0) {
break label;
}
}
}
}
}
7.JAVA陣列
陣列(array)是一種最簡單的復合資料型別,它是有序資料的集合,陣列中的每個元素具有相同的資料型別,可以用一個統一的陣列名和不同的下標來確定陣列中唯一的元素,根據陣列的維度,可以將其分為一維陣列、二維陣列和多維陣列等;
陣列是一種參考資料型別
7.1 一維陣列
- 宣告一維陣列語法格式
//宣告一個參考該陣列的變數,并指明整個變數可以參考的陣列型別
type[] arrayName; // 資料型別[] 陣列名,這種方式是推薦的,type[]是一種新的參考型別;
//或者
type arrayName[]; // 資料型別 陣列名[],盡管C++是這種宣告方式,但之后的語言都逐漸摒棄了這種方法;
宣告陣列時不要規定陣列的長度,會導致錯誤
- 實體
int[] score; // 存盤學生的成績,型別為整型
double[] price; // 存盤商品的價格,型別為浮點型
String[] name; // 存盤商品名稱,型別為字串型
宣告了陣列,只是得到了一個存放陣列的變數,并沒有為陣列元素分配記憶體空間,不能使用,因此要為陣列分配記憶體空間,這樣陣列的每一個元素才有一個空間進行存盤, Java 中可以使用 new 關鍵字來給陣列分配空間;
- 分配空間語法格式
arrayName = new type[size]; // 陣列名 = new 資料型別[陣列長度];
//當然也可以將分配空間和宣告陣列的時機放在一起
- 舉例
score = new int[10];
price = new double[30];
name = new String[20];
注意:一旦宣告了陣列的大小,就不能再修改,這里的陣列長度也是必需的,不能少;
8.JAVA集合類
(JAVA的集合類真的是一個非常非常天坑的知識點,光看知識點真的沒法理解)
陣列長度不可變、陣列無法保存具有映射關系的資料,為了保存數量不確定的資料,以及保存具有映射關系的資料(也被稱為關聯陣列),JAVA提供了集合類;
陣列元素可以是基本型別的值也可以是物件,而集合類中只能保存物件;
8.1 List集合
-
List 是一個
有序、可重復的集合,集合中每個元素都有其對應的順序索引; -
List 集合
允許使用重復元素,可以通過索引來訪問指定位置的集合元素; -
List 集合默認按元素的添加順序設定元素的索引,第一個添加到 List 集合中的元素的索引為 0,第二個為 1,依此類推;
8.1.1 ArrayList類
ArrayList 類實作了可變陣列的大小,存盤在內的資料稱為元素;
它還提供了快速基于索引訪問元素的方式,對尾部成員的增加和洗掉支持較好;
使用 ArrayList 創建的集合,允許對集合中的元素進行快速的隨機訪問,不過,向 ArrayList 中插入與洗掉元素的速度相對較慢;
8.1.2 LinkedList類
LinkedList 類采用鏈表結構保存物件,這種結構的優點是便于向集合中插入或者洗掉元素;
需要頻繁向集合中插入和洗掉元素時,使用 LinkedList 類比 ArrayList 類效果高,但是 LinkedList 類隨機訪問元素的速度則相對較慢(這里的隨機訪問是指檢索集合中特定索引位置的元素);
8.2 set集合
-
Set 集合中的物件不按特定的方式排序,只是簡單地把物件加入集合;
-
Set 集合中不能包含重復的物件,并且最多只允許包含一個 null 元素;
8.2.1 HashSet類
HashSet 是 Set 介面的典型實作,大多數時候使用 Set 集合時就是使用這個實作類,HashSet 是按照 Hash 演算法來存盤集合中的元素,因此具有很好的存取和查找性能,
- 不能保證元素的排列順序,順序可能與添加順序不同,順序也有可能發生變化;
- HashSet 不是同步的,如果多個執行緒同時訪問或修改一個 HashSet,則必須通過代碼來保證其同步;
- 集合元素值可以是 null;
8.3 Map集合
Map 是一種鍵-值對(key-value)集合,Map 集合中的每一個元素都包含一個鍵(key)物件和一個值(value)物件,用于保存具有映射關系的資料;
-
Map 集合里保存著兩組值,一組值用于保存 Map 里的 key,另外一組值用于保存 Map 里的 value,key 和 value 都可以是任何參考型別的資料;
-
Map 的 key 不允許重復,value 可以重復;
-
Map 中的 key 和 value 之間存在單向一對一關系,即通過指定的 key,總能找到唯一的、確定的 value;
Map 介面主要有兩個實作類:HashMap 類和 TreeMap 類,其中,HashMap 類按哈希演算法來存取鍵物件,而 TreeMap 類可以對鍵物件進行排序;
三、JAVA進階
1.JAVA類和物件
首先,C++中沒有這種將基本資料型別設計為包裝類的說法,為什么?因為C++的特性并不僅限于面向物件,所以無論是基本資料型別還是復合資料型別(陣列、型別別、結構)有各自的特點和作用;
但是,JAVA不一樣,它規定了“一切皆為物件”,它是完全面向物件的語言,也就是說無論是基本資料型別還是其他的型別,所有的操作都要求用物件的形式進行描述(比如.運算子訪問屬性),然而基本資料型別本身不符合這個規定,所以就出現了包裝類這個說法(將在后面簡單介紹這一性質,這個性質算不上JAVA的重點);
- 類:構造物件的模板或藍圖;
- 物件:通過類構造(也稱為創建)的實體;
- 實體域:類中的資料稱為實體域,每個特定的實體物件都有一組特定的實體域值,這些值的集合就是物件的
狀態; - 方法:類中操縱資料的程序;
- 對實體域做出修改的方法稱為更改器方法;
- 僅訪問實體域而不進行修改的方法稱為訪問器方法;
- 封裝:絕對不能讓類中的方法直接地訪問其他類的實體域(實體域設定為Private),程式只能通過物件的方法與物件資料進行互動進而改變物件的狀態,
JAVA封裝的基本單位是類;
類之間的關系有:
- 依賴(uses-a):一個類的物件操作另一個類的物件,應當減少依賴類的存在(讓類之間的耦合程度最小);
- 聚合(has-a):一個類的物件包含另一個類的物件;
- 繼承(is-a):子類繼承父類的成員(方法和域)(C++支持多繼承,但是多繼承往往會帶來很多沖突,所以JAVA只支持單繼承);
1.1 物件和物件變數
JAVA中使用構造器來構造一個物件,我們假設使用JAVA中的Date類
- 構造一個Date類的物件
new Date();//構造器的名字和類名相同,在構造器前面加上new運算子
- 構造一個Date類的物件變數
Date deadline;
一個物件變數并沒有實際包含一個物件(所以在沒有初始化物件變數的時候不能對物件變數使用成員運算子等),物件變數僅僅參考一個物件;
可以將JAVA的物件變數看作是C++的物件指標
Date birthday;//JAVA
Date * birthday;//C++
除了顯式創建物件以外還可以隱式創建物件,無論釆用哪種方式創建物件,Java 虛擬機在創建一個物件時都包含以下步驟:
- 給物件分配記憶體,
- 將物件的實體變數自動初始化為其變數型別的默認值,
- 初始化物件,給實體變數賦予正確的初始值,
1.2 用戶自定義類
要創建一個完整的程式,應該將若干類組合在一起,其中只有一個類有main方法;
-
假設某個程式包含兩個類EmployeeTest和Employee,其中EmployeeTest類帶有public修飾符且包含了main方法,則該程式的源檔案名應該是EmployeeTest.java,當編譯器編譯這段代碼的時候將在目錄下創建兩個檔案,EmployeeTest.class和Employee.class,要運行這段程式需要將程式中包含main方法的類名提供給位元組碼解釋器javac;
-
假如習慣將每一個類存在一個單獨的源檔案中,如EmployeeTest在EmployeeTest.java,Employee在Employee.java,則有兩種編譯程式的方法使用通用符占位或直接只編譯公有類檔案;
java Employee*.java
java EmployeeTest.java
1.2.1 定義類
在 Java 中定義一個類,需要使用 class 關鍵字、一個自定義的類名和一對表示程式體的大括號
[public][abstract|final]class<class_name>[extends<class_name>][implements<interface_name>] {
...
}
中括號“[]”中的部分表示可以省略,豎線“|”表示“或關系”,“|”兩邊的關鍵字不能同時出現
public:表示“共有”的意思,如果使用 public 修飾,則可以被其他類和程式訪問,每個 Java 程式的主類都必須是 public 類,作為公共工具供其他類和程式使用的類應定義為 public 類,abstract:如果類被 abstract 修飾,則該類為抽象類,抽象類不能被實體化,但抽象類中可以有抽象方法(使用 abstract 修飾的方法)和具體方法(沒有使用 abstract 修飾的方法),繼承該抽象類的所有子類都必須實作該抽象類中的所有抽象方法(除非子類也是抽象類),final:如果類被 final 修飾,則不允許被繼承,class:宣告類的關鍵字,class_name:類的名稱,extends:表示繼承其他類,implements:表示實作某些介面,
1.2.2 構造器
這里所說的構造器本質上就是C++中的建構式
public Employee(String n, double s, int year, int month, int day)
{
name=n;
salary=s;
GregorianCalendar calendar = new Gregoriancalendar(year, month -1, day);
hireDay =calendar. getTime();
}
構造器與類同名,構造器的作用是將實體域初始化為所希望的狀態;
構造器與其他方法不同的地方在于構造器總是隨著new運算子的執行被呼叫,不能對一個已經存在的物件呼叫其構造器來重置實體域;
JAVA因為有自動回識訓制所以不支持析構器(為什么這里又說有析構方法呢?Java析構方法 (biancheng.net)解答參考java中怎么沒有解構式?_百度知道 (baidu.com));
僅當類沒有提供任何構造器的時候系統才會自動提供一個默認構造器,此時構造物件可以不提供任何構造引數,否則要想使用這種形式只能自己額外提供一個多載建構式;
構造方法不能被 static、final、synchronized、abstract 和 native(類似于 abstract)修飾
1.2.3 成員變數
宣告成員變數格式
public class Test {
[public|protected|private][static][final]<type><variable_name>
}
- public、protected、private:用于表示成員變數的訪問權限,
- static:表示該成員變數為類變數,也稱為靜態變數,
- final:表示將該成員變數宣告為常量,其值無法更改,
- type:表示變數的型別,
- variable_name:表示變數名稱,
舉例
public class Student {
public String name; // 姓名
final int sex = 0; // 性別:0表示女孩,1表示男孩
private int age; // 年齡
}
1.2.4 成員方法
一個完整的方法通常包括方法名稱、方法主體、方法引數和方法回傳值型別
宣告成員方法的格式
public class Test {
[public|private|protected][static]<void|return_type><method_name>([paramList]) {
// 方法體
}
}
1.3 訪問修飾符
JAVA提供了多個作用域修飾符,這些修飾符有類修飾符、變數修飾符和方法修飾符,詳細資訊可參考Java訪問控制修飾符詳解(public、 private、protected 和 friendly) (biancheng.net);
類的訪問控制符只能是null或者public,方法和屬性的訪問控制符有 4 個,分別是 public、 private、protected 和 friendly,其中 friendly 是一種沒有定義專門的訪問控制符的默認情況;

-
在實作一個類的時候,公開資料是十分危險的,所以應該將所有的資料域都設定為私有private;
-
對于某些輔助方法,不應當充當共有介面的一部分(因為它們往往需要一個特定的呼叫次序),這樣的方法最好設定為private;
-
實際應用中最好少用protected的域,protected的方法更加常見,因為JAVA的protected對所有子類和同一個包中的所有類都可見,所以安全性相較于C++會差一點;
1.4 靜態域和靜態方法
靜態成員不依賴于類的特定實體,被類的所有實體共享,就是說 static 修飾的方法或者變數不需要依賴于物件來進行訪問,只要這個類被加載,JAVA 虛擬機就可以根據類名找到它們
呼叫靜態成員的語法形式如下:
類名.靜態成員
- static 修飾的成員變數和方法,從屬于類,
- 普通變數和方法從屬于物件,
- 靜態方法不能呼叫非靜態成員,編譯會報錯,
1.4.1 靜態域
如果將類的實體域定義為static(每個類中只會有一個這樣的域),那么這個類的每一個物件將共享這個靜態域,即使沒有任何一個類物件,靜態域也存在(因為它屬于類而不屬于任何獨立的物件);
實際上JAVA中的靜態域一般都被稱為類域;
1.4.2 靜態常量
靜態變數使用較少而靜態常量(不屬于靜態域的字符)使用較多;
可以直接通過類名.常量名的形式獲取這個常量;
1.4.3 靜態方法
使用靜態方法的情況:
- 該方法不需要訪問物件狀態,其所需引數都是通過顯式引數提供;
- 該方法只需要訪問類的靜態域;
靜態方法是一種不能向物件實施操作的方法,可以認為靜態方法是沒有this隱式引數的方法;
因為靜態方法不能操作物件故靜態方法也就不能訪問實體域,但是靜態方法可以訪問自身類中的靜態域;
同樣可以通過類名來呼叫這個方法(當然使用物件名來呼叫靜態方法也沒有問題,但本質上靜態方法的結果和物件沒有任何關系,這容易造成混淆);
1.5 包
JAVA使用包將類組織起來,標準的JAVA類別庫分布在多個包中;
標準的JAVA包都有一個層次結構,JAVA包名是絕對唯一的;
使用包的其中一個原因是為了確保類名的唯一性(這個包實際上非常類似于C++的名稱空間),假如兩個程式員都建立了Employee類,只要將這兩個類放在不同的包中就不會產生沖突;
1.5.1 類的匯入(類匯出包)
一個類可以訪問所屬包中的所有類以及其他包中的公有類public;
訪問其他包中的公有類主要有兩種方法:
- 在每個類名之前添加完整的包名
java.util.Date today = new java.util.Date()
- 使用import陳述句
import java.util.*;//匯入java.util包中的所有類
import java.util.Date;//匯入包中一個特定的類
可以使用import陳述句匯入一個特定的類或者整個包,import陳述句需要位于源檔案的頂部、package陳述句后面
1.5.2 靜態匯入
import陳述句不僅可以匯入類,還可以匯入靜態方法和靜態域,靜態匯入使用相對較少,主要用于以下情況:
- 算術函式:對Math類使用靜態匯入則可以更加自然的使用算術函式;
- 笨重的常量:如果需要使用大量帶有冗長名字的常量則最好使用靜態匯入;
1.5.3 包匯入類
若需要將一個類放入包中,則必須將這個包的名字放在源檔案的開頭定義類的代碼之前
package java.util
public class Employee
{
...
...
}
如果沒有在源檔案中防止package陳述句則這個源檔案的類就被放置在一個默認的包中(默認包是一個沒有名字的包);
我們需要將包中的檔案存放在與完整包名匹配的子目錄中,com.horstman.corejava包中的所有源檔案都應該被放在對應子目錄下,這樣編譯器也會相應的將類檔案放在同樣的目錄結構中;

1.5.4 包作用域
前面介紹的訪問修飾符public標記的部分可以被任意的類使用,private標記的部分只能被定義它們的類使用,如果沒有指定public和private則這個部分可以被同一個包中的所有方法訪問;
1.6 方法引數
程式設計語言中將引數傳遞給方法/函式有兩種方式:
- 值呼叫:表示方法接收的是呼叫者提供的值的拷貝;
- 參考呼叫:表示方法接收的是呼叫者提供的變數地址;
JAVA程式只能采用值呼叫(無論引數是值還是物件),因此JAVA的方法不能修改傳遞給它的任何一個引數;
1.7 this關鍵字
this 關鍵字可用于任何實體方法內指向當前物件,也可指向對其呼叫當前方法的物件,或者在需要當前型別物件參考時使用
1.7.1 this.屬性名
大部分時候,普通方法訪問其他方法、成員變數時無須使用 this 前綴,但如果方法里有個區域變數和成員變數同名,但程式又需要在該方法里訪問這個被覆寫的成員變數,則必須使用 this 前綴;
public class Teacher {
private String name; // 教師名稱
private double salary; // 工資
private int age; // 年齡
// 創建構造方法,為上面的3個屬性賦初始值
public Teacher(String name,double salary,int age) {
this.name = name; // 設定教師名稱
this.salary = salary; // 設定教師工資
this.age = age; // 設定教師年齡
}
}
當一個類的屬性(成員變數)名與訪問該屬性的方法引數名相同時,則需要使用 this 關鍵字來訪問類中的屬性,以區分類的屬性和方法中的引數
1.7.2 this.方法名
this 關鍵字最大的作用就是讓類中一個方法,訪問該類里的另一個方法或實體變數(關于實體變數上面已經介紹過this.屬性名);
public class Dog {
// 定義一個jump()方法
public void jump() {
System.out.println("正在執行jump方法");
}
// 定義一個run()方法,run()方法需要借助jump()方法
public void run() {
// 使用this參考呼叫run()方法的物件
this.jump();
System.out.println("正在執行run方法");
}
}
對于 static 修飾的方法而言,可以使用類來直接呼叫該方法,如果在 static 修飾的方法中使用 this 關鍵字,則這個關鍵字就無法指向合適的物件,所以,static 修飾的方法中不能使用 this 參考,并且 Java 語法規定,靜態成員不能直接訪問非靜態成員;
2.JAVA繼承
面向物件除了類和物件以外,另一個基本概念是繼承,利用繼承可以基于一個已經存在的類來構造一個新類;
繼承已經存在的類就是復用這些類的方法和域,再次基礎上可以添加一些新的方法和域;
2.1 類的繼承
先展示一下由繼承Employee類來定義Manager類的格式,extends關鍵字表示繼承
class Manager extends Employee
{
//添加方法和域
}
- JAVA中的所有繼承都是公有繼承public,沒有C++中的私有繼承private和保護繼承protected(但是是存在private和protected訪問修飾符的);
- 已經存在的類稱為
超類、基類或父類,如上面的Employee;派生出的新類稱為子類、派生類或孩子類; - 在通過
拓展超類定義子類的時候,只需要指出子類和超類的不同之處即可,因此設計類的時候應該將通用的方法放在超類中,將具有特殊用途的方法放在子類中; - 子類可以通過重新定義超類中的方法來
覆寫超類中原有方法,However,子類絕對不能洗掉繼承的任何域或方法; - 當子類需要呼叫超類的同名方法時可以使用super關鍵字
super.getSalary();
方法多載:同一個類中包含了兩個或兩個以上方法名相同的方法,但形參串列不同;
方法重寫:也稱為覆寫,子類中如果創建了一個與父類中相同名稱、相同回傳值型別、相同引數串列的方法,只是方法體中的實作不同,以實作不同于父類的功能;
2.2 繼承層次
由一個超類派生出的所有類的集合被稱為繼承層次,在繼承層次中從某個特定的類到其祖先的路徑被稱為繼承鏈;

2.3 阻止繼承
當需要阻止利用某個類來自定義子類,可以在定義該類的時候加上final識別符號表明該類是final類
final class Executive extends Manager{
//阻止人們自定義Executive類的子類
}
類中的方法也可以被final修飾,這樣子類就不能覆寫這個方法(final類的所有方法自動稱為final方法)
class Employee
{
public final String getName()
{
return name;
}
}
當然域也可以被宣告為final,final域在構造物件之后就不允許改變它們的值了;
將類或方法宣告為final的原因是為了確保它們不會在子類中改變語意
2.4 抽象類
從繼承結構來看,位于上層的類更加通用、抽象,而位于上層的類具備的一些通用方法,在本層可能暫時無法實作(因為可能需要的某些引數暫時還沒有),此時可以使用abstract關鍵字,這樣就完全無需在上層實作該方法(C++中利用純虛函式實作抽象類);
包含一個或多個抽象方法的類本身必須被宣告為抽象的,除了抽象方法外,抽象類還可以包含具體的資料和方法;
abstract class Person
{
public abstract String getDescription();
public String getName()
{
return name;
}
private String name;
}
抽象方法充當著占位的角色,它們的具體實作在子類中,擴展抽象類可以有兩種選擇:
- 一種是在子類中定義部分抽象方法或不定義抽象方法,這樣就必須將子類也標記為抽象類;
- 另一種是定義全部的抽象方法,這樣一來,子類就不是抽象的了;
實際上抽象類就算不包含任何的抽象方法也可以被標記為抽象類,抽象類不能被實體化也就是不能創建這個類的物件;
2.5 Object超類
盡管Object類是所有JAVA類的祖先(C++中沒有根類),但是在類宣告時沒必要這樣寫
class Employee extends Object
在實際使用中,如果沒有明確指出超類,則Object類默認成為該類的超類;
- 可以使用Object類的物件變數參考任何型別的物件
Object obj = new Employee();
- JAVA中除了基本資料型別不是物件(數值、字符、布林值),其他型別都拓展于Object類(包括陣列型別)
Object類中有一些重要的方法,比如equals方法檢測兩個物件是否相等、toString方法回傳表示物件值的字串,這些Object提供的服務需要掌握:

3.包裝類
參考自:Java內置的包裝類 (biancheng.net)
有時,需要將int這樣的基本型別轉換為物件,所有的基本型別都有一個與之對應的類,例如,Integer類對應基本型別int,通常,這些類稱為包裝器(wrapper)、包裝類、包裝器類,這些物件包裝器類擁有很鮮明的名字:Integer,Long,Float,Double,Short,Byte,Character,Void和Boolean(前6個類派生于公共的超類Number),
- 物件包裝器類是不可變的,即一旦構造了包裝器,就不允許更改包裝在其中的值;
- 物件包裝器類還是final,因此不能定義它們的子類;
3.1 裝箱和拆箱
- 基本資料型別轉換為包裝類的程序稱為裝箱(自動打包);
Integer n = 3;
#編譯器自動插入一條拆物件包指令
n++;#接著進行int自增計算
#最后將結果打包進物件包Integer內
- 包裝類變為基本資料型別的程序稱為拆箱(自動拆包);
#將一個Integer物件賦值給一個int值時,會自動拆包
int n = list.get(i);
#上述陳述句被編譯器自動翻譯為
int n = list.get(i).intValue();
打包和拆包是編譯器認可的,而不是虛擬機;編譯器在進行打包和拆包的時候會插入必要的方法呼叫,接著生成類的位元組碼
要實作手動裝箱和拆箱需要借助包裝類的構造方法裝箱,通過包裝類的intValue方法拆箱
int m = 500;
Integer obj = new Integer(m); // 手動裝箱
int n = obj.intValue(); // 手動拆箱
3.2 Integer類
Integer 類在物件中包裝了一個基本型別 int 的值,該類提供了多個方法,能在 int 型別和 String 型別之間互相轉換,還提供了處理 int 型別時非常有用的其他一些常量和方法;
Integer 類中的構造方法有以下兩個(手動裝箱):
- Integer(int value):構造一個新分配的 Integer 物件,它表示指定的 int 值;
- Integer(String s):構造一個新分配的 Integer 物件,它表示 String 引數所指示的 int 值;
Integer integer1 = new Integer(100); // 以 int 型變數作為引數創建 Integer 物件
Integer integer2 = new Integer("100"); // 以 String 型變數作為引數創建 Integer 物件
可以借助Integer中的方法將字串(應當只包含數值型別的字符)和int型別的數值相互轉換
String str = "456";
int num = Integer.parseInt(str); // 將字串轉換為int型別的數值
int i = 789;
String s = Integer.toString(i); // 將int型別的數值轉換為字串
Integer類包含以下四個常量
int max_value = https://www.cnblogs.com/Tintoki/p/Integer.MAX_VALUE; // 獲取 int 型別可取的最大值
int min_value = Integer.MIN_VALUE; // 獲取 int 型別可取的最小值
int size = Integer.SIZE; // 獲取 int 型別的二進制位
Class c = Integer.TYPE; // 獲取基本型別 int 的 Class 實體
3.3 Float類
Float 類在物件中包裝了一個基本型別 float 的值,該類提供了多個方法,能在 float 型別與 String 型別之間互相轉換,同時還提供了處理 float 型別時比較常用的常量和方法;
Float 類中的構造方法有以下 3 個,
- Float(double value):構造一個新分配的 Float 物件,它表示轉換為 float 型別的引數;
- Float(float value):構造一個新分配的 Float 物件,它表示基本的 float 引數;
- Float(String s):構造一個新分配的 Float 物件,它表示 String 引數所指示的 float 值;
Float float1 = new Float(3.14145); // 以 double 型別的變數作為引數創建 Float 物件
Float float2 = new Float(6.5); // 以 float 型別的變數作為引數創建 Float 物件
Float float3 = new Float("3.1415"); // 以 String 型別的變數作為引數創建 Float 物件
可以借助Integer中的方法將字串(應當只包含數值型別的字符)和float型別的數值相互轉換
String str = "456.7";
float num = Float.parseFloat(str); // 將字串轉換為 float 型別的數值
float f = 123.4f;
String s = Float.toString(f); // 將 float 型別的數值轉換為字串
Float類包含很多常量,具體可以查閱資料
float max_value = https://www.cnblogs.com/Tintoki/p/Float.MAX_VALUE; // 獲取 float 型別可取的最大值
float min_value = Float.MIN_VALUE; // 獲取 float 型別可取的最小值
float min_normal = Float.MIN_NORMAL; // 獲取 float 型別可取的最小標準值
float size = Float.SIZE; // 獲取 float 型別的二進制位
3.4 Number超類
上面說過有六個基本的包裝類派生于公共的Number超類,Number同時也是一個抽象類,Number類屬于java.lang包;
因為抽象類不能被實體化,只能實體化它的具體的子類(Double、Float...),下面簡單展示一下Number類的使用
Number num = new Double(12.5);#定義一個抽象類的物件變數,只能參考非抽象子類的物件
System.out.println("回傳 double 型別的值:" + num.doubleValue());#回傳 double 型別的值:12.5
System.out.println("回傳 int 型別的值:" + num.intValue());#回傳 int 型別的值:12
System.out.println("回傳 float 型別的值:" + num.floatValue());#回傳 float 型別的值:12.5
4.System類
System 類位于 java.lang 包,代表當前JAVA程式的運行平臺,系統級的很多屬性和控制方法都放置在該類的內部,由于該類的構造方法是 private 的,所以無法創建該類的物件,也就是無法實體化該類;
System 類提供了一些類變數和類方法,允許直接通過 System 類來呼叫這些類變數和類方法;
4.1 成員變數
System類有3個靜態成員變數:
- printstream out:標準輸出流,對應于顯示幕輸出或者由主機環境或用戶指定的另一個輸出目標
#撰寫一行輸出資料的典型方式
System.out.println(data);
#println 方法是屬于流類 PrintStream 的方法,而不是 System 中的方法
- inputstream in:標準輸入流,對應于鍵盤輸入或者由主機環境或用戶指定的另一個輸入源
- printstream err:標準錯誤輸出流:語法與 System.out 類似,不需要提供引數就可輸出錯誤資訊,也可以用來輸出用戶指定的其他資訊,包括變數的值
4.2 成員方法
System 類中提供了一些系統級的操作方法,常用的方法有 arraycopy()、currentTimeMillis()、exit()、gc() 和 getProperty(),具體使用方法可以查閱資料;
5.反射
-
編譯期:指把原始碼交給編譯器編譯成計算機可以執行的檔案的程序(Java 中也就是把 Java 代碼編成 class 檔案的程序);
-
運行期:把編譯后的檔案交給計算機執行,直到程式運行結束(所謂運行期就把在磁盤中的代碼放到記憶體中執行起);
JAVA反射機制是指在運行狀態中,對于任意一個類,都能夠知道這個類的所有屬性和方法;對于任意一個物件,都能夠呼叫它的任意方法和屬性(簡單來說,反射機制指的是程式在運行時能夠獲取自身的資訊);
Java 反射機制主要提供了以下功能,這些功能都位于java.lang.reflect包:
- 在運行時判斷任意一個物件所屬的類,
- 在運行時構造任意一個類的物件,
- 在運行時判斷任意一個類所具有的成員變數和方法,
- 在運行時呼叫任意一個物件的方法,
- 生成動態代理,
JAVA中反射機制用的比較少,這里就不再贅述,感興趣可以自己查閱資料;
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/529836.html
標籤:Java
