java8增強(qiáng)的包裝類
java中基本數(shù)據(jù)類型不能當(dāng)作對(duì)象類型變量使用的問題渐北, java提供了包裝類 (Wrapper Class),包裝類均位于java.lang包.
java是可以直接處理基本類型的,但是在有些情況下我們需要將其作為對(duì)象來處理,這時(shí)就需要將其轉(zhuǎn)化為包裝類了.所有的包裝類(Wrapper Class)都有共同的方法:
- 帶有基本值參數(shù)并創(chuàng)建包裝類對(duì)象的構(gòu)造函數(shù).如可以利用Integer包裝類創(chuàng)建對(duì)象,Integer obj=new Integer(145);
- 帶有字符串參數(shù)并創(chuàng)建包裝類對(duì)象的構(gòu)造函數(shù).如new Integer("-45.36");
- 可生成對(duì)象基本值的typeValue方法,如obj.intValue();
- 將字符串轉(zhuǎn)換為基本值的 parseType方法,如Integer.parseInt(args[0]);
- 生成哈稀表代碼的hashCode方法,如obj.hasCode();
- 對(duì)同一個(gè)類的兩個(gè)對(duì)象進(jìn)行比較的equals()方法,如obj1.eauqls(obj2);
- 生成字符串表示法的toString()方法,如obj.toString().
在JDK1.5以前吨灭,把基本數(shù)據(jù)類型變量變成包裝類實(shí)例需要通過對(duì)應(yīng)包裝類的構(gòu)造器實(shí)現(xiàn)燕刻。
但從JDK1.5開始不同,JDK提供了自動(dòng)裝箱(Autoboxing)和自動(dòng)拆箱(AutoUnboxing)功能未檩。
所謂自動(dòng)裝箱伟姐,就是可以把一個(gè)基本類型變量直接賦給對(duì)應(yīng)的包裝變量罚拟,或者賦給Object變量(Object是所有類的父類,子類對(duì)象可以直接賦給父類變量)驱敲;自動(dòng)拆箱則與之相反铁蹈,允許直接把包裝類對(duì)象直接賦給一個(gè)對(duì)應(yīng)的基本類型變量。
package com.company;public class Main {
public static void main(String[] args) {
double b = 4.0;
Double a = 4.0;
Double c = 4.0;
System.out.println(a.doubleValue());
//System.out.println(b.doubleValue());
System.out.println(a < b);
System.out.println(a.toString());
System.out.println(a == b);
System.out.println( a == c );
System.out.println( a.equals(b));
}
}
進(jìn)行自動(dòng)拆箱和自動(dòng)拆箱必須注意類型匹配众眨。例如Integer只能自動(dòng)拆箱成int類型變量握牧,不要試圖拆箱成boolean類型變量;與之類似的是娩梨,int類型變量只能自動(dòng)裝箱成Integer對(duì)象(即使賦給Object類型變量沿腰,也只是利用了Java類型的向上自動(dòng)轉(zhuǎn)型特性),不要試圖裝箱成boolean對(duì)象狈定。
處理對(duì)象
Java對(duì)象都是Object類的實(shí)例颂龙,都可以調(diào)用該類中定義的方法,這些方法提供了處理Java對(duì)象的通用方法纽什。通俗的可以說任何對(duì)象都可以調(diào)用Object類中的方法措嵌。
- toString 方法
Object類里面的的一個(gè)實(shí)例方法,所有的對(duì)象都具有toString()方法芦缰,所有的java對(duì)象都可以和字符串進(jìn)行連接運(yùn)算企巢,當(dāng)java對(duì)象和字符串連接對(duì)象時(shí),系統(tǒng)自動(dòng)調(diào)用Java對(duì)象toString()方法的返回值和字符串進(jìn)行連接運(yùn)算让蕾。toString()是一個(gè)特殊的方法浪规,它是一個(gè)“自我描述”的功能,返回的對(duì)象實(shí)現(xiàn)類的類名+@+hascode(8位十六進(jìn)制數(shù)字)探孝,也可以在該類中重寫toString()實(shí)現(xiàn)不同的功能笋婿。
class People{
private Integer age;
private Double height;
public People(Integer age, Double height){
this.age = age;
this.height = height;
}
public String toString(){
return "該人的年齡是:"+ age + ", 身高是:"+ height;
}
}
- == 和 equals方法
java程序中測(cè)試兩個(gè)變量是否相等有兩種方式,一種是利用==運(yùn)算符顿颅,另外一種利用equals()方法萌抵。當(dāng)使用==時(shí),只要要求這兩變量的數(shù)值相等,而當(dāng)兩個(gè)引用類型是==卻要要求他們引用的為同一個(gè)對(duì)象绍填。而equals卻不用他引用的為同一個(gè)類型霎桅。new String("hello")和hello當(dāng)java在直接使用形如“hello”的字符串直接量時(shí),jvm將會(huì)使用常量池來管理這些字符串讨永,當(dāng)使用new String("hello")時(shí)滔驶,jvm會(huì)先使用常量池來保管“hello”直接量,再調(diào)用String類的構(gòu)造器來創(chuàng)建一個(gè)新的String對(duì)象卿闹,新創(chuàng)建的String對(duì)象被保存在堆內(nèi)存里面揭糕。也就是說 new String(“hello”)一共產(chǎn)生兩個(gè)字符串對(duì)象。常量池專門用于管理在編譯時(shí)被確定并被保存在已編譯的.class文件中的一些數(shù)據(jù)锻霎。他包括了關(guān)于類著角、方法、接口中的常量旋恼,還包括字符串常量吏口。new String()創(chuàng)建出來的字符串對(duì)象是運(yùn)行時(shí)創(chuàng)建出來的,他被保存在在運(yùn)行時(shí)內(nèi)存里面(即堆內(nèi)存)冰更,不會(huì)放入常量池里产徊。
Object默認(rèn)提供的equals只是比較對(duì)象的地址,在實(shí)際中常常會(huì)重寫equals()方法蜀细。重寫equals方法滿足自反性舟铜、對(duì)稱性、傳遞性奠衔。instanceof運(yùn)算符谆刨,當(dāng)前面對(duì)象是后面的實(shí)例或其子類的實(shí)例時(shí)都將返回true。
static 和 final
- static
** 1. static變量**
按照是否靜態(tài), 對(duì)類成員變量進(jìn)行分類可分兩種:一種是被static修飾的變量归斤,叫靜態(tài)變量或類變量痊夭;另一種是沒有被static修飾的變量,叫實(shí)例變量官册。兩者的區(qū)別是:
對(duì)于靜態(tài)變量在內(nèi)存中只有一個(gè)拷貝(節(jié)省內(nèi)存),JVM只為靜態(tài)分配一次內(nèi)存难捌,在加載類的過程中完成靜態(tài)變量的內(nèi)存分配膝宁,可用類名直接訪問(方便),當(dāng)然也可以通過對(duì)象來訪問(但是這是不推薦的)根吁。對(duì)于實(shí)例變量员淫,沒創(chuàng)建一個(gè)實(shí)例,就會(huì)為實(shí)例變量分配一次內(nèi)存击敌,實(shí)例變量可以在內(nèi)存中有多個(gè)拷貝介返,互不影響(靈活)。
2. static代碼塊
static代碼塊是類加載時(shí),初始化自動(dòng)執(zhí)行的圣蝎。如果static代碼塊有多個(gè)刃宵,JVM將按照它們?cè)陬愔谐霈F(xiàn)的先后順序依次執(zhí)行它們,每個(gè)代碼塊只會(huì)被執(zhí)行一次徘公。
3. static方法
static方法可以直接通過類名調(diào)用牲证,任何的實(shí)例也都可以調(diào)用,因此static方法中不能用this和super關(guān)鍵字关面,不能直接訪問所屬類的實(shí)例變量和實(shí)例方法(就是不帶static的成員變量和成員成員方法)坦袍,只能訪問所屬類的靜態(tài)成員變量和成員方法。因?yàn)閟tatic方法獨(dú)立于任何實(shí)例等太,因此static方法必須被實(shí)現(xiàn)捂齐,而不能是抽象的abstract。
static方法只能訪問static的變量和方法缩抡,因?yàn)榉莝tatic的變量和方法是需要?jiǎng)?chuàng)建一個(gè)對(duì)象才能訪問的奠宜,而static的變量/方法不需要?jiǎng)?chuàng)建任何對(duì)象。static的數(shù)據(jù)或方法缝其,屬于整個(gè)類的而不是屬于某個(gè)對(duì)象的挎塌,是不會(huì)和類的任何對(duì)象實(shí)例聯(lián)系到一起。所以子類和父類之間可以存在同名的static方法名内边,這里不涉及重載榴都。所以不能把任何方法體內(nèi)的變量聲明為static,例如:
fun() {
static int i=0; //非法漠其。
}```
其實(shí)理解static是只有一個(gè)存儲(chǔ)地方嘴高,而使用時(shí)直接使用,不需要?jiǎng)?chuàng)建對(duì)象和屎,就能明白以上的注意事項(xiàng)拴驮。
> * final
在Java中聲明屬性、方法和類時(shí)柴信,可使用關(guān)鍵字final來修飾套啤。
final變量即為常量,只能賦值一次随常;
final方法不能被子類重寫潜沦;
final類不能被繼承。
**1. final變量**
聲明 final 字段有助于優(yōu)化器作出更好的優(yōu)化決定绪氛,因?yàn)槿绻幾g器知道字段的值不會(huì)更改唆鸡,那么它能安全地在寄存器中高速緩存該值。
其初始化可以在兩個(gè)地方枣察,一是其定義處, 二是在構(gòu)造函數(shù)中, 這兩個(gè)地方只能選其争占。
一旦被初始化便不可改變燃逻,這里不可改變的意思對(duì)基本類型來說是其值不可變,而對(duì)于對(duì)象變量來說其引用不可再變臂痕。
**在java中伯襟,普通變量系統(tǒng)是自動(dòng)初始化的,數(shù)值變量自動(dòng)初始化為0刻蟹,其余類型變量自動(dòng)初始化為空逗旁。但是final類型的變量必須顯示初始化,且不能通過調(diào)用函數(shù)賦值舆瘪。**
**2. final方法**
如果一個(gè)類不允許其子類覆蓋某個(gè)方法片效,則可以把這個(gè)方法聲明為final方法。
使用final方法的原因有二:
第一英古、把方法鎖定淀衣,防止任何繼承類修改它的意義和實(shí)現(xiàn)。
第二召调、高效膨桥。編譯器在遇到調(diào)用final方法時(shí)候會(huì)轉(zhuǎn)入內(nèi)嵌inline機(jī)制,大大提高執(zhí)行效率唠叛。
注意只嚣,類中所有的private方法都被隱含是final的。由于無法取用private方法艺沼,則也無法重載之册舞。
**3. final類**
final類不能被繼承,因此final類的成員方法沒有機(jī)會(huì)被覆蓋障般,默認(rèn)都是final的调鲸。在設(shè)計(jì)類時(shí)候,如果這個(gè)類不需要有子類挽荡,類的實(shí)現(xiàn)細(xì)節(jié)不允許改變藐石,并且確信這個(gè)類不會(huì)載被擴(kuò)展,那么就設(shè)計(jì)為final類定拟。
# 抽象類 與 接口
> * 抽象類
抽象方法: 它只有聲明于微,而沒有具體的實(shí)現(xiàn), 必須用abstract關(guān)鍵字進(jìn)行修飾。抽象方法的聲明格式為:
abstract void fun(); ```
如果一個(gè)類含有抽象方法青自,則稱這個(gè)類為抽象類株依,抽象類必須在類前用abstract關(guān)鍵字修飾。因?yàn)槌橄箢愔泻袩o具體實(shí)現(xiàn)的方法性穿,所以不能用抽象類創(chuàng)建對(duì)象勺三。
[public] abstract class ClassName {
abstract void fun();
}```
抽象類和普通類的主要有三點(diǎn)區(qū)別:
1)抽象方法必須為public或者protected(因?yàn)槿绻麨閜rivate雷滚,則不能被子類繼承需曾,子類便無法實(shí)現(xiàn)該方法),缺省情況下默認(rèn)為public。
2)抽象類不能用來創(chuàng)建對(duì)象呆万;
3)如果一個(gè)類繼承于一個(gè)抽象類商源,則子類必須實(shí)現(xiàn)父類的抽象方法。如果子類沒有實(shí)現(xiàn)父類的抽象方法谋减,則必須將子類也定義為為abstract類牡彻。
> * 接口
是對(duì)行為的抽象;接口類定義格式和使用格式如下:
//定義
[public] interface InterfaceName {
}
//使用
class ClassName implements Interface1,Interface2,[....]{
}
接口中可以含有 變量和方法出爹。但是要注意庄吼,接口中的變量會(huì)被隱式地指定為public static final變量(并且只能是public static final變量,用private修飾會(huì)報(bào)編譯錯(cuò)誤)严就,而方法會(huì)被隱式地指定為public abstract方法且只能是public abstract方法(用其他關(guān)鍵字总寻,比如private、protected梢为、static渐行、 final等修飾會(huì)報(bào)編譯錯(cuò)誤),并且接口中所有的方法不能有具體的實(shí)現(xiàn)铸董,也就是說祟印,接口中的方法必須都是抽象方法。從這里可以隱約看出接口和抽象類的區(qū)別粟害,接口是一種極度抽象的類型蕴忆,它比抽象類更加“抽象”,并且一般情況下不在接口中定義變量我磁。
interface Bird{
String fly();
void jump();
}
class Chicken implements Bird{
@Override
public String fly(){
return "chicken can fly";
}
@Override
public void jump(){
System.out.println("chicken cannot jump");
}
}```
- 抽象類和接口的區(qū)別
1.語法層面上的區(qū)別
1)抽象類可以提供成員方法的實(shí)現(xiàn)細(xì)節(jié)孽文,而接口中只能存在public abstract 方法;
2)抽象類中的成員變量可以是各種類型的夺艰,而接口中的成員變量只能是public static final類型的芋哭;
3)接口中不能含有靜態(tài)代碼塊以及靜態(tài)方法,而抽象類可以有靜態(tài)代碼塊和靜態(tài)方法郁副;
4)一個(gè)類只能繼承一個(gè)抽象類减牺,而一個(gè)類卻可以實(shí)現(xiàn)多個(gè)接口。
2.設(shè)計(jì)層面上的區(qū)別
1)抽象類是對(duì)一種事物的抽象存谎,即對(duì)類抽象拔疚,而接口是對(duì)行為的抽象。
2)設(shè)計(jì)層面不同既荚,抽象類作為很多子類的父類稚失,它是一種模板式設(shè)計(jì)。而接口是一種行為規(guī)范恰聘,它是一種輻射式設(shè)計(jì)句各。
垃圾回收
當(dāng)程序創(chuàng)建對(duì)象吸占、數(shù)組等引用類型實(shí)體時(shí),系統(tǒng)都會(huì)在堆內(nèi)存中為之分配一塊內(nèi)存區(qū)凿宾,對(duì)象就保存在這塊內(nèi)存區(qū)中矾屯,當(dāng)這塊內(nèi)存不再被任何引用變量引用時(shí),這塊內(nèi)存就變成垃圾初厚,等待垃圾回收機(jī)制進(jìn)行回收件蚕。垃圾回收機(jī)制具有如下特征。
* 垃圾回收機(jī)制只負(fù)責(zé)回收內(nèi)存中的對(duì)象产禾,不會(huì)回收任何物理資源(例如數(shù)據(jù)庫(kù)連接排作、網(wǎng)絡(luò)IO等資源)
* 程序無法精確控制垃圾回收的運(yùn)行,垃圾回收會(huì)在合適的時(shí)候進(jìn)行亚情。
* 在垃圾回收機(jī)制回收任何對(duì)象之前纽绍,總會(huì)先調(diào)用它的finalize()方法,該方法可能使該對(duì)象重新復(fù)活(讓一個(gè)引用變量重新引用該對(duì)象)势似,從而導(dǎo)致垃圾回收機(jī)制取消回收拌夏。
修飾符的適用范圍
在以上所列出的表格里,前四個(gè)(public,protected,包訪問控制符,private)是互斥的不能同時(shí)使用履因;不僅如此障簿,abstract和final不能同時(shí)使用,abstract和static栅迄,以及abstract和private也不能同時(shí)使用站故。
使用JAR文件
Java Archive File,Java檔案文件
- 創(chuàng)建JAR文件:jar cf test.jar test
該命令沒有顯示壓縮過程毅舆,執(zhí)行結(jié)果是將當(dāng)前路徑下的test路徑下的全部?jī)?nèi)容生成一個(gè)test.jar文件西篓。如果當(dāng)前目錄中已經(jīng)存在test.jar文件,那么該文件將被覆蓋
- 創(chuàng)建JAR文件憋活,并顯示壓縮過程:jar cvf test.jar test
- 不使用清單文件:jar cvfM test.jar test
M選項(xiàng)表明不生成清單文件岂津,即沒有包含META-INF/MANIFEST.MF文件 - 自定義清單文件內(nèi)容:jar cvfm test.jar manifest.mf test
m選項(xiàng)指定讀取用戶清單文件信息。清單文件的內(nèi)容由如下格式的多個(gè)key-value對(duì)組成悦即。
key:<空格>value
清單文件的內(nèi)容格式:
每行只能定義一個(gè)key-value對(duì)吮成,每行的key-value對(duì)之前不能有空格,即key-value對(duì)必須頂格寫辜梳。
每組key-value對(duì)之間以“:”(英文冒號(hào)后緊跟一個(gè)英文空格)分隔粱甫,少寫了冒號(hào)或空格都是錯(cuò)誤的。
文件開頭不能與空行
文件必須以一個(gè)空行結(jié)束
將上面文件保存在當(dāng)前路徑下作瞄,文件名為a.txt茶宵。使用如下命令即可將清單文件中的key-value對(duì)提取到META-INF/MANIFEST.MF文件中。
jar cvfm test.jar a.txt test - 查看JAR包內(nèi)容:jar tf test.jar
- 查看JAR包詳細(xì)內(nèi)容:jar tvf test.jar
- 解壓縮:jar xf test.jar
- 帶提示信息解壓縮:jar xvf test.jar
- 更新JAR文件:jar uf test.jar Hello.class
更新test.jar中的Hello.class文件宗挥。如果存在乌庶,則使用新的Hello.class文件替換原來的文件叶摄;如果沒有,則把新的文件添加到test.jar文件中安拟。 - 更新時(shí)顯式詳細(xì)信息:jar uvf test.jar Hello.class