日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程语言 > java >内容正文

java

我肝了一个月,给你写出了这本Java开发手册。

發(fā)布時(shí)間:2025/3/21 java 72 豆豆
生活随笔 收集整理的這篇文章主要介紹了 我肝了一个月,给你写出了这本Java开发手册。 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

先來看一下本篇文章的思維導(dǎo)圖吧,我會圍繞下面這些內(nèi)容進(jìn)行講解。

下面開始我們的文章。

?

Java 概述

什么是 Java?

Java 是 Sun Microsystems 于1995 年首次發(fā)布的一種編程語言和計(jì)算平臺。編程語言還比較好理解,那么什么是?計(jì)算平臺?呢?

計(jì)算平臺是在電腦中運(yùn)行應(yīng)用程序(軟件)的環(huán)境,包括硬件環(huán)境和軟件環(huán)境。一般系統(tǒng)平臺包括一臺電腦的硬件體系結(jié)構(gòu)、操作系統(tǒng)、運(yùn)行時(shí)庫。

Java 是快速,安全和可靠的。從筆記本電腦到數(shù)據(jù)中心,從游戲機(jī)到科學(xué)超級計(jì)算機(jī),從手機(jī)到互聯(lián)網(wǎng),Java 無處不在!Java 主要分為三個(gè)版本

  • JavaSE(J2SE)(Java2 Platform Standard Edition,java平臺標(biāo)準(zhǔn)版)

  • JavaEE(J2EE)(Java 2 Platform,Enterprise Edition,java平臺企業(yè)版)

  • JavaME(J2ME)(Java 2 Platform Micro Edition,java平臺微型版)。

Java 的特點(diǎn)

  • Java 是一門面向?qū)ο蟮木幊陶Z言

什么是面向?qū)ο?#xff1f;面向?qū)ο?Object Oriented)?是一種軟件開發(fā)思想。它是對現(xiàn)實(shí)世界的一種抽象,面向?qū)ο髸严嚓P(guān)的數(shù)據(jù)和方法組織為一個(gè)整體來看待。

相對的另外一種開發(fā)思想就是面向過程的開發(fā)思想,什么面向過程?面向過程(Procedure Oriented)?是一種以過程為中心的編程思想。舉個(gè)例子:比如你是個(gè)學(xué)生,你每天去上學(xué)需要做幾件事情?

起床、穿衣服、洗臉?biāo)⒀?#xff0c;吃飯,去學(xué)校。一般是順序性的完成一系列動作。

class?student?{void?student_wakeUp(){...}void?student_cloth(){...}void?student_wash(){...}void?student_eating(){...}void?student_gotoSchool(){...} }

而面向?qū)ο罂梢园褜W(xué)生進(jìn)行抽象,所以這個(gè)例子就會變?yōu)?/p> class?student(){void?wakeUp(){...}void?cloth(){...}void?wash(){...}void?eating(){...}void?gotoSchool(){...} }

可以不用嚴(yán)格按照順序來執(zhí)行每個(gè)動作。這是特點(diǎn)一。

  • Java 摒棄了 C++ 中難以理解的多繼承、指針、內(nèi)存管理等概念;不用手動管理對象的生命周期,這是特征二。

  • Java 語言具有功能強(qiáng)大和簡單易用兩個(gè)特征,現(xiàn)在企業(yè)級開發(fā),快速敏捷開發(fā),尤其是各種框架的出現(xiàn),使 Java 成為越來越火的一門語言。這是特點(diǎn)三。

  • Java 是一門靜態(tài)語言,靜態(tài)語言指的就是在編譯期間就能夠知道數(shù)據(jù)類型的語言,在運(yùn)行前就能夠檢查類型的正確性,一旦類型確定后就不能再更改,比如下面這個(gè)例子。

public?void?foo()?{int?x?=?5;boolean?b?=?x; }

靜態(tài)語言主要有?Pascal, Perl, C/C++, JAVA, C#, Scala?等。

相對應(yīng)的,動態(tài)語言沒有任何特定的情況需要指定變量的類型,在運(yùn)行時(shí)確定的數(shù)據(jù)類型。比如有**Lisp, Perl, Python、Ruby、JavaScript **等。

從設(shè)計(jì)的角度上來說,所有的語言都是設(shè)計(jì)用來把人類可讀的代碼轉(zhuǎn)換為機(jī)器指令。動態(tài)語言是為了能夠讓程序員提高編碼效率,因此你可以使用更少的代碼來實(shí)現(xiàn)功能。靜態(tài)語言設(shè)計(jì)是用來讓硬件執(zhí)行的更高效,因此需要程序員編寫準(zhǔn)確無誤的代碼,以此來讓你的代碼盡快的執(zhí)行。從這個(gè)角度來說,靜態(tài)語言的執(zhí)行效率要比動態(tài)語言高,速度更快。這是特點(diǎn)四。

  • Java 具有平臺獨(dú)立性和可移植性

Java 有一句非常著名的口號:Write once, run anywhere,也就是一次編寫、到處運(yùn)行。為什么 Java 能夠吹出這種牛批的口號來?核心就是?JVM。我們知道,計(jì)算機(jī)應(yīng)用程序和硬件之間會屏蔽很多細(xì)節(jié),它們之間依靠操作系統(tǒng)完成調(diào)度和協(xié)調(diào),大致的體系結(jié)構(gòu)如下

那么加上 Java 應(yīng)用、JVM 的體系結(jié)構(gòu)會變?yōu)槿缦?/p>

Java 是跨平臺的,已編譯的 Java 程序可以在任何帶有 JVM 的平臺上運(yùn)行。你可以在 Windows 平臺下編寫代碼,然后拿到 Linux 平臺下運(yùn)行,該如何實(shí)現(xiàn)呢?

首先你需要在應(yīng)用中編寫 Java 代碼;

用?Eclipse?或者?javac?把 Java 代碼編譯為?.class?文件;

然后把你的 .class 文件打成?.jar?文件;

然后你的 .jar 文件就能夠在 Windows 、Mac OS X、Linux 系統(tǒng)下運(yùn)行了。不同的操作系統(tǒng)有不同的 JVM 實(shí)現(xiàn),切換平臺時(shí),不需要再次編譯你的 Java 代碼了。這是特點(diǎn)五。

  • Java 能夠容易實(shí)現(xiàn)多線程

Java 是一門高級語言,高級語言會對用戶屏蔽很多底層實(shí)現(xiàn)細(xì)節(jié)。比如 Java 是如何實(shí)現(xiàn)多線程的。從操作系統(tǒng)的角度來說,實(shí)現(xiàn)多線程的方式主要有下面這幾種

在用戶空間中實(shí)現(xiàn)多線程

在內(nèi)核空間中實(shí)現(xiàn)多線程

在用戶和內(nèi)核空間中混合實(shí)現(xiàn)線程

而我認(rèn)為 Java 應(yīng)該是在?用戶空間?實(shí)現(xiàn)的多線程,內(nèi)核是感知不到 Java 存在多線程機(jī)制的。這是特點(diǎn)六。

  • Java 具有高性能

我們編寫的代碼,經(jīng)過 javac 編譯器編譯稱為?字節(jié)碼(bytecode),經(jīng)過 JVM 內(nèi)嵌的解釋器將字節(jié)碼轉(zhuǎn)換為機(jī)器代碼,這是解釋執(zhí)行,這種轉(zhuǎn)換過程效率較低。但是部分 JVM 的實(shí)現(xiàn)比如?Hotspot JVM?都提供了?JIT(Just-In-Time)?編譯器,也就是通常所說的動態(tài)編譯􏱆器,JIT 能夠在運(yùn)行時(shí)將􏲀熱點(diǎn)代碼編譯機(jī)器碼,這種方式運(yùn)行效率比較高,這是編譯執(zhí)行。所以 Java 不僅僅只是一種解釋執(zhí)行的語言。這是特點(diǎn)七。

  • Java 語言具有健壯性

Java 的強(qiáng)類型機(jī)制、異常處理、垃圾的自動收集等是 Java 程序健壯性的重要保證。這也是 Java 與 C 語言的重要區(qū)別。這是特點(diǎn)八。

  • Java 很容易開發(fā)分布式項(xiàng)目

Java 語言支持 Internet 應(yīng)用的開發(fā),Java 中有 net api,它提供了用于網(wǎng)絡(luò)應(yīng)用編程的類庫,包括URL、URLConnection、Socket、ServerSocket等。Java的?RMI(遠(yuǎn)程方法激活)機(jī)制也是開發(fā)分布式應(yīng)用的重要手段。這是特點(diǎn)九。

Java 開發(fā)環(huán)境

JDK

JDK(Java Development Kit)稱為 Java 開發(fā)包或 Java 開發(fā)工具,是一個(gè)編寫 Java 的 Applet 小程序和應(yīng)用程序的程序開發(fā)環(huán)境。JDK是整個(gè)Java的核心,包括了Java運(yùn)行環(huán)境(Java Runtime Environment),一些Java 工具?和?Java 的核心類庫(Java API)。

我們可以認(rèn)真研究一下這張圖,它幾乎包括了 Java 中所有的概念,我使用的是?jdk1.8,可以點(diǎn)進(jìn)去?Description of Java Conceptual Diagram, 可以發(fā)現(xiàn)這里面包括了所有關(guān)于 Java 的描述

Oracle 提供了兩種 Java 平臺的實(shí)現(xiàn),一種是我們上面說的 JDK,Java 開發(fā)標(biāo)準(zhǔn)工具包,一種是 JRE,叫做Java Runtime Environment,Java 運(yùn)行時(shí)環(huán)境。JDK 的功能要比 JRE 全很多。

JRE

JRE 是個(gè)運(yùn)行環(huán)境,JDK 是個(gè)開發(fā)環(huán)境。因此寫 Java 程序的時(shí)候需要 JDK,而運(yùn)行 Java 程序的時(shí)候就需要JRE。而 JDK 里面已經(jīng)包含了JRE,因此只要安裝了JDK,就可以編輯 Java 程序,也可以正常運(yùn)行 Java 程序。但由于 JDK 包含了許多與運(yùn)行無關(guān)的內(nèi)容,占用的空間較大,因此運(yùn)行普通的 Java 程序無須安裝 JDK,而只需要安裝 JRE 即可。

Java 開發(fā)環(huán)境配置

這個(gè)地方不再多說了,網(wǎng)上有很多教程配置的資料可供參考。

Java 基本語法

在配置完 Java 開發(fā)環(huán)境,并下載 Java 開發(fā)工具(Eclipse、IDEA 等)后,就可以寫 Java 代碼了,因?yàn)楸酒恼率菑念^梳理 Java 體系,所以有必要從基礎(chǔ)的概念開始談起。

數(shù)據(jù)類型

在 Java 中,數(shù)據(jù)類型只有四類八種

  • 整數(shù)型:byte、short、int、long

byte 也就是字節(jié),1 byte = 8 bits,byte 的默認(rèn)值是 0 ;

short 占用兩個(gè)字節(jié),也就是 16 位,1 short = 16 bits,它的默認(rèn)值也是 0 ;

int 占用四個(gè)字節(jié),也就是 32 位,1 int = 32 bits,默認(rèn)值是 0 ;

long 占用八個(gè)字節(jié),也就是 64 位,1 long = 64 bits,默認(rèn)值是 0L;

所以整數(shù)型的占用字節(jié)大小空間為 long > int > short > byte

  • 浮點(diǎn)型

浮點(diǎn)型有兩種數(shù)據(jù)類型:float 和 double

float 是單精度浮點(diǎn)型,占用 4 位,1 float = 32 bits,默認(rèn)值是 0.0f;

double 是雙精度浮點(diǎn)型,占用 8 位,1 double = 64 bits,默認(rèn)值是 0.0d;

  • 字符型

字符型就是 char,char 類型是一個(gè)單一的 16 位 Unicode 字符,最小值是?\u0000 (也就是 0 ),最大值是?\uffff (即為 65535),char 數(shù)據(jù)類型可以存儲任何字符,例如 char a = 'A'。

  • 布爾型

布爾型指的就是 boolean,boolean 只有兩種值,true 或者是 false,只表示 1 位,默認(rèn)值是 false。

以上?x 位都指的是在內(nèi)存中的占用。

基礎(chǔ)語法

  • 大小寫敏感:Java 是對大小寫敏感的語言,例如 Hello 與 hello 是不同的,這其實(shí)就是 Java 的字符串表示方式

  • 類名:對于所有的類來說,首字母應(yīng)該大寫,例如?MyFirstClass

  • 包名:包名應(yīng)該盡量保證小寫,例如?my.first.package

  • 方法名:方法名首字母需要小寫,后面每個(gè)單詞字母都需要大寫,例如?myFirstMethod()

運(yùn)算符

運(yùn)算符不只 Java 中有,其他語言也有運(yùn)算符,運(yùn)算符是一些特殊的符號,主要用于數(shù)學(xué)函數(shù)、一些類型的賦值語句和邏輯比較方面,我們就以 Java 為例,來看一下運(yùn)算符。

  • 賦值運(yùn)算符

賦值運(yùn)算符使用操作符?=?來表示,它的意思是把 = 號右邊的值復(fù)制給左邊,右邊的值可以是任何常數(shù)、變量或者表達(dá)式,但左邊的值必須是一個(gè)明確的,已經(jīng)定義的變量。比如?int a = 4。

但是對于對象來說,復(fù)制的不是對象的值,而是對象的引用,所以如果說將一個(gè)對象復(fù)制給另一個(gè)對象,實(shí)際上是將一個(gè)對象的引用賦值給另一個(gè)對象

  • 算數(shù)運(yùn)算符

算數(shù)運(yùn)算符就和數(shù)學(xué)中的數(shù)值計(jì)算差不多,主要有

算數(shù)運(yùn)算符需要注意的就是優(yōu)先級問題,當(dāng)一個(gè)表達(dá)式中存在多個(gè)操作符時(shí),操作符的優(yōu)先級順序就決定了計(jì)算順序,最簡單的規(guī)則就是先乘除后加減,()?的優(yōu)先級最高,沒必要記住所有的優(yōu)先級順序,不確定的直接用 () 就可以了。

  • 自增、自減運(yùn)算符

這個(gè)就不文字解釋了,解釋不如直接看例子明白

int?a?=?5; b?=?++a; c?=?a++;
  • 比較運(yùn)算符

比較運(yùn)算符用于程序中的變量之間,變量和自變量之間以及其他類型的信息之間的比較。

比較運(yùn)算符的運(yùn)算結(jié)果是 boolean 型。當(dāng)運(yùn)算符對應(yīng)的關(guān)系成立時(shí),運(yùn)算的結(jié)果為 true,否則為 false。比較運(yùn)算符共有 6 個(gè),通常作為判斷的依據(jù)用于條件語句中。

  • 邏輯運(yùn)算符

邏輯運(yùn)算符主要有三種,與、或、非

下面是邏輯運(yùn)算符對應(yīng)的 true/false 符號表

  • 按位運(yùn)算符

按位運(yùn)算符用來操作整數(shù)基本類型中的每個(gè)比特位,也就是二進(jìn)制位。按位操作符會對兩個(gè)參數(shù)中對應(yīng)的位執(zhí)行布爾代數(shù)運(yùn)算,并最終生成一個(gè)結(jié)果。

如果進(jìn)行比較的雙方是數(shù)字的話,那么進(jìn)行比較就會變?yōu)榘次贿\(yùn)算。

按位與:按位進(jìn)行與運(yùn)算(AND),兩個(gè)操作數(shù)中位都為1,結(jié)果才為1,否則結(jié)果為0。需要首先把比較雙方轉(zhuǎn)換成二進(jìn)制再按每個(gè)位進(jìn)行比較

按位或:按位進(jìn)行或運(yùn)算(OR),兩個(gè)位只要有一個(gè)為1,那么結(jié)果就是1,否則就為0。

按位非:按位進(jìn)行異或運(yùn)算(XOR),如果位為0,結(jié)果是1,如果位為1,結(jié)果是0。

按位異或:按位進(jìn)行取反運(yùn)算(NOT),兩個(gè)操作數(shù)的位中,相同則結(jié)果為0,不同則結(jié)果為1。

  • 移位運(yùn)算符

移位運(yùn)算符用來將操作數(shù)向某個(gè)方向(向左或者右)移動指定的二進(jìn)制位數(shù)。

  • 三元運(yùn)算符

三元運(yùn)算符是類似?if...else...?這種的操作符,語法為:條件表達(dá)式?表達(dá)式 1:表達(dá)式 2。問號前面的位置是判斷的條件,判斷結(jié)果為布爾型,為 true 時(shí)調(diào)用表達(dá)式 1,為 false 時(shí)調(diào)用表達(dá)式 2。

Java 執(zhí)行控制流程

Java 中的控制流程其實(shí)和 C 一樣,在 Java 中,流程控制會涉及到包括?if-else、while、do-while、for、return、break?以及選擇語句?switch。下面以此進(jìn)行分析

條件語句

條件語句可根據(jù)不同的條件執(zhí)行不同的語句。包括 if 條件語句與 switch 多分支語句。

if 條件語句

if 語句可以單獨(dú)判斷表達(dá)式的結(jié)果,表示表達(dá)的執(zhí)行結(jié)果,例如

int?a?=?10; if(a?>?10){return?true; } return?false;

if...else 條件語句

if 語句還可以與 else 連用,通常表現(xiàn)為?如果滿足某種條件,就進(jìn)行某種處理,否則就進(jìn)行另一種處理

int?a?=?10; int?b?=?11; if(a?>=?b){System.out.println("a?>=?b"); }else{System.out.println("a?<?b"); }

if 后的 () 內(nèi)的表達(dá)式必須是 boolean 型的。如果為 true,則執(zhí)行 if 后的復(fù)合語句;如果為 false,則執(zhí)行 else 后的復(fù)合語句。

if...else if 多分支語句

上面中的 if...else 是單分支和兩個(gè)分支的判斷,如果有多個(gè)判斷條件,就需要使用?if...else if

int?x?=?40; if(x?>?60)?{System.out.println("x的值大于60"); }?else?if?(x?>?30)?{System.out.println("x的值大于30但小于60"); }?else?if?(x?>?0)?{System.out.println("x的值大于0但小于30"); }?else?{System.out.println("x的值小于等于0"); }

switch 多分支語句

一種比 **if...else if ** 語句更優(yōu)雅的方式是使用?switch?多分支語句,它的示例如下

switch?(week)?{case?1:System.out.println("Monday");break;case?2:System.out.println("Tuesday");break;case?3:System.out.println("Wednesday");break;case?4:System.out.println("Thursday");break;case?5:System.out.println("Friday");break;case?6:System.out.println("Saturday");break;case?7:System.out.println("Sunday");break;default:System.out.println("No?Else");break; }

循環(huán)語句

循環(huán)語句就是在滿足一定的條件下反復(fù)執(zhí)行某一表達(dá)式的操作,直到滿足循環(huán)語句的要求。使用的循環(huán)語句主要有 **for、do...while() 、 while **,

while 循環(huán)語句

while 循環(huán)語句的循環(huán)方式為利用一個(gè)條件來控制是否要繼續(xù)反復(fù)執(zhí)行這個(gè)語句。while 循環(huán)語句的格式如下

while(布爾值){表達(dá)式 }

它的含義是,當(dāng) (布爾值) 為 true 的時(shí)候,執(zhí)行下面的表達(dá)式,布爾值為 false 的時(shí)候,結(jié)束循環(huán),布爾值其實(shí)也是一個(gè)表達(dá)式,比如

int?a?=?10; while(a?>?5){a--; }

do...while 循環(huán)

while 與 do...while 循環(huán)的唯一區(qū)別是 do...while 語句至少執(zhí)行一次,即使第一次的表達(dá)式為 false。而在 while 循環(huán)中,如果第一次條件為 false,那么其中的語句根本不會執(zhí)行。在實(shí)際應(yīng)用中,while 要比 do...while 應(yīng)用的更廣。它的一般形式如下

int?b?=?10; //?do···while循環(huán)語句 do?{System.out.println("b?==?"?+?b);b--; }?while(b?==?1);

for 循環(huán)語句

for 循環(huán)是我們經(jīng)常使用的循環(huán)方式,這種形式會在第一次迭代前進(jìn)行初始化。它的形式如下

for(初始化;?布爾表達(dá)式;?步進(jìn)){}

每次迭代前會測試布爾表達(dá)式。如果獲得的結(jié)果是 false,就會執(zhí)行 for 語句后面的代碼;每次循環(huán)結(jié)束,會按照步進(jìn)的值執(zhí)行下一次循環(huán)。

逗號操作符

這里不可忽略的一個(gè)就是逗號操作符,Java 里唯一用到逗號操作符的就是 for 循環(huán)控制語句。在表達(dá)式的初始化部分,可以使用一系列的逗號分隔的語句;通過逗號操作符,可以在 for 語句內(nèi)定義多個(gè)變量,但它們必須具有相同的類型

for(int?i?=?1;j?=?i?+?10;i?<?5;i++,?j?=?j?*?2){}

for-each 語句

在 Java JDK 1.5 中還引入了一種更加簡潔的、方便對數(shù)組和集合進(jìn)行遍歷的方法,即?for-each?語句,例子如下

int?array[]?=?{7,?8,?9};for?(int?arr?:?array)?{System.out.println(arr); }

跳轉(zhuǎn)語句

Java 語言中,有三種跳轉(zhuǎn)語句:?break、continue 和 return

break 語句

break 語句我們在 switch 中已經(jīng)見到了,它是用于終止循環(huán)的操作,實(shí)際上 break 語句在for、while、do···while循環(huán)語句中,用于強(qiáng)行退出當(dāng)前循環(huán),例如

for(int?i?=?0;i?<?10;i++){if(i?==?5){break;} }

continue 語句

continue 也可以放在循環(huán)語句中,它與 break 語句具有相反的效果,它的作用是用于執(zhí)行下一次循環(huán),而不是退出當(dāng)前循環(huán),還以上面的例子為主

for(int?i?=?0;i?<?10;i++){System.out.printl("?i?=?"?+?i?);if(i?==?5){System.out.printl("continue?...?");continue;} }

return 語句

return 語句可以從一個(gè)方法返回,并把控制權(quán)交給調(diào)用它的語句。

public?void?getName()?{return?name; }

面向?qū)ο?/h2>

下面我們來探討面向?qū)ο蟮乃枷?#xff0c;面向?qū)ο蟮乃枷胍呀?jīng)逐步取代了過程化的思想 --- 面向過程,Java 是面向?qū)ο蟮母呒壘幊陶Z言,面向?qū)ο笳Z言具有如下特征

  • 面向?qū)ο笫且环N常見的思想,比較符合人們的思考習(xí)慣;

  • 面向?qū)ο罂梢詫?fù)雜的業(yè)務(wù)邏輯簡單化,增強(qiáng)代碼復(fù)用性;

  • 面向?qū)ο缶哂谐橄蟆⒎庋b、繼承、多態(tài)等特性。

面向?qū)ο蟮木幊陶Z言主要有:C++、Java、C#等。

所以必須熟悉面向?qū)ο蟮乃枷氩拍芫帉懗?Java 程序。

類也是一種對象

現(xiàn)在我們來認(rèn)識一個(gè)面向?qū)ο蟮男碌母拍?--- 類,什么是類,它就相當(dāng)于是一系列對象的抽象,就比如書籍一樣,類相當(dāng)于是書的封面,大多數(shù)面向?qū)ο蟮恼Z言都使用?class?來定義類,它告訴你它里面定義的對象都是什么樣的,我們一般使用下面來定義類

class?ClassName?{//?body; }

代碼段中涉及一個(gè)新的概念?//?,這個(gè)我們后面會說。上面,你聲明了一個(gè) class 類,現(xiàn)在,你就可以使用 new 來創(chuàng)建這個(gè)對象

ClassName?classname?=?new?ClassName();

一般,類的命名遵循駝峰原則,它的定義如下

駱駝式命名法(Camel-Case)又稱駝峰式命名法,是電腦程式編寫時(shí)的一套命名規(guī)則(慣例)。正如它的名稱 CamelCase 所表示的那樣,是指混合使用大小寫字母來構(gòu)成變量和函數(shù)的名字。程序員們?yōu)榱俗约旱拇a能更容易的在同行之間交流,所以多采取統(tǒng)一的可讀性比較好的命名方式。

對象的創(chuàng)建

在 Java 中,萬事萬物都是對象。這句話相信你一定不陌生,盡管一切都看作是對象,但是你操縱的卻是一個(gè)對象的?引用(reference)。在這里有一個(gè)很形象的比喻:你可以把車鑰匙和車看作是一組對象引用和對象的組合。當(dāng)你想要開車的時(shí)候,你首先需要拿出車鑰匙點(diǎn)擊開鎖的選項(xiàng),停車時(shí),你需要點(diǎn)擊加鎖來鎖車。車鑰匙相當(dāng)于就是引用,車就是對象,由車鑰匙來驅(qū)動車的加鎖和開鎖。并且,即使沒有車的存在,車鑰匙也是一個(gè)獨(dú)立存在的實(shí)體,也就是說,你有一個(gè)對象引用,但你不一定需要一個(gè)對象與之關(guān)聯(lián),也就是

Car?carKey;

這里創(chuàng)建的只是引用,而并非對象,但是如果你想要使用 s 這個(gè)引用時(shí),會返回一個(gè)異常,告訴你需要一個(gè)對象來和這個(gè)引用進(jìn)行關(guān)聯(lián)。一種安全的做法是,在創(chuàng)建對象引用時(shí)同時(shí)把一個(gè)對象賦給它。

Car?carKey?=?new?Car();

在 Java 中,一旦創(chuàng)建了一個(gè)引用,就希望它能與一個(gè)新的對象進(jìn)行關(guān)聯(lián),通常使用?new?操作符來實(shí)現(xiàn)這一目的。new 的意思是,給我一個(gè)新對象,如果你不想相親,自己 new 一個(gè)對象就好了。祝你下輩子幸福。

屬性和方法

類一個(gè)最基本的要素就是有屬性和方法。

屬性也被稱為字段,它是類的重要組成部分,屬性可以是任意類型的對象,也可以是基本數(shù)據(jù)類型。例如下

class?A{int?a;Apple?apple; }

類中還應(yīng)該包括方法,方法表示的是?做某些事情的方式。方法其實(shí)就是函數(shù),只不過 Java 習(xí)慣把函數(shù)稱為方法。這種叫法也體現(xiàn)了面向?qū)ο蟮母拍睢?/p>

方法的基本組成包括?方法名稱、參數(shù)、返回值和方法體, 下面是它的示例

public?int?getResult(){//?...return?1; }

其中,getResult?就是方法名稱、()?里面表示方法接收的參數(shù)、return?表示方法的返回值,注意:方法的返回值必須和方法的參數(shù)類型保持一致。有一種特殊的參數(shù)類型 ---?void?表示方法無返回值。{}?包含的代碼段被稱為方法體。

構(gòu)造方法

在 Java 中,有一種特殊的方法被稱為?構(gòu)造方法,也被稱為構(gòu)造函數(shù)、構(gòu)造器等。在 Java 中,通過提供這個(gè)構(gòu)造器,來確保每個(gè)對象都被初始化。構(gòu)造方法只能在對象的創(chuàng)建時(shí)期調(diào)用一次,保證了對象初始化的進(jìn)行。構(gòu)造方法比較特殊,它沒有參數(shù)類型和返回值,它的名稱要和類名保持一致,并且構(gòu)造方法可以有多個(gè),下面是一個(gè)構(gòu)造方法的示例

class?Apple?{int?sum;String?color;public?Apple(){}public?Apple(int?sum){}public?Apple(String?color){}public?Apple(int?sum,String?color){}}

上面定義了一個(gè) Apple 類,你會發(fā)現(xiàn)這個(gè) Apple 類沒有參數(shù)類型和返回值,并且有多個(gè)以 Apple 同名的方法,而且各個(gè) Apple 的參數(shù)列表都不一樣,這其實(shí)是一種多態(tài)的體現(xiàn),我們后面會說。在定義完成構(gòu)造方法后,我們就能夠創(chuàng)建 Apple 對象了。

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");} }

如上面所示,我們定義了四個(gè) Apple 對象,并調(diào)用了 Apple 的四種不同的構(gòu)造方法,其中,不加任何參數(shù)的構(gòu)造方法被稱為默認(rèn)的構(gòu)造方法,也就是

Apple?apple1?=?new?Apple();

如果類中沒有定義任何構(gòu)造方法,那么 JVM 會為你自動生成一個(gè)構(gòu)造方法,如下

class?Apple?{int?sum;String?color;}class?createApple?{public?static?void?main(String[]?args)?{Apple?apple1?=?new?Apple();} }

上面代碼不會發(fā)生編譯錯誤,因?yàn)?Apple 對象包含了一個(gè)默認(rèn)的構(gòu)造方法。

默認(rèn)的構(gòu)造方法也被稱為默認(rèn)構(gòu)造器或者無參構(gòu)造器。

這里需要注意一點(diǎn)的是,即使 JVM 會為你默認(rèn)添加一個(gè)無參的構(gòu)造器,但是如果你手動定義了任何一個(gè)構(gòu)造方法,JVM 就不再為你提供默認(rèn)的構(gòu)造器,你必須手動指定,否則會出現(xiàn)編譯錯誤

顯示的錯誤是,必須提供 Apple 帶有 int 參數(shù)的構(gòu)造函數(shù),而默認(rèn)的無參構(gòu)造函數(shù)沒有被允許使用。

方法重載

在 Java 中一個(gè)很重要的概念是方法的重載,它是類名的不同表現(xiàn)形式。我們上面說到了構(gòu)造函數(shù),其實(shí)構(gòu)造函數(shù)也是重載的一種。另外一種就是方法的重載

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";}}

如上面所示,就有兩種重載的方式,一種是 Apple 構(gòu)造函數(shù)的重載,一種是 getApple 方法的重載。

但是這樣就涉及到一個(gè)問題,要是有幾個(gè)相同的名字,Java 如何知道你調(diào)用的是哪個(gè)方法呢?這里記住一點(diǎn)即可,每個(gè)重載的方法都有獨(dú)一無二的參數(shù)列表。其中包括參數(shù)的類型、順序、參數(shù)數(shù)量等,滿足一種一個(gè)因素就構(gòu)成了重載的必要條件。

請記住下面重載的條件

  • 方法名稱必須相同。

  • 參數(shù)列表必須不同(個(gè)數(shù)不同、或類型不同、參數(shù)類型排列順序不同等)。

  • 方法的返回類型可以相同也可以不相同。

  • 僅僅返回類型不同不足以成為方法的重載。

  • 重載是發(fā)生在編譯時(shí)的,因?yàn)榫幾g器可以根據(jù)參數(shù)的類型來選擇使用哪個(gè)方法。

方法的重寫

方法的重寫與重載雖然名字很相似,但卻完全是不同的東西。方法重寫的描述是對子類和父類之間的。而重載指的是同一類中的。例如如下代碼

class?Fruit?{public?void?eat(){System.out.printl('eat?fruit');} }class?Apple?extends?Fruit{@Overridepublic?void?eat(){System.out.printl('eat?apple');} }

上面這段代碼描述的就是重寫的代碼,你可以看到,子類 Apple 中的方法和父類 Fruit 中的方法同名,所以,我們能夠推斷出重寫的原則

  • 重寫的方法必須要和父類保持一致,包括返回值類型,方法名,參數(shù)列表?也都一樣。

  • 重寫的方法可以使用?@Override?注解來標(biāo)識

  • 子類中重寫方法的訪問權(quán)限不能低于父類中方法的訪問權(quán)限。

初始化

類的初始化

上面我們創(chuàng)建出來了一個(gè) Car 這個(gè)對象,其實(shí)在使用 new 關(guān)鍵字創(chuàng)建一個(gè)對象的時(shí)候,其實(shí)是調(diào)用了這個(gè)對象無參數(shù)的構(gòu)造方法進(jìn)行的初始化,也就是如下這段代碼

class?Car{public?Car(){} }

這個(gè)無參數(shù)的構(gòu)造函數(shù)可以隱藏,由 JVM 自動添加。也就是說,構(gòu)造函數(shù)能夠確保類的初始化。

成員初始化

Java 會盡量保證每個(gè)變量在使用前都會獲得初始化,初始化涉及兩種初始化。

  • 一種是編譯器默認(rèn)指定的字段初始化,基本數(shù)據(jù)類型的初始化

  • 一種是其他對象類型的初始化,String 也是一種對象,對象的初始值都為?null?,其中也包括基本類型的包裝類。

  • 一種是指定數(shù)值的初始化,例如

int?a?=?11

也就是說, 指定 a 的初始化值不是 0 ,而是 11。其他基本類型和對象類型也是一樣的。

構(gòu)造器初始化

可以利用構(gòu)造器來對某些方法和某些動作進(jìn)行初始化,確定初始值,例如

public?class?Counter{int?i;public?Counter(){i?=?11;} }

利用構(gòu)造函數(shù),能夠把 i 的值初始化為 11。

初始化順序

首先先來看一下有哪些需要探討的初始化順序

  • 靜態(tài)屬性:static 開頭定義的屬性

  • 靜態(tài)方法塊:static {} 包起來的代碼塊

  • 普通屬性:非 static 定義的屬性

  • 普通方法塊:{} 包起來的代碼塊

  • 構(gòu)造函數(shù):類名相同的方法

  • 方法:普通方法

public?class?LifeCycle?{//?靜態(tài)屬性private?static?String?staticField?=?getStaticField();//?靜態(tài)方法塊static?{System.out.println(staticField);System.out.println("靜態(tài)方法塊初始化");}//?普通屬性private?String?field?=?getField();//?普通方法塊{System.out.println(field);}//?構(gòu)造函數(shù)public?LifeCycle()?{System.out.println("構(gòu)造函數(shù)初始化");}public?static?String?getStaticField()?{String?statiFiled?=?"Static?Field?Initial";return?statiFiled;}public?static?String?getField()?{String?filed?=?"Field?Initial";return?filed;}???//?主函數(shù)public?static?void?main(String[]?argc)?{new?LifeCycle();} }

這段代碼的執(zhí)行結(jié)果就反應(yīng)了它的初始化順序

靜態(tài)屬性初始化 靜態(tài)方法塊初始化 普通屬性初始化 普通方法塊初始化 構(gòu)造函數(shù)初始化

數(shù)組初始化

數(shù)組是相同類型的、用一個(gè)標(biāo)識符名稱封裝到一起的一個(gè)對象序列或基本類型數(shù)據(jù)序列。數(shù)組是通過方括號下標(biāo)操作符?[]?來定義使用。

一般數(shù)組是這么定義的

int[]?a1;//或者int?a1[];

兩種格式的含義是一樣的。

  • 直接給每個(gè)元素賦值 : int array[4] = {1,2,3,4};

  • 給一部分賦值,后面的都為 0 :int array[4] = {1,2};

  • 由賦值參數(shù)個(gè)數(shù)決定數(shù)組的個(gè)數(shù) :int array[] = {1,2};

可變參數(shù)列表

Java 中一種數(shù)組冷門的用法就是可變參數(shù)?,可變參數(shù)的定義如下

public?int?add(int...?numbers){int?sum?=?0;for(int?num?:?numbers){sum?+=?num;}return?sum; }

然后,你可以使用下面這幾種方式進(jìn)行可變參數(shù)的調(diào)用

add();??//?不傳參數(shù) add(1);??//?傳遞一個(gè)參數(shù) add(2,1);??//?傳遞多個(gè)參數(shù) add(new?Integer[]?{1,?3,?2});??//?傳遞數(shù)組

對象的銷毀

雖然 Java 語言是基于 C++ 的,但是它和 C/C++ 一個(gè)重要的特征就是不需要手動管理對象的銷毀工作。在著名的一書 《深入理解 Java 虛擬機(jī)》中提到一個(gè)觀點(diǎn)

在 Java 中,我們不再需要手動管理對象的銷毀,它是由?Java 虛擬機(jī)進(jìn)行管理和銷毀的。雖然我們不需要手動管理對象,但是你需要知道?對象作用域?這個(gè)概念。

對象作用域

J多數(shù)語言都有作用域(scope)?這個(gè)概念。作用域決定了其內(nèi)部定義的變量名的可見性和生命周期。在 C、C++ 和 Java 中,作用域通常由?{}?的位置來決定,例如

{int?a?=?11;{int?b?=?12;} }

a 變量會在兩個(gè)?{}?作用域內(nèi)有效,而 b 變量的值只能在它自己的?{}?內(nèi)有效。

雖然存在作用域,但是不允許這樣寫

{int?x?=?11;{int?x?=?12;} }

這種寫法在 C/C++ 中是可以的,但是在 Java 中不允許這樣寫,因?yàn)?Java 設(shè)計(jì)者認(rèn)為這樣寫會導(dǎo)致程序混亂。

###this 和 super

this 和 super 都是 Java 中的關(guān)鍵字

this 表示的當(dāng)前對象,this 可以調(diào)用方法、調(diào)用屬性和指向?qū)ο蟊旧怼his 在 Java 中的使用一般有三種:指向當(dāng)前對象

public?class?Apple?{int?i?=?0;Apple?eatApple(){i++;return?this;}public?static?void?main(String[]?args)?{Apple?apple?=?new?Apple();apple.eatApple().eatApple();} }

這段代碼比較精妙,精妙在哪呢,我一個(gè) eatApple() 方法竟然可以調(diào)用多次,你在后面還可以繼續(xù)調(diào)用,這就很神奇了,為啥呢?其實(shí)就是 this 在作祟了,我在?eatApple?方法中加了一個(gè)?return this?的返回值,也就是說哪個(gè)對象調(diào)用 eatApple 方法都能返回對象的自身。

this 還可以修飾屬性,最常見的就是在構(gòu)造方法中使用 this ,如下所示

public?class?Apple?{private?int?num;public?Apple(int?num){this.num?=?num;}public?static?void?main(String[]?args)?{new?Apple(10);} }

main 方法中傳遞了一個(gè) int 值為 10 的參數(shù),它表示的就是蘋果的數(shù)量,并把這個(gè)數(shù)量賦給了 num 全局變量。所以 num 的值現(xiàn)在就是 10。

this 還可以和構(gòu)造函數(shù)一起使用,充當(dāng)一個(gè)全局關(guān)鍵字的效果

public?class?Apple?{private?int?num;private?String?color;public?Apple(int?num){this(num,"紅色");}public?Apple(String?color){this(1,color);}public?Apple(int?num,?String?color)?{this.num?=?num;this.color?=?color;}}

你會發(fā)現(xiàn)上面這段代碼使用的不是 this, 而是?this(參數(shù))。它相當(dāng)于調(diào)用了其他構(gòu)造方法,然后傳遞參數(shù)進(jìn)去。這里注意一點(diǎn):this() 必須放在構(gòu)造方法的第一行,否則編譯不通過

如果你把 this 理解為指向自身的一個(gè)引用,那么 super 就是指向父類的一個(gè)引用。super 關(guān)鍵字和 this 一樣,你可以使用?super.對象?來引用父類的成員,如下

public?class?Fruit?{int?num;String?color;public?void?eat(){System.out.println("eat?Fruit");} }public?class?Apple?extends?Fruit{@Overridepublic?void?eat()?{super.num?=?10;System.out.println("eat?"?+?num?+?"?Apple");}}

你也可以使用?super(參數(shù))?來調(diào)用父類的構(gòu)造函數(shù),這里不再舉例子了。

下面為你匯總了 this 關(guān)鍵字和 super 關(guān)鍵字的比較。

訪問控制權(quán)限

訪問控制權(quán)限又稱為封裝,它是面向?qū)ο笕筇匦灾械囊环N,我之前在學(xué)習(xí)過程中經(jīng)常會忽略封裝,心想這不就是一個(gè)訪問修飾符么,怎么就是三大特性的必要條件了?后來我才知道,如果你信任的下屬對你隱瞞 bug,你是根本不知道的

訪問控制權(quán)限其實(shí)最核心就是一點(diǎn):只對需要的類可見。

Java中成員的訪問權(quán)限共有四種,分別是?public、protected、default、private,它們的可見性如下

繼承

繼承是所有?OOP(Object Oriented Programming)?語言和 Java 語言都不可或缺的一部分。只要我們創(chuàng)建了一個(gè)類,就隱式的繼承自?Object?父類,只不過沒有指定。如果你顯示指定了父類,那么你繼承于父類,而你的父類繼承于 Object 類。

繼承的關(guān)鍵字是?extends?,如上圖所示,如果使用了 extends 顯示指定了繼承,那么我們可以說 Father 是父類,而 Son 是子類,用代碼表示如下

class?Father{}class?Son?extends?Father{}

繼承雙方擁有某種共性的特征

class?Father{public?void?feature(){System.out.println("父親的特征");} }class?Son?extends?Father?{ }

如果 Son 沒有實(shí)現(xiàn)自己的方法的話,那么默認(rèn)就是用的是父類的?feature?方法。如果子類實(shí)現(xiàn)了自己的 feature 方法,那么就相當(dāng)于是重寫了父類的 feature 方法,這也是我們上面提到的重寫了。

多態(tài)

多態(tài)指的是同一個(gè)行為具有多個(gè)不同表現(xiàn)形式。是指一個(gè)類實(shí)例(對象)的相同方法在不同情形下具有不同表現(xiàn)形式。封裝和繼承是多態(tài)的基礎(chǔ),也就是說,多態(tài)只是一種表現(xiàn)形式而已。

如何實(shí)現(xiàn)多態(tài)?多態(tài)的實(shí)現(xiàn)具有三種充要條件

  • 繼承

  • 重寫父類方法

  • 父類引用指向子類對象

比如下面這段代碼

public?class?Fruit?{int?num;public?void?eat(){System.out.println("eat?Fruit");} }public?class?Apple?extends?Fruit{@Overridepublic?void?eat()?{super.num?=?10;System.out.println("eat?"?+?num?+?"?Apple");}public?static?void?main(String[]?args)?{Fruit?fruit?=?new?Apple();fruit.eat();} }

你可以發(fā)現(xiàn)?main?方法中有一個(gè)很神奇的地方,Fruit fruit = new Apple(),Fruit 類型的對象竟然指向了 Apple 對象的引用,這其實(shí)就是多態(tài) -> 父類引用指向子類對象,因?yàn)?Apple 繼承于 Fruit,并且重寫了 eat 方法,所以能夠表現(xiàn)出來多種狀態(tài)的形式。

組合

組合其實(shí)不難理解,就是將對象引用置于新類中即可。組合也是一種提高類的復(fù)用性的一種方式。如果你想讓類具有更多的擴(kuò)展功能,你需要記住一句話多用組合,少用繼承

public?class?SoccerPlayer?{private?String?name;private?Soccer?soccer;}public?class?Soccer?{private?String?soccerName;???? }

代碼中 SoccerPlayer 引用了 Soccer 類,通過引用 Soccer 類,來達(dá)到調(diào)用 soccer 中的屬性和方法。

組合和繼承是有區(qū)別的,它們的主要區(qū)別如下。

關(guān)于繼承和組合孰優(yōu)孰劣的爭論沒有結(jié)果,只要發(fā)揮各自的長處和優(yōu)點(diǎn)即可,一般情況下,組合和繼承也是一對可以連用的好兄弟。

代理

除了繼承和組合外,另外一種值得探討的關(guān)系模型稱為?代理。代理的大致描述是,A 想要調(diào)用 B 類的方法,A 不直接調(diào)用,A 會在自己的類中創(chuàng)建一個(gè) B 對象的代理,再由代理調(diào)用 B 的方法。例如如下代碼

public?class?Destination?{public?void?todo(){System.out.println("control...");} }public?class?Device?{private?String?name;private?Destination?destination;private?DeviceController?deviceController;public?void?control(Destination?destination){destination.todo();}}public?class?DeviceController?{private?Device?name;private?Destination?destination;public?void?control(Destination?destination){destination.todo();} }

向上轉(zhuǎn)型

向上轉(zhuǎn)型代表了父類與子類之間的關(guān)系,其實(shí)父類和子類之間不僅僅有向上轉(zhuǎn)型,還有向下轉(zhuǎn)型,它們的轉(zhuǎn)型后的范圍不一樣

  • 向上轉(zhuǎn)型:通過子類對象(小范圍)轉(zhuǎn)化為父類對象(大范圍),這種轉(zhuǎn)換是自動完成的,不用強(qiáng)制。

  • 向下轉(zhuǎn)型?: 通過父類對象(大范圍)實(shí)例化子類對象(小范圍),這種轉(zhuǎn)換不是自動完成的,需要強(qiáng)制指定。

static

static 是 Java 中的關(guān)鍵字,它的意思是?靜態(tài)的,static 可以用來修飾成員變量和方法,static 用在沒有創(chuàng)建對象的情況下調(diào)用 方法/變量。

  • 用 static 聲明的成員變量為靜態(tài)成員變量,也成為類變量。類變量的生命周期和類相同,在整個(gè)應(yīng)用程序執(zhí)行期間都有效。

static?String?name?=?"cxuan";
  • 使用 static 修飾的方法稱為靜態(tài)方法,靜態(tài)方法能夠直接使用類名.方法名?進(jìn)行調(diào)用。由于靜態(tài)方法不依賴于任何對象就可以直接訪問,因此對于靜態(tài)方法來說,是沒有 this 關(guān)鍵字的,實(shí)例變量都會有 this 關(guān)鍵字。在靜態(tài)方法中不能訪問類的非靜態(tài)成員變量和非靜態(tài)方法,

static?void?printMessage(){System.out.println("cxuan?is?writing?the?article"); }

static 除了修飾屬性和方法外,還有靜態(tài)代碼塊?的功能,可用于類的初始化操作。進(jìn)而提升程序的性能。

public?class?StaicBlock?{static{System.out.println("I'm?A?static?code?block");} }

由于靜態(tài)代碼塊隨著類的加載而執(zhí)行,因此,很多時(shí)候會將只需要進(jìn)行一次的初始化操作放在 static 代碼塊中進(jìn)行。

final

final 的意思是最后的、最終的,它可以修飾類、屬性和方法。

  • final 修飾類時(shí),表明這個(gè)類不能被繼承。final 類中的成員變量可以根據(jù)需要設(shè)為 final,但是要注意 final 類中的所有成員方法都會被隱式地指定為 final 方法。

  • final 修飾方法時(shí),表明這個(gè)方法不能被任何子類重寫,因此,如果只有在想明確禁止該方法在子類中被覆蓋的情況下才將方法設(shè)置為 final。

  • final 修飾變量分為兩種情況,一種是修飾基本數(shù)據(jù)類型,表示數(shù)據(jù)類型的值不能被修改;一種是修飾引用類型,表示對其初始化之后便不能再讓其指向另一個(gè)對象。

接口和抽象類

接口

接口相當(dāng)于就是對外的一種約定和標(biāo)準(zhǔn),這里拿操作系統(tǒng)舉例子,為什么會有操作系統(tǒng)?就會為了屏蔽軟件的復(fù)雜性和硬件的簡單性之間的差異,為軟件提供統(tǒng)一的標(biāo)準(zhǔn)。

在 Java 語言中,接口是由?interface?關(guān)鍵字來表示的,比如我們可以向下面這樣定義一個(gè)接口

public?interface?CxuanGoodJob?{}

比如我們定義了一個(gè) CxuanGoodJob 的接口,然后你就可以在其內(nèi)部定義 cxuan 做的好的那些事情,比如 cxuan 寫的文章不錯。

public?interface?CxuanGoodJob?{void?writeWell(); }

這里隱含了一些接口的特征:

  • interface?接口是一個(gè)完全抽象的類,他不會提供任何方法的實(shí)現(xiàn),只是會進(jìn)行方法的定義。

  • 接口中只能使用兩種訪問修飾符,一種是?public,它對整個(gè)項(xiàng)目可見;一種是?default?缺省值,它只具有包訪問權(quán)限。

  • 接口只提供方法的定義,接口沒有實(shí)現(xiàn),但是接口可以被其他類實(shí)現(xiàn)。也就是說,實(shí)現(xiàn)接口的類需要提供方法的實(shí)現(xiàn),實(shí)現(xiàn)接口使用?implements?關(guān)鍵字來表示,一個(gè)接口可以有多個(gè)實(shí)現(xiàn)。

class?CXuanWriteWell?implements?CxuanGoodJob{@Overridepublic?void?writeWell()?{System.out.println("Cxuan?write?Java?is?vary?well");} }
  • 接口不能被實(shí)例化,所以接口中不能有任何構(gòu)造方法,你定義構(gòu)造方法編譯會出錯。

  • 接口的實(shí)現(xiàn)比如實(shí)現(xiàn)接口的全部方法,否則必須定義為抽象類,這就是我們下面要說的內(nèi)容

抽象類

抽象類是一種抽象能力弱于接口的類,在 Java 中,抽象類使用?abstract?關(guān)鍵字來表示。如果把接口形容為狗這個(gè)物種,那么抽象類可以說是毛發(fā)是白色、小體的品種,而實(shí)現(xiàn)類可以是具體的類,比如說是博美、泰迪等。你可以像下面這樣定義抽象類

public?interface?Dog?{void?FurColor();}abstract?class?WhiteDog?implements?Dog{public?void?FurColor(){System.out.println("Fur?is?white");}abstract?void?SmallBody(); }

在抽象類中,具有如下特征

  • 如果一個(gè)類中有抽象方法,那么這個(gè)類一定是抽象類,也就是說,使用關(guān)鍵字?abstract?修飾的方法一定是抽象方法,具有抽象方法的類一定是抽象類。實(shí)現(xiàn)類方法中只有方法具體的實(shí)現(xiàn)。

  • 抽象類中不一定只有抽象方法,抽象類中也可以有具體的方法,你可以自己去選擇是否實(shí)現(xiàn)這些方法。

  • 抽象類中的約束不像接口那么嚴(yán)格,你可以在抽象類中定義?構(gòu)造方法、抽象方法、普通屬性、方法、靜態(tài)屬性和靜態(tài)方法

  • 抽象類和接口一樣不能被實(shí)例化,實(shí)例化只能實(shí)例化具體的類

異常

異常是程序經(jīng)常會出現(xiàn)的,發(fā)現(xiàn)錯誤的最佳時(shí)機(jī)是在編譯階段,也就是你試圖在運(yùn)行程序之前。但是,在編譯期間并不能找到所有的錯誤,有一些?NullPointerException?和?ClassNotFoundException?異常在編譯期找不到,這些異常是 RuntimeException 運(yùn)行時(shí)異常,這些異常往往在運(yùn)行時(shí)才能被發(fā)現(xiàn)。

我們寫 Java 程序經(jīng)常會出現(xiàn)兩種問題,一種是 java.lang.Exception ,一種是 java.lang.Error,都用來表示出現(xiàn)了異常情況,下面就針對這兩種概念進(jìn)行理解。

認(rèn)識 Exception

Exception?位于?java.lang?包下,它是一種頂級接口,繼承于?Throwable?類,Exception 類及其子類都是 Throwable 的組成條件,是程序出現(xiàn)的合理情況。

在認(rèn)識 Exception 之前,有必要先了解一下什么是?Throwable。

什么是 Throwable

Throwable 類是 Java 語言中所有錯誤(errors)和異常(exceptions)的父類。只有繼承于 Throwable 的類或者其子類才能夠被拋出,還有一種方式是帶有 Java 中的?@throw?注解的類也可以拋出。

在Java規(guī)范中,對非受查異常和受查異常的定義是這樣的:

The?unchecked exception classes?are the run-time exception classes and the error classes.

The?checked exception classes?are all exception classes other than the unchecked exception classes. That is, the checked exception classes are?Throwable?and all its subclasses other than?RuntimeException?and its subclasses and?Errorand its subclasses.

也就是說,除了?RuntimeException?和其子類,以及error和其子類,其它的所有異常都是?checkedException。

那么,按照這種邏輯關(guān)系,我們可以對 Throwable 及其子類進(jìn)行歸類分析

可以看到,Throwable 位于異常和錯誤的最頂層,我們查看 Throwable 類中發(fā)現(xiàn)它的方法和屬性有很多,我們只討論其中幾個(gè)比較常用的

//?返回拋出異常的詳細(xì)信息 public?string?getMessage(); public?string?getLocalizedMessage();//返回異常發(fā)生時(shí)的簡要描述 public?public?String?toString();//?打印異常信息到標(biāo)準(zhǔn)輸出流上 public?void?printStackTrace(); public?void?printStackTrace(PrintStream?s); public?void?printStackTrace(PrintWriter?s)//?記錄棧幀的的當(dāng)前狀態(tài) public?synchronized?Throwable?fillInStackTrace();

此外,因?yàn)?Throwable 的父類也是?Object,所以常用的方法還有繼承其父類的getClass()?和?getName()?方法。

常見的 Exception

下面我們回到 Exception 的探討上來,現(xiàn)在你知道了 Exception 的父類是 Throwable,并且 Exception 有兩種異常,一種是?RuntimeException?;一種是?CheckedException,這兩種異常都應(yīng)該去捕獲。

下面列出了一些 Java 中常見的異常及其分類,這塊面試官也可能讓你舉出幾個(gè)常見的異常情況并將其分類

RuntimeException

UncheckedException

與 Exception 有關(guān)的 Java 關(guān)鍵字

那么 Java 中是如何處理這些異常的呢?在 Java 中有這幾個(gè)關(guān)鍵字?throws、throw、try、finally、catch?下面我們分別來探討一下

throws 和 throw

在 Java 中,異常也就是一個(gè)對象,它能夠被程序員自定義拋出或者應(yīng)用程序拋出,必須借助于?throws?和?throw?語句來定義拋出異常。

throws 和 throw 通常是成對出現(xiàn)的,例如

static?void?cacheException()?throws?Exception{throw?new?Exception();}

throw 語句用在方法體內(nèi),表示拋出異常,由方法體內(nèi)的語句處理。throws 語句用在方法聲明后面,表示再拋出異常,由該方法的調(diào)用者來處理。

throws 主要是聲明這個(gè)方法會拋出這種類型的異常,使它的調(diào)用者知道要捕獲這個(gè)異常。throw 是具體向外拋異常的動作,所以它是拋出一個(gè)異常實(shí)例。

try 、finally 、catch

這三個(gè)關(guān)鍵字主要有下面幾種組合方式?try...catch 、try...finally、try...catch...finally

try...catch 表示對某一段代碼可能拋出異常進(jìn)行的捕獲,如下

static?void?cacheException()?throws?Exception{try?{System.out.println("1");}catch?(Exception?e){e.printStackTrace();}}

try...finally 表示對一段代碼不管執(zhí)行情況如何,都會走 finally 中的代碼

static?void?cacheException()?throws?Exception{for?(int?i?=?0;?i?<?5;?i++)?{System.out.println("enter:?i="?+?i);try?{System.out.println("execute:?i="?+?i);continue;}?finally?{System.out.println("leave:?i="?+?i);}} }

try...catch...finally 也是一樣的,表示對異常捕獲后,再走 finally 中的代碼邏輯。

什么是 Error

Error 是程序無法處理的錯誤,表示運(yùn)行應(yīng)用程序中較嚴(yán)重問題。大多數(shù)錯誤與代碼編寫者執(zhí)行的操作無關(guān),而表示代碼運(yùn)行時(shí) JVM(Java 虛擬機(jī))出現(xiàn)的問題。這些錯誤是不可檢查的,因?yàn)樗鼈冊趹?yīng)用程序的控制和處理能力之 外,而且絕大多數(shù)是程序運(yùn)行時(shí)不允許出現(xiàn)的狀況,比如?OutOfMemoryError?和?StackOverflowError異常的出現(xiàn)會有幾種情況,這里需要先介紹一下 Java 內(nèi)存模型 JDK1.7。

其中包括兩部分,由所有線程共享的數(shù)據(jù)區(qū)和線程隔離的數(shù)據(jù)區(qū)組成,在上面的 Java 內(nèi)存模型中,只有程序計(jì)數(shù)器是不會發(fā)生?OutOfMemoryError?情況的區(qū)域,程序計(jì)數(shù)器控制著計(jì)算機(jī)指令的分支、循環(huán)、跳轉(zhuǎn)、異常處理和線程恢復(fù),并且程序計(jì)數(shù)器是每個(gè)線程私有的。

什么是線程私有:表示的就是各條線程之間互不影響,獨(dú)立存儲的內(nèi)存區(qū)域。

如果應(yīng)用程序執(zhí)行的是 Java 方法,那么這個(gè)計(jì)數(shù)器記錄的就是虛擬機(jī)字節(jié)碼指令的地址;如果正在執(zhí)行的是?Native?方法,這個(gè)計(jì)數(shù)器值則為空(Undefined)。

除了程序計(jì)數(shù)器外,其他區(qū)域:方法區(qū)(Method Area)、虛擬機(jī)棧(VM Stack)、本地方法棧(Native Method Stack)?和?堆(Heap)?都是可能發(fā)生 OutOfMemoryError 的區(qū)域。

  • 虛擬機(jī)棧:如果線程請求的棧深度大于虛擬機(jī)棧所允許的深度,將會出現(xiàn)?StackOverflowError?異常;如果虛擬機(jī)動態(tài)擴(kuò)展無法申請到足夠的內(nèi)存,將出現(xiàn)?OutOfMemoryError。

  • 本地方法棧和虛擬機(jī)棧一樣

  • 堆:Java 堆可以處于物理上不連續(xù),邏輯上連續(xù),就像我們的磁盤空間一樣,如果堆中沒有內(nèi)存完成實(shí)例分配,并且堆無法擴(kuò)展時(shí),將會拋出 OutOfMemoryError。

  • 方法區(qū):方法區(qū)無法滿足內(nèi)存分配需求時(shí),將拋出 OutOfMemoryError 異常。

在 Java 中,你可以把異常理解為是一種能夠提高你程序健壯性的機(jī)制,它能夠讓你在編寫代碼中注意這些問題,也可以說,如果你寫代碼不會注意這些異常情況,你是無法成為一位硬核程序員的。

內(nèi)部類

距今為止,我們了解的都是普通類的定義,那就是直接在 IDEA 中直接新建一個(gè) class 。

新建完成后,你就會擁有一個(gè) class 文件的定義,這種操作太簡單了,時(shí)間長了就會枯燥,我們年輕人多需要更新潮和騷氣的寫法,好吧,既然你提到了那就使用?內(nèi)部類吧,這是一種有用而且騷氣的定義類的方式,內(nèi)部類的定義非常簡單:可以將一個(gè)類的定義放在另一個(gè)類的內(nèi)部,這就是內(nèi)部類

內(nèi)部類是一種非常有用的特性,定義在類內(nèi)部的類,持有外部類的引用,但卻對其他外部類不可見,看起來就像是一種隱藏代碼的機(jī)制,就和?弗蘭奇將軍?似的,弗蘭奇可以和弗蘭奇將軍進(jìn)行通訊,但是外面的敵人卻無法直接攻擊到弗蘭奇本體。

下面我們就來聊一聊創(chuàng)建內(nèi)部類的方式。

創(chuàng)建內(nèi)部類

定義內(nèi)部類非常簡單,就是直接將一個(gè)類定義在外圍類的里面,如下代碼所示

public?class?OuterClass?{private?String?name?;private?int?age;class?InnerClass{public?InnerClass(){name?=?"cxuan";age?=?25;}} }

在這段代碼中,InnerClass 就是 OuterClass 的一個(gè)內(nèi)部類。也就是說,每個(gè)內(nèi)部類都能獨(dú)立地繼承一個(gè)(接口的)實(shí)現(xiàn),所以無論外圍類是否已經(jīng)繼承了某個(gè)(接口的)實(shí)現(xiàn),對于內(nèi)部類都沒有影響。這也是隱藏了內(nèi)部實(shí)現(xiàn)細(xì)節(jié)。內(nèi)部類擁有外部類的訪問權(quán)

內(nèi)部類不僅僅能夠定義在類的內(nèi)部,還可以定義在方法和作用域內(nèi)部,這種被稱為局部內(nèi)部類,除此之外,還有匿名內(nèi)部類、內(nèi)部類可以實(shí)現(xiàn) Java 中的?多重繼承。下面是定義內(nèi)部類的方式

  • 一個(gè)在方法中定義的類(局部內(nèi)部類)
  • 一個(gè)定義在作用域內(nèi)的類,這個(gè)作用域在方法的內(nèi)部(成員內(nèi)部類)
  • 一個(gè)實(shí)現(xiàn)了接口的匿名類(匿名內(nèi)部類)
  • 一個(gè)匿名類,它擴(kuò)展了非默認(rèn)構(gòu)造器的類
  • 一個(gè)匿名類,執(zhí)行字段初始化操作
  • 一個(gè)匿名類,它通過實(shí)例初始化實(shí)現(xiàn)構(gòu)造

由于每個(gè)類都會產(chǎn)生一個(gè)?.class?文件,其中包含了如何創(chuàng)建該類型的對象的全部信息,那么,如何表示內(nèi)部類的信息呢?可以使用?$?來表示,比如?OuterClass$InnerClass.class

集合

集合在我們的日常開發(fā)中所使用的次數(shù)簡直太多了,你已經(jīng)把它們都用的熟透了,但是作為一名合格的程序員,你不僅要了解它的基本用法,你還要了解它的源碼;存在即合理,你還要了解它是如何設(shè)計(jì)和實(shí)現(xiàn)的,你還要了解它的衍生過程。

這篇博客就來詳細(xì)介紹一下 Collection 這個(gè)龐大集合框架的家族體系和成員,讓你了解它的設(shè)計(jì)與實(shí)現(xiàn)。

是時(shí)候祭出這張神圖了

首先來介紹的就是列表爺爺輩兒的接口-?Iterator

Iterable 接口

實(shí)現(xiàn)此接口允許對象成為 for-each 循環(huán)的目標(biāo),也就是增強(qiáng) for 循環(huán),它是 Java 中的一種語法糖。

List<Object>?list?=?new?ArrayList(); for?(Object?obj:?list){}

除了實(shí)現(xiàn)此接口的對象外,數(shù)組也可以用 for-each 循環(huán)遍歷,如下:

Object[]?list?=?new?Object[10]; for?(Object?obj:?list){}

其他遍歷方式

jdk 1.8之前Iterator只有 iterator 一個(gè)方法,就是

Iterator<T>?iterator();

實(shí)現(xiàn)次接口的方法能夠創(chuàng)建一個(gè)輕量級的迭代器,用于安全的遍歷元素,移除元素,添加元素。這里面涉及到一個(gè)?fail-fast?機(jī)制。

總之一點(diǎn)就是能創(chuàng)建迭代器進(jìn)行元素的添加和刪除的話,就盡量使用迭代器進(jìn)行添加和刪除。

也可以使用迭代器的方式進(jìn)行遍歷

for(Iterator?it?=?coll.iterator();?it.hasNext();?){System.out.println(it.next()); }

頂層接口

Collection 是一個(gè)頂層接口,它主要用來定義集合的約定

List 接口也是一個(gè)頂層接口,它繼承了 Collection 接口 ,同時(shí)也是 ArrayList、LinkedList 等集合元素的父類

Set 接口位于與 List 接口同級的層次上,它同時(shí)也繼承了 Collection 接口。Set 接口提供了額外的規(guī)定。它對add、equals、hashCode ?方法提供了額外的標(biāo)準(zhǔn)。

Queue 是和 List、Set 接口并列的 Collection 的三大接口之一。Queue 的設(shè)計(jì)用來在處理之前保持元素的訪問次序。除了 Collection 基礎(chǔ)的操作之外,隊(duì)列提供了額外的插入,讀取,檢查操作。

SortedSet 接口直接繼承于 Set 接口,使用 Comparable 對元素進(jìn)行自然排序或者使用 Comparator 在創(chuàng)建時(shí)對元素提供定制的排序規(guī)則。set 的迭代器將按升序元素順序遍歷集合。

Map 是一個(gè)支持 key-value 存儲的對象,Map 不能包含重復(fù)的 key,每個(gè)鍵最多映射一個(gè)值。這個(gè)接口代替了Dictionary 類,Dictionary 是一個(gè)抽象類而不是接口。

ArrayList

ArrayList 是實(shí)現(xiàn)了 List 接口的可擴(kuò)容數(shù)組(動態(tài)數(shù)組),它的內(nèi)部是基于數(shù)組實(shí)現(xiàn)的。它的具體定義如下:

public?class?ArrayList<E>?extends?AbstractList<E>?implements?List<E>,?RandomAccess,?Cloneable,?java.io.Serializable?{...}
  • ArrayList 可以實(shí)現(xiàn)所有可選擇的列表操作,允許所有的元素,包括空值。ArrayList 還提供了內(nèi)部存儲 list 的方法,它能夠完全替代 Vector,只有一點(diǎn)例外,ArrayList 不是線程安全的容器。

  • ArrayList 有一個(gè)容量的概念,這個(gè)數(shù)組的容量就是 List 用來存儲元素的容量。

  • ArrayList 不是線程安全的容器,如果多個(gè)線程中至少有兩個(gè)線程修改了 ArrayList 的結(jié)構(gòu)的話就會導(dǎo)致線程安全問題,作為替代條件可以使用線程安全的 List,應(yīng)使用?Collections.synchronizedList?。

List?list?=?Collections.synchronizedList(new?ArrayList(...))
  • ArrayList 具有 fail-fast 快速失敗機(jī)制,能夠?qū)?ArrayList 作出失敗檢測。當(dāng)在迭代集合的過程中該集合在結(jié)構(gòu)上發(fā)生改變的時(shí)候,就有可能會發(fā)生 fail-fast,即拋出?ConcurrentModificationException異常。

Vector

Vector 同 ArrayList 一樣,都是基于數(shù)組實(shí)現(xiàn)的,只不過 Vector 是一個(gè)線程安全的容器,它對內(nèi)部的每個(gè)方法都簡單粗暴的上鎖,避免多線程引起的安全性問題,但是通常這種同步方式需要的開銷比較大,因此,訪問元素的效率要遠(yuǎn)遠(yuǎn)低于 ArrayList。

還有一點(diǎn)在于擴(kuò)容上,ArrayList 擴(kuò)容后的數(shù)組長度會增加 50%,而 Vector 的擴(kuò)容長度后數(shù)組會增加一倍。

LinkedList 類

LinkedList 是一個(gè)雙向鏈表,允許存儲任何元素(包括 null )。它的主要特性如下:

  • LinkedList 所有的操作都可以表現(xiàn)為雙向性的,索引到鏈表的操作將遍歷從頭到尾,視哪個(gè)距離近為遍歷順序。

  • 注意這個(gè)實(shí)現(xiàn)也不是線程安全的,如果多個(gè)線程并發(fā)訪問鏈表,并且至少其中的一個(gè)線程修改了鏈表的結(jié)構(gòu),那么這個(gè)鏈表必須進(jìn)行外部加鎖。或者使用

List?list?=?Collections.synchronizedList(new?LinkedList(...))

Stack

堆棧是我們常說的后入先出(吃了吐)的容器 。它繼承了 Vector 類,提供了通常用的 push 和 pop 操作,以及在棧頂?shù)?peek 方法,測試 stack 是否為空的 empty 方法,和一個(gè)尋找與棧頂距離的 search 方法。

第一次創(chuàng)建棧,不包含任何元素。一個(gè)更完善,可靠性更強(qiáng)的 LIFO 棧操作由 Deque 接口和他的實(shí)現(xiàn)提供,應(yīng)該優(yōu)先使用這個(gè)類

Deque<Integer>?stack?=?new?ArrayDeque<Integer>()

HashSet

HashSet 是 Set 接口的實(shí)現(xiàn)類,由哈希表支持(實(shí)際上 HashSet 是 HashMap 的一個(gè)實(shí)例)。它不能保證集合的迭代順序。這個(gè)類允許 null 元素。

  • 注意這個(gè)實(shí)現(xiàn)不是線程安全的。如果多線程并發(fā)訪問 HashSet,并且至少一個(gè)線程修改了set,必須進(jìn)行外部加鎖。或者使用?Collections.synchronizedSet()?方法重寫。

  • 這個(gè)實(shí)現(xiàn)支持 fail-fast 機(jī)制。

TreeSet

TreeSet 是一個(gè)基于 TreeMap 的 NavigableSet 實(shí)現(xiàn)。這些元素使用他們的自然排序或者在創(chuàng)建時(shí)提供的Comparator 進(jìn)行排序,具體取決于使用的構(gòu)造函數(shù)。

  • 此實(shí)現(xiàn)為基本操作 add,remove 和 contains 提供了 log(n) 的時(shí)間成本。

  • 注意這個(gè)實(shí)現(xiàn)不是線程安全的。如果多線程并發(fā)訪問 TreeSet,并且至少一個(gè)線程修改了 set,必須進(jìn)行外部加鎖。或者使用

SortedSet?s?=?Collections.synchronizedSortedSet(new?TreeSet(...))
  • 這個(gè)實(shí)現(xiàn)持有 fail-fast 機(jī)制。

LinkedHashSet 類

LinkedHashSet 繼承于 Set,先來看一下 LinkedHashSet 的繼承體系:

LinkedHashSet 是 Set 接口的 Hash 表和 LinkedList 的實(shí)現(xiàn)。這個(gè)實(shí)現(xiàn)不同于 HashSet 的是它維護(hù)著一個(gè)貫穿所有條目的雙向鏈表。此鏈表定義了元素插入集合的順序。注意:如果元素重新插入,則插入順序不會受到影響。

  • LinkedHashSet 有兩個(gè)影響其構(gòu)成的參數(shù):初始容量和加載因子。它們的定義與 HashSet 完全相同。但請注意:對于 LinkedHashSet,選擇過高的初始容量值的開銷要比 HashSet 小,因?yàn)?LinkedHashSet 的迭代次數(shù)不受容量影響。

  • 注意 LinkedHashSet 也不是線程安全的,如果多線程同時(shí)訪問 LinkedHashSet,必須加鎖,或者通過使用

Collections.synchronizedSet
  • 該類也支持fail-fast機(jī)制

PriorityQueue

PriorityQueue 是 AbstractQueue 的實(shí)現(xiàn)類,優(yōu)先級隊(duì)列的元素根據(jù)自然排序或者通過在構(gòu)造函數(shù)時(shí)期提供Comparator 來排序,具體根據(jù)構(gòu)造器判斷。PriorityQueue 不允許 null 元素。

  • 隊(duì)列的頭在某種意義上是指定順序的最后一個(gè)元素。隊(duì)列查找操作 poll,remove,peek 和 element 訪問隊(duì)列頭部元素。

  • 優(yōu)先級隊(duì)列是無限制的,但具有內(nèi)部 capacity,用于控制用于在隊(duì)列中存儲元素的數(shù)組大小。

  • 該類以及迭代器實(shí)現(xiàn)了 Collection、Iterator 接口的所有可選方法。這個(gè)迭代器提供了?iterator()?方法不能保證以任何特定順序遍歷優(yōu)先級隊(duì)列的元素。如果你需要有序遍歷,考慮使用?Arrays.sort(pq.toArray())。

  • 注意這個(gè)實(shí)現(xiàn)不是線程安全的,多線程不應(yīng)該并發(fā)訪問 PriorityQueue 實(shí)例如果有某個(gè)線程修改了隊(duì)列的話,使用線程安全的類?PriorityBlockingQueue。

HashMap

HashMap 是一個(gè)利用哈希表原理來存儲元素的集合,并且允許空的 key-value 鍵值對。HashMap 是非線程安全的,也就是說在多線程的環(huán)境下,可能會存在問題,而 Hashtable 是線程安全的容器。HashMap 也支持 fail-fast 機(jī)制。HashMap 的實(shí)例有兩個(gè)參數(shù)影響其性能:初始容量 和加載因子。可以使用?Collections.synchronizedMap(new HashMap(...))?來構(gòu)造一個(gè)線程安全的 HashMap。

TreeMap 類

一個(gè)基于 NavigableMap 實(shí)現(xiàn)的紅黑樹。這個(gè) map 根據(jù) key 自然排序存儲,或者通過 Comparator 進(jìn)行定制排序。

  • TreeMap 為 containsKey,get,put 和remove方法提供了 log(n) 的時(shí)間開銷。

  • 注意這個(gè)實(shí)現(xiàn)不是線程安全的。如果多線程并發(fā)訪問 TreeMap,并且至少一個(gè)線程修改了 map,必須進(jìn)行外部加鎖。這通常通過在自然封裝集合的某個(gè)對象上進(jìn)行同步來實(shí)現(xiàn),或者使用?SortedMap m = Collections.synchronizedSortedMap(new TreeMap(...))。

  • 這個(gè)實(shí)現(xiàn)持有fail-fast機(jī)制。

LinkedHashMap 類

LinkedHashMap 是 Map 接口的哈希表和鏈表的實(shí)現(xiàn)。這個(gè)實(shí)現(xiàn)與 HashMap 不同之處在于它維護(hù)了一個(gè)貫穿其所有條目的雙向鏈表。這個(gè)鏈表定義了遍歷順序,通常是插入 map 中的順序。

  • 它提供一個(gè)特殊的 LinkedHashMap(int,float,boolean) 構(gòu)造器來創(chuàng)建 LinkedHashMap,其遍歷順序是其最后一次訪問的順序。

  • 可以重寫 removeEldestEntry(Map.Entry) 方法,以便在將新映射添加到 map 時(shí)強(qiáng)制刪除過期映射的策略。

  • 這個(gè)類提供了所有可選擇的 map 操作,并且允許 null 元素。由于維護(hù)鏈表的額外開銷,性能可能會低于HashMap,有一條除外:遍歷 LinkedHashMap 中的 collection-views 需要與 map.size 成正比,無論其容量如何。HashMap 的迭代看起來開銷更大,因?yàn)檫€要求時(shí)間與其容量成正比。

  • LinkedHashMap 有兩個(gè)因素影響了它的構(gòu)成:初始容量和加載因子。

  • 注意這個(gè)實(shí)現(xiàn)不是線程安全的。如果多線程并發(fā)訪問LinkedHashMap,并且至少一個(gè)線程修改了map,必須進(jìn)行外部加鎖。這通常通過在自然封裝集合的某個(gè)對象上進(jìn)行同步來實(shí)現(xiàn)?Map m = Collections.synchronizedMap(new LinkedHashMap(...))。

  • 這個(gè)實(shí)現(xiàn)持有fail-fast機(jī)制。

Hashtable 類

Hashtable 類實(shí)現(xiàn)了一個(gè)哈希表,能夠?qū)㈡I映射到值。任何非空對象都可以用作鍵或值。

  • 此實(shí)現(xiàn)類支持 fail-fast 機(jī)制

  • 與新的集合實(shí)現(xiàn)不同,Hashtable 是線程安全的。如果不需要線程安全的容器,推薦使用 HashMap,如果需要多線程高并發(fā),推薦使用?ConcurrentHashMap。

IdentityHashMap 類

IdentityHashMap 是比較小眾的 Map 實(shí)現(xiàn)了。

  • 這個(gè)類不是一個(gè)通用的 Map 實(shí)現(xiàn)!雖然這個(gè)類實(shí)現(xiàn)了 Map 接口,但它故意違反了 Map 的約定,該約定要求在比較對象時(shí)使用 equals 方法,此類僅適用于需要引用相等語義的極少數(shù)情況。

  • 同 HashMap,IdentityHashMap 也是無序的,并且該類不是線程安全的,如果要使之線程安全,可以調(diào)用Collections.synchronizedMap(new IdentityHashMap(...))方法來實(shí)現(xiàn)。

  • 支持fail-fast機(jī)制

WeakHashMap 類

WeakHashMap 類基于哈希表的 Map 基礎(chǔ)實(shí)現(xiàn),帶有弱鍵。WeakHashMap 中的 entry 當(dāng)不再使用時(shí)還會自動移除。更準(zhǔn)確的說,給定key的映射的存在將不會阻止 key 被垃圾收集器丟棄。

  • 基于 map 接口,是一種弱鍵相連,WeakHashMap 里面的鍵會自動回收

  • 支持 null 值和 null 鍵。

  • fast-fail 機(jī)制

  • 不允許重復(fù)

  • WeakHashMap 經(jīng)常用作緩存

Collections 類

Collections 不屬于 Java 框架繼承樹上的內(nèi)容,它屬于單獨(dú)的分支,Collections 是一個(gè)包裝類,它的作用就是為集合框架提供某些功能實(shí)現(xiàn),此類只包括靜態(tài)方法操作或者返回 collections。

同步包裝

同步包裝器將自動同步(線程安全性)添加到任意集合。六個(gè)核心集合接口(Collection,Set,List,Map,SortedSet 和 SortedMap)中的每一個(gè)都有一個(gè)靜態(tài)工廠方法。

public?static??Collection?synchronizedCollection(Collection?c); public?static??Set?synchronizedSet(Set?s); public?static??List?synchronizedList(List?list); public?static?<K,V>?Map<K,V>?synchronizedMap(Map<K,V>?m); public?static??SortedSet?synchronizedSortedSet(SortedSet?s); public?static?<K,V>?SortedMap<K,V>?synchronizedSortedMap(SortedMap<K,V>?m);

不可修改的包裝

不可修改的包裝器通過攔截修改集合的操作并拋出?UnsupportedOperationException,主要用在下面兩個(gè)情景:

  • 構(gòu)建集合后使其不可變。在這種情況下,最好不要去獲取返回 collection 的引用,這樣有利于保證不變性

  • 允許某些客戶端以只讀方式訪問你的數(shù)據(jù)結(jié)構(gòu)。你保留對返回的 collection 的引用,但分發(fā)對包裝器的引用。通過這種方式,客戶可以查看但不能修改,同時(shí)保持完全訪問權(quán)限。

這些方法是:

public?static??Collection?unmodifiableCollection(Collection<??extends?T>?c); public?static??Set?unmodifiableSet(Set<??extends?T>?s); public?static??List?unmodifiableList(List<??extends?T>?list); public?static?<K,V>?Map<K,?V>?unmodifiableMap(Map<??extends?K,???extends?V>?m); public?static??SortedSet?unmodifiableSortedSet(SortedSet<??extends?T>?s); public?static?<K,V>?SortedMap<K,?V>?unmodifiableSortedMap(SortedMap<K,???extends?V>?m);

線程安全的Collections

Java1.5 并發(fā)包?(java.util.concurrent)?提供了線程安全的 collections 允許遍歷的時(shí)候進(jìn)行修改,通過設(shè)計(jì)iterator 為 fail-fast 并拋出 ConcurrentModificationException。一些實(shí)現(xiàn)類是CopyOnWriteArrayList,ConcurrentHashMap,CopyOnWriteArraySet

Collections 算法

此類包含用于集合框架算法的方法,例如二進(jìn)制搜索,排序,重排,反向等。

集合實(shí)現(xiàn)類特征圖

下圖匯總了部分集合框架的主要實(shí)現(xiàn)類的特征圖,讓你能有清晰明了看出每個(gè)實(shí)現(xiàn)類之間的差異性

還有一種類型是關(guān)于強(qiáng)引用、弱引用、虛引用的文章,請參考

https://mp.weixin.qq.com/s/ZflBpn2TBzTNv_-G-zZxNg

泛形

在 Jdk1.5 中,提出了一種新的概念,那就是泛型,那么什么是泛型呢?

泛型其實(shí)就是一種參數(shù)化的集合,它限制了你添加進(jìn)集合的類型。泛型的本質(zhì)就是一種參數(shù)化類型。多態(tài)也可以看作是泛型的機(jī)制。一個(gè)類繼承了父類,那么就能通過它的父類找到對應(yīng)的子類,但是不能通過其他類來找到具體要找的這個(gè)類。泛型的設(shè)計(jì)之處就是希望對象或方法具有最廣泛的表達(dá)能力。

下面來看一個(gè)例子說明沒有泛型的用法

List?arrayList?=?new?ArrayList(); arrayList.add("cxuan"); arrayList.add(100);for(int?i?=?0;?i<?arrayList.size();i++){String?item?=?(String)arrayList.get(i);System.out.println("test?===?",?item); }

這段程序不能正常運(yùn)行,原因是 Integer ?類型不能直接強(qiáng)制轉(zhuǎn)換為 String 類型

java.lang.ClassCastException:?java.lang.Integer?cannot?be?cast?to?java.lang.String

如果我們用泛型進(jìn)行改寫后,示例代碼如下

List<String>?arrayList?=?new?ArrayList<String>();arrayList.add(100);

這段代碼在編譯期間就會報(bào)錯,編譯器會在編譯階段就能夠幫我們發(fā)現(xiàn)類似這樣的問題。

泛型的使用

泛型的使用有多種方式,下面我們就來一起探討一下。

用泛型表示類

泛型可以加到類上面,來表示這個(gè)類的類型

//此處?T?可以隨便寫為任意標(biāo)識,常見的如T、E、K、V等形式的參數(shù)常用于表示泛型 public?class?GenericDemo<T>{?//value?這個(gè)成員變量的類型為T,T的類型由外部指定??private?T?value;public?GenericDemo(T?value)?{this.value?=?value;}public?T?getValue(){?//泛型方法getKey的返回值類型為T,T的類型由外部指定return?value;}public?void?setValue(T?value){this.value?=?value} }

用泛型表示接口

泛型接口與泛型類的定義及使用基本相同。

//定義一個(gè)泛型接口 public?interface?Generator<T>?{public?T?next(); }

一般泛型接口常用于?生成器(generator)?中,生成器相當(dāng)于對象工廠,是一種專門用來創(chuàng)建對象的類。

泛型方法

可以使用泛型來表示方法

public?class?GenericMethods?{public?<T>?void?f(T?x){System.out.println(x.getClass().getName());} }

泛型通配符

List 是泛型類,為了 表示各種泛型 List 的父類,可以使用類型通配符,類型通配符使用問號(?)表示,它的元素類型可以匹配任何類型。例如

public?static?void?main(String[]?args)?{List<String>?name?=?new?ArrayList<String>();List<Integer>?age?=?new?ArrayList<Integer>();List<Number>?number?=?new?ArrayList<Number>();name.add("cxuan");age.add(18);number.add(314);generic(name);generic(age);generic(number);??? }public?static?void?generic(List<?>?data)?{System.out.println("Test?cxuan?:"?+?data.get(0)); }

上界通配符?: ?<? extends ClassType> 該通配符為 ClassType 的所有子類型。它表示的是任何類型都是 ClassType 類型的子類。

下界通配符:<? super ClassType> 該通配符為 ClassType 的所有超類型。它表示的是任何類型的父類都是 ClassType。

反射

反射是 Java 中一個(gè)非常重要同時(shí)也是一個(gè)高級特性,基本上 Spring 等一系列框架都是基于反射的思想寫成的。我們首先來認(rèn)識一下什么反射。

Java 反射機(jī)制是在程序的運(yùn)行過程中,對于任何一個(gè)類,都能夠知道它的所有屬性和方法;對于任意一個(gè)對象,都能夠知道調(diào)用它的任意屬性和方法,這種動態(tài)獲取信息以及動態(tài)調(diào)用對象方法的功能稱為java語言的反射機(jī)制。(來源于百度百科)

Java 反射機(jī)制主要提供了以下這幾個(gè)功能

  • 在運(yùn)行時(shí)判斷任意一個(gè)對象所屬的類

  • 在運(yùn)行時(shí)構(gòu)造任意一個(gè)類的對象

  • 在運(yùn)行時(shí)判斷任意一個(gè)類所有的成員變量和方法

  • 在運(yùn)行時(shí)調(diào)用任意一個(gè)對象的方法

這么一看,反射就像是一個(gè)掌控全局的角色,不管你程序怎么運(yùn)行,我都能夠知道你這個(gè)類有哪些屬性和方法,你這個(gè)對象是由誰調(diào)用的,嗯,很屌。

在 Java 中,使用?Java.lang.reflect包實(shí)現(xiàn)了反射機(jī)制。Java.lang.reflect 所設(shè)計(jì)的類如下

下面是一個(gè)簡單的反射類

public?class?Person?{public?String?name;//?姓名public?int?age;//?年齡public?Person()?{super();}public?Person(String?name,?int?age)?{super();this.name?=?name;this.age?=?age;}public?String?showInfo()?{return?"name="?+?name?+?",?age="?+?age;} }public?class?Student?extends?Person?implements?Study?{public?String?className;//?班級private?String?address;//?住址public?Student()?{super();}public?Student(String?name,?int?age,?String?className,?String?address)?{super(name,?age);this.className?=?className;this.address?=?address;}public?Student(String?className)?{this.className?=?className;}public?String?toString()?{return?"姓名:"?+?name?+?",年齡:"?+?age?+?",班級:"?+?className?+?",住址:"+?address;}public?String?getAddress()?{return?address;}public?void?setAddress(String?address)?{this.address?=?address;} }public?class?TestRelect?{public?static?void?main(String[]?args)?{Class?student?=?null;try?{student?=?Class.forName("com.cxuan.reflection.Student");}?catch?(ClassNotFoundException?e)?{e.printStackTrace();}//?獲取對象的所有公有屬性。Field[]?fields?=?student.getFields();for?(Field?f?:?fields)?{System.out.println(f);}System.out.println("---------------------");//?獲取對象所有屬性,但不包含繼承的。Field[]?declaredFields?=?student.getDeclaredFields();for?(Field?df?:?declaredFields)?{System.out.println(df);}//?獲取對象的所有公共方法Method[]?methods?=?student.getMethods();for?(Method?m?:?methods)?{System.out.println(m);}System.out.println("---------------------");//?獲取對象所有方法,但不包含繼承的Method[]?declaredMethods?=?student.getDeclaredMethods();for?(Method?dm?:?declaredMethods)?{System.out.println(dm);}//?獲取對象所有的公共構(gòu)造方法Constructor[]?constructors?=?student.getConstructors();for?(Constructor?c?:?constructors)?{System.out.println(c);}System.out.println("---------------------");//?獲取對象所有的構(gòu)造方法Constructor[]?declaredConstructors?=?student.getDeclaredConstructors();for?(Constructor?dc?:?declaredConstructors)?{System.out.println(dc);}Class?c?=?Class.forName("com.cxuan.reflection.Student");Student?stu1?=?(Student)?c.newInstance();//?第一種方法,實(shí)例化默認(rèn)構(gòu)造方法,調(diào)用set賦值stu1.setAddress("河北石家莊");System.out.println(stu1);//?第二種方法?取得全部的構(gòu)造函數(shù)?使用構(gòu)造函數(shù)賦值Constructor<Student>?constructor?=?c.getConstructor(String.class,?int.class,?String.class,?String.class);Student?student2?=?(Student)?constructor.newInstance("cxuan",?24,?"六班",?"石家莊");System.out.println(student2);/***?獲取方法并執(zhí)行方法*/Method?show?=?c.getMethod("showInfo");//獲取showInfo()方法Object?object?=?show.invoke(stu2);//調(diào)用showInfo()方法} }

有一些是比較常用的,有一些是我至今都沒見過怎么用的,下面進(jìn)行一個(gè)歸類。

與 Java 反射有關(guān)的類主要有

Class 類

在 Java 中,你每定義一個(gè) java class 實(shí)體都會產(chǎn)生一個(gè) Class 對象。也就是說,當(dāng)我們編寫一個(gè)類,編譯完成后,在生成的?.class?文件中,就會產(chǎn)生一個(gè) Class 對象,這個(gè) Class 對象用于表示這個(gè)類的類型信息。Class 中沒有公共的構(gòu)造器,也就是說 Class 對象不能被實(shí)例化。下面來簡單看一下 Class 類都包括了哪些方法

toString()

public?String?toString()?{return?(isInterface()???"interface?"?:?(isPrimitive()???""?:?"class?"))+?getName(); }

toString() 方法能夠?qū)ο筠D(zhuǎn)換為字符串,toString() 首先會判斷 Class 類型是否是接口類型,也就是說,普通類和接口都能夠用 Class 對象來表示,然后再判斷是否是基本數(shù)據(jù)類型,這里判斷的都是基本數(shù)據(jù)類型和包裝類,還有?void類型。

所有的類型如下

  • java.lang.Boolean : 代表 boolean 數(shù)據(jù)類型的包裝類

  • java.lang.Character: 代表 char 數(shù)據(jù)類型的包裝類

  • java.lang.Byte: 代表 byte 數(shù)據(jù)類型的包裝類

  • java.lang.Short: 代表 short 數(shù)據(jù)類型的包裝類

  • java.lang.Integer: 代表 int 數(shù)據(jù)類型的包裝類

  • java.lang.Long: 代表 long 數(shù)據(jù)類型的包裝類

  • java.lang.Float: 代表 float 數(shù)據(jù)類型的包裝類

  • java.lang.Double: 代表 double 數(shù)據(jù)類型的包裝類

  • java.lang.Void: 代表 void 數(shù)據(jù)類型的包裝類

然后是?getName()?方法,這個(gè)方法返回類的全限定名稱。

  • 如果是引用類型,比如 String.class.getName() ?->?java.lang.String

  • 如果是基本數(shù)據(jù)類型,byte.class.getName() ->?byte

  • 如果是數(shù)組類型,new Object[3]).getClass().getName() ->?[Ljava.lang.Object

toGenericString()

這個(gè)方法會返回類的全限定名稱,而且包括類的修飾符和類型參數(shù)信息。

forName()

根據(jù)類名獲得一個(gè) Class 對象的引用,這個(gè)方法會使類對象進(jìn)行初始化。

例如?Class t = Class.forName("java.lang.Thread")?就能夠初始化一個(gè) Thread 線程對象

在 Java 中,一共有三種獲取類實(shí)例的方式

  • Class.forName(java.lang.Thread)

  • Thread.class

  • thread.getClass()

newInstance()

創(chuàng)建一個(gè)類的實(shí)例,代表著這個(gè)類的對象。上面 forName() 方法對類進(jìn)行初始化,newInstance 方法對類進(jìn)行實(shí)例化。

getClassLoader()

獲取類加載器對象。

getTypeParameters()

按照聲明的順序獲取對象的參數(shù)類型信息。

getPackage()

返回類的包

getInterfaces()

獲得當(dāng)前類實(shí)現(xiàn)的類或是接口,可能是有多個(gè),所以返回的是 Class 數(shù)組。

Cast

把對象轉(zhuǎn)換成代表類或是接口的對象

asSubclass(Class clazz)

把傳遞的類的對象轉(zhuǎn)換成代表其子類的對象

getClasses()

返回一個(gè)數(shù)組,數(shù)組中包含該類中所有公共類和接口類的對象

getDeclaredClasses()

返回一個(gè)數(shù)組,數(shù)組中包含該類中所有類和接口類的對象

getSimpleName()

獲得類的名字

getFields()

獲得所有公有的屬性對象

getField(String name)

獲得某個(gè)公有的屬性對象

getDeclaredField(String name)

獲得某個(gè)屬性對象

getDeclaredFields()

獲得所有屬性對象

getAnnotation(Class annotationClass)

返回該類中與參數(shù)類型匹配的公有注解對象

getAnnotations()

返回該類所有的公有注解對象

getDeclaredAnnotation(Class annotationClass)

返回該類中與參數(shù)類型匹配的所有注解對象

getDeclaredAnnotations()

返回該類所有的注解對象

getConstructor(Class...<?> parameterTypes)

獲得該類中與參數(shù)類型匹配的公有構(gòu)造方法

getConstructors()

獲得該類的所有公有構(gòu)造方法

getDeclaredConstructor(Class...<?> parameterTypes)

獲得該類中與參數(shù)類型匹配的構(gòu)造方法

getDeclaredConstructors()

獲得該類所有構(gòu)造方法

getMethod(String name, Class...<?> parameterTypes)

獲得該類某個(gè)公有的方法

getMethods()

獲得該類所有公有的方法

getDeclaredMethod(String name, Class...<?> parameterTypes)

獲得該類某個(gè)方法

getDeclaredMethods()

獲得該類所有方法

Field 類

Field 類提供類或接口中單獨(dú)字段的信息,以及對單獨(dú)字段的動態(tài)訪問。

這里就不再對具體的方法進(jìn)行介紹了,讀者有興趣可以參考官方 API

這里只介紹幾個(gè)常用的方法

equals(Object obj)

屬性與obj相等則返回true

get(Object obj)

獲得obj中對應(yīng)的屬性值

set(Object obj, Object value)

設(shè)置obj中對應(yīng)屬性值

Method 類

invoke(Object obj, Object... args)

傳遞object對象及參數(shù)調(diào)用該對象對應(yīng)的方法

ClassLoader 類

反射中,還有一個(gè)非常重要的類就是 ClassLoader 類,類裝載器是用來把類(class)?裝載進(jìn)?JVM的。ClassLoader 使用的是雙親委托模型來搜索加載類的,這個(gè)模型也就是雙親委派模型。ClassLoader 的類繼承圖如下

枚舉

枚舉可能是我們使用次數(shù)比較少的特性,在 Java 中,枚舉使用?enum?關(guān)鍵字來表示,枚舉其實(shí)是一項(xiàng)非常有用的特性,你可以把它理解為具有特定性質(zhì)的類。enum 不僅僅 Java 有,C 和 C++ 也有枚舉的概念。下面是一個(gè)枚舉的例子。

public?enum?Family?{FATHER,MOTHER,SON,Daughter;}

上面我們創(chuàng)建了一個(gè)?Family的枚舉類,它具有 4 個(gè)值,由于枚舉類型都是常量,所以都用大寫字母來表示。那么 enum 創(chuàng)建出來了,該如何引用呢?

public?class?EnumUse?{public?static?void?main(String[]?args)?{Family?s?=?Family.FATHER;} }

枚舉特性

enum 枚舉這個(gè)類比較有意思,當(dāng)你創(chuàng)建完 enum 后,編譯器會自動為你的 enum 添加?toString()?方法,能夠讓你方便的顯示 enum 實(shí)例的具體名字是什么。除了 toString() 方法外,編譯器還會添加?ordinal()?方法,這個(gè)方法用來表示 enum 常量的聲明順序,以及?values()?方法顯示順序的值。

public?static?void?main(String[]?args)?{for(Family?family?:?Family.values()){System.out.println(family?+?",?ordinal"?+?family.ordinal());} }

enum 可以進(jìn)行靜態(tài)導(dǎo)入包,靜態(tài)導(dǎo)入包可以做到不用輸入?枚舉類名.常量,可以直接使用常量,神奇嗎? 使用 ennum 和?static?關(guān)鍵字可以做到靜態(tài)導(dǎo)入包

上面代碼導(dǎo)入的是 Family 中所有的常量,也可以單獨(dú)指定常量。

枚舉和普通類一樣

枚舉就和普通類一樣,除了枚舉中能夠方便快捷的定義常量,我們?nèi)粘i_發(fā)使用的?public static final xxx?其實(shí)都可以用枚舉來定義。在枚舉中也能夠定義屬性和方法,千萬不要把它看作是異類,它和萬千的類一樣。

public?enum?OrdinalEnum?{WEST("live?in?west"),EAST("live?in?east"),SOUTH("live?in?south"),NORTH("live?in?north");String?description;OrdinalEnum(String?description){this.description?=?description;}public?String?getDescription()?{return?description;}public?void?setDescription(String?description)?{this.description?=?description;}public?static?void?main(String[]?args)?{for(OrdinalEnum?ordinalEnum?:?OrdinalEnum.values()){System.out.println(ordinalEnum.getDescription());}} }

一般 switch 可以和 enum 一起連用,來構(gòu)造一個(gè)小型的狀態(tài)轉(zhuǎn)換機(jī)。

enum?Signal?{GREEN,?YELLOW,?RED }public?class?TrafficLight?{Signal?color?=?Signal.RED;public?void?change()?{switch?(color)?{case?RED:color?=?Signal.GREEN;break;case?YELLOW:color?=?Signal.RED;break;case?GREEN:color?=?Signal.YELLOW;break;}} }

是不是代碼頓時(shí)覺得優(yōu)雅整潔了些許呢?

枚舉神秘之處

在 Java 中,萬事萬物都是對象,enum 雖然是個(gè)關(guān)鍵字,但是它卻隱式的繼承于?Enum?類。我們來看一下 Enum 類,此類位于?java.lang?包下,可以自動引用。

此類的屬性和方法都比較少。你會發(fā)現(xiàn)這個(gè)類中沒有我們的 values 方法。前面剛說到,values()?方法是你使用枚舉時(shí)被編譯器添加進(jìn)來的 static 方法。可以使用反射來驗(yàn)證一下

除此之外,enum 還和 Class 類有交集,在 Class 類中有三個(gè)關(guān)于 Enum 的方法

前面兩個(gè)方法用于獲取 enum 常量,isEnum?用于判斷是否是枚舉類型的。

枚舉類

除了 Enum 外,還需要知道兩個(gè)關(guān)于枚舉的工具類,一個(gè)是?EnumSet?,一個(gè)是?EnumMap

EnumSet 和 EnumMap

EnumSet 是 JDK1.5 引入的,EnumSet 的設(shè)計(jì)充分考慮到了速度因素,使用 EnumSet 可以作為 Enum 的替代者,因?yàn)樗男时容^高。

EnumMap 是一種特殊的 Map,它要求其中的 key 鍵值是來自一個(gè) enum。因?yàn)?EnumMap 速度也很快,我們可以使用 EnumMap 作為 key 的快速查找。

總的來說,枚舉的使用不是很復(fù)雜,它也是 Java 中很小的一塊功能,但有時(shí)卻能夠因?yàn)檫@一個(gè)小技巧,能夠讓你的代碼變得優(yōu)雅和整潔。

I/O

創(chuàng)建一個(gè)良好的 I/O 程序是非常復(fù)雜的。JDK 開發(fā)人員編寫了大量的類只為了能夠創(chuàng)建一個(gè)良好的工具包,想必編寫 I/O 工具包很費(fèi)勁吧。

IO 類設(shè)計(jì)出來,肯定是為了解決 IO 相關(guān)操作的,最常見的 I/O 讀寫就是網(wǎng)絡(luò)、磁盤等。在 Java 中,對文件的操作是一個(gè)典型的 I/O 操作。下面我們就對 I/O 進(jìn)行一個(gè)分類。

公號回復(fù)?IO獲取思維導(dǎo)圖

I/O 還可以根據(jù)操作對象來進(jìn)行區(qū)分:主要分為

除此之外,I/O 中還有其他比較重要的類

File 類

File 類是對文件系統(tǒng)中文件以及文件夾進(jìn)行操作的類,可以通過面向?qū)ο蟮乃枷氩僮魑募臀募A,是不是很神奇?

文件創(chuàng)建操作如下,主要涉及?文件創(chuàng)建、刪除文件、獲取文件描述符等

class?FileDemo{public?static?void?main(String[]?args)?{File?file?=?new?File("D:\\file.txt");try{f.createNewFile();?//?創(chuàng)建一個(gè)文件//?File類的兩個(gè)常量//路徑分隔符(與系統(tǒng)有關(guān)的)<windows里面是?; linux里面是?:?>System.out.println(File.pathSeparator);??//???;//與系統(tǒng)有關(guān)的路徑名稱分隔符<windows里面是?\?linux里面是/?>System.out.println(File.separator);??????//??\//?刪除文件/*File?file?=?new?File(fileName);if(f.exists()){f.delete();}else{System.out.println("文件不存在");}???*/}catch?(Exception?e)?{e.printStackTrace();}} }

也可以對文件夾進(jìn)行操作

class?FileDemo{public?static?void?main(String[]?args)?{String?fileName?=?"D:"+?File.separator?+?"filepackage";File?file?=?new?File(fileName);f.mkdir();//?列出所有文件/*String[]?str?=?file.list();for?(int?i?=?0;?i?<?str.length;?i++)?{System.out.println(str[i]);}*///?使用?file.listFiles();?列出所有文件,包括隱藏文件//?使用?file.isDirectory()?判斷指定路徑是否是目錄} }

上面只是舉出來了兩個(gè)簡單的示例,實(shí)際上,還有一些其他對文件的操作沒有使用。比如創(chuàng)建文件,就可以使用三種方式來創(chuàng)建

File(String?directoryPath); File(String?directoryPath,?String?filename); File(File?dirObj,?String?filename);

directoryPath 是文件的路徑名,filename 是文件名,dirObj 是一個(gè) File 對象。例如

File?file?=?new?File("D:\\java\\file1.txt");??//雙\\是轉(zhuǎn)義 System.out.println(file); File?file2?=?new?File("D:\\java","file2.txt");//父路徑、子路徑--可以適用于多個(gè)文件的! System.out.println(file2); File?parent?=?new?File("D:\\java"); File?file3?=?new?File(parent,"file3.txt");//File類的父路徑、子路徑 System.out.println(file3);

現(xiàn)在對 File 類進(jìn)行總結(jié)

基礎(chǔ) IO 類和相關(guān)方法

雖然. IO 類有很多,但是最基本的是四個(gè)抽象類,InputStream、OutputStream、Reader、Writer。最基本的方法也就是?read()?和?write()?方法,其他流都是上面這四類流的子類,方法也是通過這兩類方法衍生而成的。而且大部分的 IO 源碼都是?native?標(biāo)志的,也就是說源碼都是 C/C++ 寫的。這里我們先來認(rèn)識一下這些流類及其方法

InputStream

InputStream 是一個(gè)定義了 Java 流式字節(jié)輸入模式的抽象類。該類的所有方法在出錯條件下引發(fā)一個(gè)IOException 異常。它的主要方法定義如下

OutputStream

OutputStream 是定義了流式字節(jié)輸出模式的抽象類。該類的所有方法返回一個(gè)void 值并且在出錯情況下引發(fā)一個(gè)IOException異常。它的主要方法定義如下

Reader 類

Reader 是 Java 定義的流式字符輸入模式的抽象類。類中的方法在出錯時(shí)引發(fā)?IOException?異常。

Writer 類

Writer 是定義流式字符輸出的抽象類。所有該類的方法都返回一個(gè) void 值并在出錯條件下引發(fā) IOException 異常

InputStream 及其子類

FileInputStream 文件輸入流:FileInputStream 類創(chuàng)建一個(gè)能從文件讀取字節(jié)的 InputStream 類

ByteArrayInputStream 字節(jié)數(shù)組輸入流?:把內(nèi)存中的一個(gè)緩沖區(qū)作為 InputStream 使用

PipedInputStream 管道輸入流:實(shí)現(xiàn)了pipe 管道的概念,主要在線程中使用

SequenceInputStream 順序輸入流:把多個(gè) InputStream 合并為一個(gè) InputStream

FilterOutputStream 過濾輸入流:其他輸入流的包裝。

ObjectInputStream 反序列化輸入流?:將之前使用 ObjectOutputStream 序列化的原始數(shù)據(jù)恢復(fù)為對象,以流的方式讀取對象

**DataInputStream ** : 數(shù)據(jù)輸入流允許應(yīng)用程序以與機(jī)器無關(guān)方式從底層輸入流中讀取基本 Java 數(shù)據(jù)類型。

PushbackInputStream 推回輸入流:緩沖的一個(gè)新穎的用法是實(shí)現(xiàn)推回 (pushback)?。Pushback 用于輸入流允許字節(jié)被讀取然后返回到流。

OutputStream 及其子類

FileOutputStream 文件輸出流:該類實(shí)現(xiàn)了一個(gè)輸出流,其數(shù)據(jù)寫入文件。

ByteArrayOutputStream 字節(jié)數(shù)組輸出流?:該類實(shí)現(xiàn)了一個(gè)輸出流,其數(shù)據(jù)被寫入由 byte 數(shù)組充當(dāng)?shù)木彌_區(qū),緩沖區(qū)會隨著數(shù)據(jù)的不斷寫入而自動增長。

PipedOutputStream 管道輸出流?:管道的輸出流,是管道的發(fā)送端。

ObjectOutputStream 基本類型輸出流??:該類將實(shí)現(xiàn)了序列化的對象序列化后寫入指定地方。

FilterOutputStream 過濾輸出流:其他輸出流的包裝。

PrintStream 打印流?通過 PrintStream 可以將文字打印到文件或者網(wǎng)絡(luò)中去。

DataOutputStream?: 數(shù)據(jù)輸出流允許應(yīng)用程序以與機(jī)器無關(guān)方式向底層輸出流中寫入基本 Java 數(shù)據(jù)類型。

Reader 及其子類

FileReader 文件字符輸入流?:把文件轉(zhuǎn)換為字符流讀入

CharArrayReader 字符數(shù)組輸入流?:是一個(gè)把字符數(shù)組作為源的輸入流的實(shí)現(xiàn)

BufferedReader 緩沖區(qū)輸入流?:BufferedReader 類從字符輸入流中讀取文本并緩沖字符,以便有效地讀取字符,數(shù)組和行

PushbackReader: PushbackReader 類允許一個(gè)或多個(gè)字符被送回輸入流。

PipedReader 管道輸入流:主要用途也是在線程間通訊,不過這個(gè)可以用來傳輸字符

Writer 及其子類

FileWriter 字符輸出流?:FileWriter 創(chuàng)建一個(gè)可以寫文件的 Writer 類。

CharArrayWriter 字符數(shù)組輸出流:CharArrayWriter 實(shí)現(xiàn)了以數(shù)組作為目標(biāo)的輸出流。

BufferedWriter 緩沖區(qū)輸出流?:BufferedWriter是一個(gè)增加了flush( )?方法的Writer。flush( )方法可以用來確保數(shù)據(jù)緩沖器確實(shí)被寫到實(shí)際的輸出流。

PrintWriter?:PrintWriter 本質(zhì)上是 PrintStream 的字符形式的版本。

PipedWriter 管道輸出流:主要用途也是在線程間通訊,不過這個(gè)可以用來傳輸字符

Java 的輸入輸出的流式接口為復(fù)雜而繁重的任務(wù)提供了一個(gè)簡潔的抽象。過濾流類的組合允許你動態(tài)建立客戶端流式接口來配合數(shù)據(jù)傳輸要求。繼承高級流類 InputStream、InputStreamReader、 Reader 和 Writer 類的 Java 程序在將來 (即使創(chuàng)建了新的和改進(jìn)的具體類)也能得到合理運(yùn)用。

注解

Java?注解(Annotation)?又稱為元數(shù)據(jù)?,它為我們在代碼中添加信息提供了一種形式化的方法。它是 JDK1.5 引入的,Java 定義了一套注解,共有 7 個(gè),3 個(gè)在?java.lang?中,剩下 4 個(gè)在?java.lang.annotation?中。

作用在代碼中的注解有三個(gè),它們分別是

  • @Override:重寫標(biāo)記,一般用在子類繼承父類后,標(biāo)注在重寫過后的子類方法上。如果發(fā)現(xiàn)其父類,或者是引用的接口中并沒有該方法時(shí),會報(bào)編譯錯誤。

  • @Deprecated?:用此注解注釋的代碼已經(jīng)過時(shí),不再推薦使用

  • @SuppressWarnings:這個(gè)注解起到忽略編譯器的警告作用

元注解有四個(gè),元注解就是用來標(biāo)志注解的注解。它們分別是

  • @Retention: 標(biāo)識如何存儲,是只在代碼中,還是編入class文件中,或者是在運(yùn)行時(shí)可以通過反射訪問。

RetentionPolicy.SOURCE:注解只保留在源文件,當(dāng) Java 文件編譯成class文件的時(shí)候,注解被遺棄;

RetentionPolicy.CLASS:注解被保留到 class 文件,但 jvm 加載 class 文件時(shí)候被遺棄,這是默認(rèn)的生命周期;

RetentionPolicy.RUNTIME:注解不僅被保存到 class 文件中,jvm 加載 class 文件之后,仍然存在;

  • @Documented: 標(biāo)記這些注解是否包含在 JavaDoc 中。

  • @Target:標(biāo)記這個(gè)注解說明了 Annotation 所修飾的對象范圍,Annotation 可被用于 packages、types(類、接口、枚舉、Annotation類型)、類型成員(方法、構(gòu)造方法、成員變量、枚舉值)、方法參數(shù)和本地變量(如循環(huán)變量、catch參數(shù))。取值如下

public?enum?ElementType?{TYPE,FIELD,METHOD,PARAMETER,CONSTRUCTOR,LOCAL_VARIABLE,ANNOTATION_TYPE,PACKAGE,TYPE_PARAMETER,TYPE_USE
  • @Inherited?:標(biāo)記這個(gè)注解是繼承于哪個(gè)注解類的。

從 JDK1.7 開始,又添加了三個(gè)額外的注解,它們分別是

  • @SafeVarargs?:在聲明可變參數(shù)的構(gòu)造函數(shù)或方法時(shí),Java 編譯器會報(bào) unchecked 警告。使用 @SafeVarargs 可以忽略這些警告

  • @FunctionalInterface: 表明這個(gè)方法是一個(gè)函數(shù)式接口

  • @Repeatable:標(biāo)識某注解可以在同一個(gè)聲明上使用多次。

注意:注解是不支持繼承的。

關(guān)于 null 的幾種處理方式

對于 Java 程序員來說,空指針一直是惱人的問題,我們在開發(fā)中經(jīng)常會受到 NullPointerException 的蹂躪和壁咚。Java 的發(fā)明者也承認(rèn)這是一個(gè)巨大的設(shè)計(jì)錯誤。

那么關(guān)于 null ,你應(yīng)該知道下面這幾件事情來有效的了解 null ,從而避免很多由 null 引起的錯誤。

null 是大小寫敏感

首先,null 是 Java 中的關(guān)鍵字,像是 public、static、final。它是大小寫敏感的,你不能將 null 寫成 Null 或 NULL,編輯器將不能識別它們?nèi)缓髨?bào)錯。

這個(gè)問題已經(jīng)幾乎不會出現(xiàn),因?yàn)?eclipse 和 Idea 編譯器已經(jīng)給出了編譯器提示,所以你不用考慮這個(gè)問題。

null 是任何引用類型的初始值

null 是所有引用類型的默認(rèn)值,Java 中的任何引用變量都將null作為默認(rèn)值,也就是說所有 Object 類下的引用類型默認(rèn)值都是 null。這對所有的引用變量都適用。就像是基本類型的默認(rèn)值一樣,例如 int 的默認(rèn)值是 0,boolean 的默認(rèn)值是 false。

下面是基本數(shù)據(jù)類型的初始值

null 只是一種特殊的值

null 既不是對象也不是一種類型,它僅是一種特殊的值,你可以將它賦予任何類型,你可以將 null 轉(zhuǎn)換為任何類型

public?static?void?main(String[]?args)?{String?str?=?null;Integer?itr?=?null;Double?dou?=?null;Integer?integer?=?(Integer)?null;String?string?=?(String)null;System.out.println("integer?=?"?+?integer);System.out.println("string?=?"?+?string); }

你可以看到在編譯期和運(yùn)行期內(nèi),將 null 轉(zhuǎn)換成任何的引用類型都是可行的,并且不會拋出空指針異常。

null 只能賦值給引用變量,不能賦值給基本類型變量

持有 null 的包裝類在進(jìn)行自動拆箱的時(shí)候,不能完成轉(zhuǎn)換,會拋出空指針異常,并且 null 也不能和基本數(shù)據(jù)類型進(jìn)行對比

public?static?void?main(String[]?args)?{int?i?=?0;Integer?itr?=?null;System.out.println(itr?==?i); }

使用了帶有 null 值的引用類型變量,instanceof?操作會返回 false

public?static?void?main(String[]?args)?{Integer?isNull?=?null;//?instanceof?=?isInstance?方法if(isNull?instanceof?Integer){System.out.println("isNull?is?instanceof?Integer");}else{System.out.println("isNull?is?not?instanceof?Integer");} }

這是 instanceof 操作符一個(gè)很重要的特性,使得對類型強(qiáng)制轉(zhuǎn)換檢查很有用

靜態(tài)變量為 null 調(diào)用靜態(tài)方法不會拋出 NullPointerException。因?yàn)殪o態(tài)方法使用了靜態(tài)綁定

使用 Null-Safe 方法

你應(yīng)該使用 null-safe 安全的方法,java 類庫中有很多工具類都提供了靜態(tài)方法,例如基本數(shù)據(jù)類型的包裝類,Integer , Double 等。例如

public?class?NullSafeMethod?{private?static?String?number;public?static?void?main(String[]?args)?{String?s?=?String.valueOf(number);String?string?=?number.toString();System.out.println("s?=?"?+?s);System.out.println("string?=?"?+?string);} }

number 沒有賦值,所以默認(rèn)為null,使用String.value(number)?靜態(tài)方法沒有拋出空指針異常,但是使用?toString()卻拋出了空指針異常。所以盡量使用對象的靜態(tài)方法。

null 判斷

你可以使用?==?或者?!=?操作來比較 null 值,但是不能使用其他算法或者邏輯操作,例如小于或者大于。跟SQL不一樣,在Java中 null == null 將返回 true,如下所示:

public?class?CompareNull?{private?static?String?str1;private?static?String?str2;public?static?void?main(String[]?args)?{System.out.println("str1?==?str2???"?+?str1?==?str2);System.out.println(null?==?null);} }

關(guān)于思維導(dǎo)圖

我把一些常用的 Java 工具包的思維導(dǎo)圖做了匯總,方便讀者查閱。

Java.IO

Java.lang

Java.math

Java.net

?

《新程序員》:云原生和全面數(shù)字化實(shí)踐50位技術(shù)專家共同創(chuàng)作,文字、視頻、音頻交互閱讀

總結(jié)

以上是生活随笔為你收集整理的我肝了一个月,给你写出了这本Java开发手册。的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。

成人av午夜 | 久久久久免费精品国产小说色大师 | 欧美一级片免费在线观看 | 国产精品区免费视频 | av先锋中文字幕 | 在线影院中文字幕 | 91成年人在线观看 | 久久国语露脸国产精品电影 | 五月婷婷一区 | 久久久久观看 | 中文字幕在线免费看线人 | 在线中文字幕网站 | 中文字幕观看在线 | av综合站 | 国产91对白在线播 | 亚洲精选视频免费看 | 天天综合日 | 99久久99精品 | 成人免费网站视频 | 精品国产午夜 | 六月激情网 | 99 精品 在线| 婷婷四房综合激情五月 | 少妇资源站| 亚洲高清视频在线观看免费 | 99热在线精品观看 | 欧美成人久久 | 天天做夜夜做 | 国产精品成人免费一区久久羞羞 | 亚洲视屏| 日本久久久久久 | 国产一级电影网 | 国产h在线观看 | 在线91精品 | 综合色狠狠 | 日韩一区二区免费播放 | 亚洲高清av在线 | 久久久国产精品久久久 | 久草在线视频资源 | 国产精品完整版 | 国产精品门事件 | 人人澡人人添人人爽一区二区 | 成人高清av在线 | 91网址在线观看 | 久久桃花网 | 久久免费国产电影 | 久久精品99国产国产精 | 国产看片网站 | 国产免费久久久久 | 成人欧美一区二区三区在线观看 | 亚洲国产97在线精品一区 | 在线观看视频免费播放 | 欧美在线观看视频一区二区三区 | 国产在线中文 | 亚洲 综合 国产 精品 | 91精品视频导航 | 99视频在线免费看 | 欧美激情综合五月色丁香 | 在线播放 亚洲 | 久久久久久国产精品亚洲78 | 在线精品在线 | 欧美一区日韩一区 | 亚洲一级特黄 | 最新国产一区二区三区 | 久久精品亚洲一区二区三区观看模式 | 中文字幕在线成人 | 日韩一级电影在线观看 | 免费观看一区二区三区视频 | a在线观看视频 | 免费观看十分钟 | www.激情五月.com | 久久综合久久综合这里只有精品 | 国产美女网站视频 | 黄色在线观看免费网站 | 国产裸体视频bbbbb | 最近更新好看的中文字幕 | 久久久综合九色合综国产精品 | 欧美天天综合 | 亚洲视频电影在线 | 91九色视频观看 | 国产91精品一区二区麻豆亚洲 | 美州a亚洲一视本频v色道 | 免费观看v片在线观看 | 成人三级网站在线观看 | 色综合久久88色综合天天免费 | 久久久午夜精品福利内容 | 波多野结衣理论片 | www最近高清中文国语在线观看 | 亚洲国产精品人久久电影 | 狠狠色丁香婷婷综合橹88 | 久草视频在线播放 | 在线国产一区二区 | 91免费版成人 | 久久免费99 | 成人网在线免费视频 | 狠狠色噜噜狠狠狠狠 | 岛国精品一区二区 | av解说在线观看 | 天天激情综合网 | 久久久久久久久久电影 | 国产流白浆高潮在线观看 | 久草在线手机视频 | 免费日韩一区二区三区 | 午夜在线国产 | 99理论片| 亚洲一区免费在线 | 中文字幕乱码在线播放 | 久久久久这里只有精品 | 欧美在线视频一区二区三区 | 婷婷久操 | 欧美日韩亚洲在线 | 中文字幕在线不卡国产视频 | 黄网站色成年免费观看 | 插婷婷| 天天色 天天| 81国产精品久久久久久久久久 | 欧美一级裸体视频 | 国产精品一区电影 | 久久国产精品视频 | 亚洲波多野结衣 | 天天人人综合 | 日韩成人免费在线观看 | 久久综合网色—综合色88 | 黄色成人av在线 | 国际精品久久久 | 欧美大片www| 天天干天天干天天干天天干天天干天天干 | 五月开心色 | 91av美女| 激情欧美丁香 | av资源在线看 | 午夜免费在线观看 | 日韩毛片精品 | 黄色av电影免费观看 | 国产精品亚洲成人 | 美女av在线免费 | 伊人狠狠色丁香婷婷综合 | 麻豆久久久久 | 国产黄影院色大全免费 | 久久久九色精品国产一区二区三区 | 国产精品18久久久久久久网站 | 免费在线观看国产黄 | 久久国产美女 | 久久女教师 | 久久精品小视频 | 国产精彩视频一区二区 | 国产精品99久久久久的智能播放 | 免费在线观看av的网站 | 探花视频在线观看免费 | 日韩欧美在线综合网 | 日本精品视频一区 | 91精品国产99久久久久久红楼 | 国产人成在线观看 | 久久久久国产一区二区三区 | 区一区二区三区中文字幕 | 在线看片91 | 国产精品美女网站 | 亚洲精品高清视频在线观看 | 一级一片免费看 | 丁香网五月天 | 亚洲一级片av | 久草在线视频国产 | av夜夜操| 国产在线观看你懂的 | 色欧美88888久久久久久影院 | 色综合天天色综合 | 色在线最新 | 中文av网 | 国产日本亚洲高清 | 91亚洲精 | 91传媒在线播放 | www.在线观看av | 色狠狠一区二区 | 黄污视频网站大全 | 国产精品99久久久精品免费观看 | 五月天激情在线 | 亚洲一区二区三区四区在线视频 | 天堂入口网站 | 中文字幕在线专区 | 久久久久 免费视频 | 狠狠色综合网站久久久久久久 | 黄色网址中文字幕 | 视频成人永久免费视频 | 在线中文字母电影观看 | 国产精品免费观看视频 | 中文字幕a在线 | 国产免费美女 | av免费网站在线观看 | 99国产在线观看 | 激情欧美一区二区三区免费看 | 在线国产专区 | 久久r精品 | 99婷婷 | 久久久久久久久毛片 | 91精选 | 精品国产免费av | 精品国产一区二区三区在线 | 又黄又刺激又爽的视频 | 狠狠躁夜夜躁人人爽超碰97香蕉 | 四虎成人免费观看 | 狠狠做六月爱婷婷综合aⅴ 日本高清免费中文字幕 | 在线观看91精品国产网站 | 欧美成a人片在线观看久 | 国产九色91| 国产香蕉久久精品综合网 | 最近久乱中文字幕 | 亚洲精品视频偷拍 | 欧女人精69xxxxxx | 日韩欧美在线不卡 | 国产手机视频在线观看 | 麻豆视频免费 | 日韩免费久久 | 国产精选在线观看 | 国产精品网站 | 人交video另类hd | 97电影网站| 91免费在线 | 中文字幕专区高清在线观看 | 日韩欧美精品在线 | 日日干天天爽 | 国产精品视频不卡 | 成人在线观看你懂的 | 日本中文字幕在线观看 | 成人午夜剧场在线观看 | 青春草国产视频 | 81精品国产乱码久久久久久 | 亚洲粉嫩av | 娇妻呻吟一区二区三区 | 精品嫩模福利一区二区蜜臀 | 免费午夜在线视频 | 国产精品18久久久久久首页狼 | 黄色在线成人 | 成人午夜影院在线观看 | 中文字幕一区二区三区久久 | 午夜精品福利影院 | 久久久久久国产精品免费 | 中文字幕国产一区二区 | 欧美一级看片 | 精品亚洲视频在线 | 国内精品久久天天躁人人爽 | 人人爽人人香蕉 | 日韩精品在线看 | 97操碰| 免费在线观看日韩视频 | 日韩欧美一区二区在线播放 | 嫩草91影院| 久久视频免费在线观看 | 伊人五月天.com | 91福利视频一区 | 国产精品一区二区av影院萌芽 | 九月婷婷综合网 | 婷色| 日韩成人精品在线观看 | 色com网 | 亚洲黄网站 | 成人av电影免费在线观看 | 六月丁香激情综合色啪小说 | 日韩免费网址 | 亚洲欧洲美洲av | 久久精品一区二区三 | 97天天综合网 | 亚洲欧美国产精品 | 欧美精品999 | 天天综合色天天综合 | 五月的婷婷| 狠狠色狠狠色终合网 | 激情视频国产 | 亚洲免费精品一区二区 | 久久av一区二区三区亚洲 | 亚洲精品1234区 | 国产高清视频在线播放 | 极品国产91在线网站 | 天天操天天干天天摸 | 精品综合久久久 | 久久久婷| 成人av电影免费观看 | 99视频+国产日韩欧美 | 肉色欧美久久久久久久免费看 | 狠狠干夜夜操天天爽 | 欧美久草视频 | 在线观看日本高清mv视频 | www.国产精品 | 国产资源免费 | 中文有码在线视频 | 日韩欧美综合视频 | 久久综合在线 | 人人看人人做人人澡 | 午夜精品久久久久久久久久久久久久 | 视频福利在线 | 免费视频在线观看网站 | 99精品国产视频 | 亚洲欧美日韩不卡 | 18av在线视频 | 久久久久久久久久影视 | 69人人| 97精品国产一二三产区 | 日韩区在线观看 | 99视频在线观看一区三区 | 免费av网址大全 | 久久九九影视 | 久草在线免费播放 | 国产又粗又猛又黄又爽视频 | 亚洲激情六月 | 一区二区三区精品在线视频 | 天天操天天干天天爽 | 最近免费中文字幕mv在线视频3 | 一区二区三区免费在线播放 | 久久久久久久国产精品视频 | 免费在线观看黄色网 | 福利网址在线观看 | 日韩高清在线不卡 | 精品日韩中文字幕 | 成人在线视 | av在线等| 麻豆一区在线观看 | 日韩大片在线看 | 婷婷九九 | 亚洲精品一区二区在线观看 | 久草观看| 国产中文字幕视频在线 | 亚洲欧美日韩在线一区二区 | 日韩亚洲欧美中文字幕 | 亚洲国产精品资源 | 天天干,天天射,天天操,天天摸 | 日韩有码专区 | 国产一区二区三区在线 | 亚洲国产日韩在线 | avove黑丝 | 国产日韩视频在线 | 五月天堂色 | 91精品区| 国模精品一区二区三区 | av中文字幕在线免费观看 | 国产免费二区 | 国内精品美女在线观看 | 亚洲精品中文字幕视频 | 91日本在线播放 | 久久美女电影 | 久久黄网站 | 亚洲涩涩一区 | 久久久九九 | 久久久久一区二区三区 | 美女视频黄免费的久久 | 国产中年夫妇高潮精品视频 | 免费国产黄线在线观看视频 | 中文字幕在线观看视频一区二区三区 | 中文字幕成人网 | 日韩免费一区二区 | 一区二区三区视频 | 成人免费一区二区三区在线观看 | 久久综合电影 | 超碰在线观看97 | 一区二区三区四区精品视频 | 99理论片 | 亚洲国产精品女人久久久 | 日本在线观看黄色 | 91成人免费在线 | 成人久久综合 | 在线观看国产区 | 免费看片网址 | 日韩电影一区二区在线观看 | 黄色特一级 | 免费国产黄线在线观看视频 | 国产色视频网站 | 久久久久久久久久久电影 | 99久e精品热线免费 99国产精品久久久久久久久久 | 国产91精品高清一区二区三区 | 国产精品久久久av | 成人av一区二区三区 | 午夜精品一二三区 | 国产不卡免费视频 | 99精品乱码国产在线观看 | 亚洲精品久久久久久久不卡四虎 | 伊人手机在线 | 午夜视频黄 | 欧美日韩在线第一页 | 香蕉视频在线播放 | 日韩午夜在线播放 | 亚洲久草在线 | 久久综合亚洲鲁鲁五月久久 | 特级黄录像视频 | 日韩网站中文字幕 | 999久久| 久久久www成人免费毛片麻豆 | 亚洲一区二区三区91 | 91香蕉视频 mp4 | 免费在线观看污 | 99久久er热在这里只有精品66 | 欧美 日韩 国产 中文字幕 | 中文超碰字幕 | 日批视频在线 | 精品国产一区二区三区蜜臀 | 色婷婷激婷婷情综天天 | 国语精品免费视频 | 亚洲欧洲国产日韩精品 | 在线小视频你懂的 | 波多野结衣在线视频免费观看 | 欧美日韩视频在线观看免费 | 午夜精品视频在线 | 午夜精品视频一区 | 国产精品视频你懂的 | 亚洲黄a | 涩涩资源网 | 欧美日韩1区| 国产成人免费在线观看 | 久草在线手机视频 | 午夜国产福利在线观看 | 在线免费观看黄网站 | 国产这里只有精品 | 国产99久久久国产 | 一级a性色生活片久久毛片波多野 | 91伊人久久大香线蕉蜜芽人口 | 亚洲男女精品 | 国产一区免费观看 | 日韩啪啪小视频 | 久久9精品| 色网站在线免费 | 99久久这里有精品 | 激情久久婷婷 | a天堂免费| 日韩精品一区二区三区高清免费 | 四虎国产精品免费 | 国产精品自拍在线 | 国产精品一区二区三区在线播放 | 在线观看日韩精品 | 久久久久亚洲精品中文字幕 | 亚洲精品中文字幕视频 | 天天操天天干天天干 | 婷婷久久综合九色综合 | 精品视频免费观看 | 国产精品久久久久久久久久久久久久 | 久久国产一区二区三区 | 国产做爰视频 | 久久精品久久久久久久 | 色在线观看网站 | 日韩精品中文字幕在线观看 | 欧美精品在线一区 | 日韩v欧美v日本v亚洲v国产v | 色综合久久悠悠 | 国产成人精品一区二区三区在线观看 | 国产一级在线免费观看 | 在线国产日本 | 久久伦理电影网 | 国产精品96久久久久久吹潮 | 成人免费亚洲 | 亚洲小视频在线 | 最新av免费在线观看 | 久久激情视频免费观看 | 亚洲精品美女在线 | 视频国产在线 | aaa亚洲精品一二三区 | 国产精品黄色影片导航在线观看 | 一区二精品 | 色在线免费观看 | 亚洲综合网 | 欧美激情视频免费看 | 亚洲综合色激情五月 | 久久精品久久久久 | 免费影视大全推荐 | 久久久国产精品视频 | 黄免费在线观看 | 日韩精品三区四区 | 91精品国产九九九久久久亚洲 | 欧美精品首页 | 国产精品久久久久久爽爽爽 | 在线成人免费av | 久久成视频 | 中文视频在线看 | 最近中文字幕完整视频高清1 | 国产伦精品一区二区三区… | 久久久91精品国产一区二区三区 | 久久一区二区三区四区 | 伊人色综合久久天天 | 丝袜美腿在线视频 | www在线观看视频 | 亚洲欧美日韩国产 | 五月婷婷黄色网 | av中文字幕网 | 欧美九九九 | 久久99久久99精品免视看婷婷 | 日本中文一区二区 | 黄色精品一区 | 国产欧美高清 | 日韩高清国产精品 | 日韩视频三区 | 国产成年人av | 亚洲午夜精品福利 | 国产精品一区二区免费 | 久久a国产| 不卡中文字幕av | 国产视频丨精品|在线观看 国产精品久久久久久久久久久久午夜 | 欧美综合色在线图区 | 婷婷深爱网 | 99re久久精品国产 | 黄色av电影在线观看 | 国产福利精品一区二区 | 精品一区 在线 | 亚洲成人av在线 | 免费观看www7722午夜电影 | 久草视频在线观 | 久久综合久久久 | 日韩美在线 | 日日操夜 | 日韩一级电影在线观看 | 天天操欧美 | 婷婷色网视频在线播放 | 日韩成人精品一区二区三区 | 中文伊人 | 久久综合免费视频影院 | 久久精品国产亚洲精品 | 亚洲爽爽网 | 国产 一区二区三区 在线 | 成人av.com | 国产最新91 | 九九九热精品免费视频观看 | 国产一区 在线播放 | 在线一二三区 | 日韩欧美aaa | 97电影院在线观看 | 国产精品嫩草在线 | 久久精品久久精品久久精品 | 久久九九影院 | 国产精品午夜久久久久久99热 | 久久久久国产免费免费 | 午夜精品久久久久久久99 | 日韩精品中文字幕在线观看 | 久久66热这里只有精品 | 久久成人国产精品免费软件 | 操久久网| 一本一本久久a久久精品牛牛影视 | 97超碰国产精品女人人人爽 | 91亚洲精品国偷拍 | 精品久久久久久亚洲综合网站 | 成人超碰在线 | 伊人资源视频在线 | 亚洲免费a | 日日爽日日操 | 国产一级片不卡 | 亚洲精品国产精品乱码在线观看 | 一 级 黄 色 片免费看的 | 天天干天天拍天天操天天拍 | 免费激情在线电影 | 天天干,夜夜爽 | 色婷婷www | 久久久免费在线观看 | www.com久久久 | 免费观看性生活大片3 | 五月婷婷电影网 | 在线观看视频精品 | 午夜精品久久久久99热app | 国产 在线观看 | 久久久午夜电影 | 综合伊人av| 蜜桃av综合网 | 欧美精彩视频 | 色综合天天做天天爱 | 97超碰总站| 六月丁香六月婷婷 | 国产精品久久久999 国产91九色视频 | 久久草在线免费 | 香蕉久草| 久草在线资源观看 | 欧美 国产 视频 | 一本一本久久a久久精品综合妖精 | 国产美女在线精品免费观看 | 97国产精品亚洲精品 | 欧美激情xxxx | 66av99精品福利视频在线 | 天天色成人| 国产一区黄色 | 日韩在线视频线视频免费网站 | 国产午夜精品久久 | 一区二区三区在线免费观看 | 五月开心六月婷婷 | 日韩精品久久久久久久电影竹菊 | 久久精品中文 | av免费看电影 | 国产剧情在线一区 | 中文字幕在线看视频 | 久久五月激情 | 免费看国产精品 | 一级特黄aaa大片在线观看 | 五月婷婷,六月丁香 | 国产中文字幕在线播放 | 一区二区三区日韩在线观看 | 国产精品久久久久久久免费 | 国产视频2 | 亚洲免费在线播放视频 | 日本久久不卡视频 | 日日爽天天操 | 国产美女免费观看 | 成人精品电影 | 又长又大又黑又粗欧美 | 久久久污 | 久草在线视频中文 | 夜添久久精品亚洲国产精品 | 国产日韩在线视频 | www夜夜操 | 狠狠色丁香久久婷婷综合_中 | 久久久国产精品电影 | 精品久久片| 国产精品不卡在线观看 | 国产精品久久久久久久婷婷 | 日韩黄色大片在线观看 | 国产免费高清视频 | 国产一区在线播放 | 日韩黄色一级电影 | 国产亚洲欧美在线视频 | 在线视频app | 96亚洲精品久久久蜜桃 | 亚洲手机av| 欧美另类高潮 | 6699私人影院| 日本三级不卡 | 九九在线精品视频 | 午夜av片 | 国产黄色美女 | 爱射综合 | 久久午夜色播影院免费高清 | 麻豆一区在线观看 | www.色综合.com| 国产精品久久一区二区三区, | 亚洲一区二区91 | 国产成人av电影在线 | av先锋影音少妇 | 最近中文字幕免费大全 | 999久久精品 | av一区二区三区在线播放 | 高清免费在线视频 | 国内三级在线观看 | 精品在线一区二区 | 日韩资源在线播放 | 狠狠干中文字幕 | 国产黄视频在线观看 | 国产99久久久国产精品成人免费 | 中文字幕av全部资源www中文字幕在线观看 | 亚洲视频 在线观看 | 深爱婷婷久久综合 | 成人免费看黄 | 婷婷国产精品 | 国产精品一区二区久久精品爱涩 | 久草在线视频看看 | 日韩网站一区二区 | 日本精品一区二区三区在线观看 | 国产精品久久久久久电影 | 韩国一区在线 | 2000xxx影视| 狠狠干狠狠久久 | 欧美xxxxx在线视频 | 久草成人在线 | 国产成人精品一区一区一区 | 国产高清久久久久 | 在线播放国产一区二区三区 | 日韩r级电影在线观看 | 欧美视频国产视频 | 久久69精品| 色免费在线 | 国产中文字幕在线视频 | 在线观看中文字幕视频 | 91高清视频在线 | 久草精品免费 | 欧美专区日韩专区 | 欧美精品久久久久久久免费 | 亚洲国产成人高清精品 | 国产精品一区二区av影院萌芽 | 日韩字幕| 日本精品久久久久影院 | 国产精品久久久久久一区二区三区 | 久久久久久久久爱 | 激情黄色一级片 | 九9热这里真品2 | 日日夜夜中文字幕 | 久久伊人八月婷婷综合激情 | 欧美日韩精品在线观看视频 | 国产精品久免费的黄网站 | 国产视频 久久久 | 最近日本字幕mv免费观看在线 | 在线看污网站 | 开心丁香婷婷深爱五月 | 在线直播av | 亚洲黄色影院 | 在线视频 国产 日韩 | 日本中文字幕在线视频 | www日韩| 国产精品高清在线观看 | 久久免费视频在线观看30 | 亚洲天堂网站视频 | 国产精品久久久久久久毛片 | 欧美 日韩 视频 | 欧美俄罗斯性视频 | 美女中文字幕 | 免费国产黄线在线观看视频 | 欧美日韩中文在线视频 | 就要干b| 怡红院av久久久久久久 | 天天综合操 | 免费看片成人 | 国产成人在线看 | 日韩精品一区二区三区免费观看 | 国产亚洲精品久久久久久 | 国产一区二区在线观看免费 | 91色蜜桃| 久久久久久久久久电影 | 精品免费在线视频 | 伊人天天综合 | 久久国产精品99久久久久久丝袜 | 亚洲激情小视频 | 欧美综合色在线图区 | 久久精品久久精品久久39 | 又黄又爽又湿又无遮挡的在线视频 | 97**国产露脸精品国产 | 国产一级黄色av | 视频一区在线播放 | www.夜夜爱 | 一区av在线播放 | 久久公开免费视频 | 狠狠色丁香 | 国产精品成久久久久 | 日韩在线电影一区二区 | 亚洲自拍偷拍色图 | av 一区二区三区四区 | 91精品一区二区三区久久久久久 | 中文字幕人成乱码在线观看 | 狠狠色丁香久久婷婷综合丁香 | 免费观看一区二区三区视频 | 成人在线观看日韩 | 免费日韩一区二区三区 | 日本久久久久久久久久久 | 国产精品久久免费看 | 免费视频区| 日韩资源在线 | 欧美极度另类性三渗透 | www.香蕉| 91亚洲国产成人久久精品网站 | 亚洲精品国产自产拍在线观看 | 精品国产一区二区三区免费 | 亚洲国产精品小视频 | 色综合久久88 | 国产 在线观看 | 国产精品18久久久久久久久久久久 | 成人在线观看你懂的 | 亚洲男男gaygay无套同网址 | 91九色porny在线 | 久久影视一区 | 大胆欧美gogo免费视频一二区 | 午夜精品久久久99热福利 | 永久免费视频国产 | 久草在线精品观看 | 久久这里有| 久久免费av电影 | 精品视频免费观看 | 国产日韩精品一区二区三区在线 | 国产一区二区在线免费播放 | 欧美性黄网官网 | 国产精品九九九 | 久久免费在线视频 | 国产又粗又猛又黄又爽视频 | 久久国产精品免费看 | 九九导航 | 在线导航福利 | 日韩黄色中文字幕 | 视频在线一区 | 在线免费国产视频 | 日批视频在线观看免费 | 99免费在线播放99久久免费 | 国产美女免费观看 | 国产精品一区二区三区视频免费 | 久久精品国产免费观看 | 亚州精品天堂中文字幕 | 91九色蝌蚪视频在线 | 五月天综合网站 | 国产精品成人在线 | 美女视频黄在线观看 | 亚洲在线国产 | 国产资源在线免费观看 | 成年人免费观看在线视频 | 久久这里只有精品首页 | 国产一区二区三区免费在线观看 | 欧美福利精品 | 在线免费观看黄色av | 欧美乱熟臀69xxxxxx | 久久狠狠一本精品综合网 | 天天干天天操天天拍 | 波多野结衣一区二区三区中文字幕 | 天天玩天天干 | 成片免费观看视频大全 | 亚洲情感电影大片 | 欧美另类巨大 | 91精品在线免费观看视频 | 国产精品久久久久久久7电影 | 国产专区视频 | 国产亚洲一区二区在线观看 | 最新日韩电影 | 久久久视屏| 精品毛片在线 | 亚洲最新精品 | 狠狠操天天射 | 97香蕉超级碰碰久久免费软件 | 国产99久久99热这里精品5 | 九九综合九九 | 五月天丁香综合 | 欧美日韩视频在线观看一区二区 | 中文字幕免费高清 | 久久精品一二三区白丝高潮 | 国产成人av | 69av视频在线观看 | 国产中文视频 | 国产精品高清在线观看 | 97色涩| 黄色99视频 | 欧美精品免费在线观看 | 久久免费在线视频 | 成人综合免费 | 成人黄色大片在线观看 | 亚洲区精品视频 | 久久久www成人免费精品张筱雨 | 国产九九精品视频 | 人人干天天射 | 91精品国自产在线观看欧美 | 欧美高清视频不卡网 | 免费又黄又爽视频 | 久久精品久久久久电影 | 国产精品免费一区二区三区在线观看 | 久久三级视频 | 欧美一级特黄高清视频 | 天堂av免费在线 | 国产中文在线视频 | 国产一区二区三区高清播放 | 日韩欧美高清在线观看 | 中文字幕一区二区三区四区 | 欧美精品一区二区三区四区在线 | 婷婷激情站 | 亚州激情视频 | 久久综合九色综合欧美就去吻 | 亚洲天堂网在线观看视频 | 亚洲欧美综合精品久久成人 | 97精品视频在线 | 国产精品99久久久久久人免费 | 成人免费看片网址 | 97国产精品久久 | 波多野结衣一区 | 尤物一区二区三区 | 色噜噜日韩精品一区二区三区视频 | 69夜色精品国产69乱 | 欧美一级性生活 | 人人看人人艹 | 最新超碰在线 | 日韩网站在线免费观看 | 黄色免费看片网站 | 天天操夜操 | 久久免费视频这里只有精品 | 亚洲 欧美 综合 在线 精品 | 一级a性色生活片久久毛片波多野 | 亚洲作爱 | 久久精品国产99国产 | 日韩av影视在线 | 五月天天色 | 欧美日韩中文在线 | 91免费高清观看 | 国产婷婷一区二区 | 国产在线污 | 韩国av一区 | 日韩免费二区 | 夜夜夜夜猛噜噜噜噜噜初音未来 | 成人精品视频久久久久 | 成人免费在线网 | 免费观看成人网 | av亚洲产国偷v产偷v自拍小说 | 992tv成人免费看片 | 亚洲人人网 | 国产一区二区三区免费视频 | av在线免费播放网站 | 日本电影黄色 | 在线国产91 | 亚洲精品女人久久久 | 深夜国产在线 | 国产无遮挡又黄又爽馒头漫画 | 亚洲性少妇性猛交wwww乱大交 | 九九热免费在线视频 | 中文字幕有码在线播放 | 天海翼一区二区三区免费 | 国产精品a成v人在线播放 | 国产色在线观看 | 91av视频在线观看 | 国产精品2019 | 日韩一区二区三 | 24小时日本在线www免费的 | 美女视频黄免费 | 亚洲国产mv | 天天爽人人爽夜夜爽 | 欧美精品一区二区在线播放 | 91av视屏| 成人免费xxxxxx视频 | 欧美精品视 | 中文永久字幕 | av网在线观看 | 亚洲精品字幕在线观看 | 激情欧美网 | 国产字幕在线观看 | 成人网在线免费视频 | 丁香花在线观看视频在线 | 96看片 | 精品a视频| 国产在线观看 | 国产va精品免费观看 | 免费看三级黄色片 | 成人免费毛片aaaaaa片 | 国产在线传媒 | 成人在线免费av | 亚洲婷婷在线视频 | 天天摸天天操天天舔 | www.黄色片网站 | 国产精品系列在线播放 | 午夜狠狠干| av在线观 | 国产精品嫩草影视久久久 | 日日爽天天 | 免费看片网址 | 欧亚久久 | 91黄色免费网站 | 奇米先锋 | 日韩精品视| 狠狠操狠狠 | 日韩一区二区三区视频在线 | 国产馆在线播放 | 欧洲亚洲国产视频 | 成人免费亚洲 | 国产无吗一区二区三区在线欢 | 天天看天天干 | 欧美一区三区四区 | 在线观看av片 | 免费一级片在线观看 | 午夜色大片在线观看 | 婷婷新五月 | 免费看片网页 | 国产精品亚 | 91精品国产一区二区在线观看 | 天天操天天操天天操天天 | 五月天综合激情 | 在线观看黄a | 日本99热 | 国产午夜一级毛片 | 久久久精品 一区二区三区 国产99视频在线观看 | 久久国产一二区 | 日韩毛片精品 | 日韩影视在线观看 | 国产一级片毛片 | 亚洲综合色视频 | 国产精品高清在线 | 免费看的黄色录像 | 精品毛片久久久久久 | 国产成人久久av免费高清密臂 | 欧美不卡视频在线 | 日韩乱色精品一区二区 | 在线免费观看亚洲视频 | 五月av在线| 国产精品理论视频 | 麻豆91网站 | 国产精品黄网站在线观看 | 91在线视频观看免费 | 中文字幕日本在线 | 久久国产露脸精品国产 | a视频在线观看免费 | 麻豆成人精品 | 久久伊人八月婷婷综合激情 | 2023av在线| 久久试看 | 欧美日韩不卡在线观看 | 日日成人网 | 亚洲 综合 激情 | 91av短视频| 国产一区在线免费 | 国产精品久久久久aaaa九色 | 国产麻豆电影在线观看 | 成人中文字幕+乱码+中文字幕 | 日韩亚洲在线视频 | 丁香免费视频 | 久久久久国产精品免费网站 | 一级黄网 | 亚洲精品在线免费 | 中文字幕人成一区 | 国产精品99久久免费观看 | 婷婷丁香激情 | 免费91麻豆精品国产自产在线观看 | 久久av网 | 亚洲精品午夜久久久久久久 | 国产福利在线免费观看 | 久久精品一区二区三区四区 | 日韩高清一 | 免费看成年人 | 国产精品 日韩 | www.久久精品视频 | 久精品在线 | 黄色成人在线观看 | 日韩免费精品 | 色爱区综合激月婷婷 | 久久 一区| 激情五月婷婷激情 |