Java 基礎(chǔ)知識大綱
- 一澈魄、面向?qū)ο?/li>
- 二景鼠、
Object
類相關(guān) - 三、重要關(guān)鍵字
- 四痹扇、內(nèi)部類
- 五铛漓、抽象類 & 接口
- 六、編碼
- 七鲫构、異常
- 八浓恶、注解
- 九、容器
- 十结笨、內(nèi)存區(qū)域
- 十一包晰、垃圾回收
- 十二湿镀、類加載
- 十三、泛型
- 十四伐憾、反射
一勉痴、面向?qū)ο?/h1>
1.1 對 Java 多態(tài)的理解
面向?qū)ο缶幊痰娜筇匦裕悍庋b、繼承树肃、多態(tài)蚀腿。
- 封裝:隱藏類的內(nèi)部實現(xiàn)機制奔则。
- 繼承:重用父類代碼亦镶,為多態(tài)做鋪墊。
- 多態(tài):程序中定義的引用變量所指向的具體類型和通過該引用變量發(fā)出的方法調(diào)用在編程時并不確定进萄,而是在程序運行期間才確定筛谚。
實現(xiàn)多態(tài)的三個必要條件:繼承磁玉、重寫、向上轉(zhuǎn)型驾讲。
- 繼承:在多態(tài)中必須存在有繼承關(guān)系的子類和父類蚊伞。
- 重寫:子類對父類中的某些方法進行重新定義,在調(diào)用這些方法時就會調(diào)用子類的方法吮铭。
- 向上轉(zhuǎn)型:將父類引用指向子類對象时迫,只有這樣,該引用才具備調(diào)用子類方法的能力谓晌。
實現(xiàn)形式:
- 基于繼承實現(xiàn)的多態(tài)掠拳。
- 基于接口實現(xiàn)的多態(tài)。
1.2 父類靜態(tài)方法能不能被子類重寫
結(jié)論
父類的靜態(tài)方法可以被子類繼承纸肉,但是不能被子類重寫溺欧。
當(dāng)子類聲明了一個與父類相同的靜態(tài)方法時,只能稱為隱藏柏肪。
- 父類
/**
* @author lizejun
**/
public class Parent {
public static void staticMethod() {
System.out.println("Parent Static Method");
}
public void method() {
System.out.println("Parent Method");
}
}
- 子類
/**
* @author lizejun
**/
public class Child extends Parent {
public static void staticMethod() {
System.out.println("Child Static Method");
}
public void method() {
System.out.println("Child Method");
}
}
- 示例姐刁。
/**
* @author lizejun
*/
public class MainApp {
public static void main(String[] args) {
Parent parent = new Child();
parent.method();
parent.staticMethod();
Child child = new Child();
child.method();
child.staticMethod();
}
}
- 運行結(jié)果。
Child Method
Parent Static Method
Child Method
Child Static Method
二烦味、Object 類相關(guān)
2.1 Java 中 ==聂使、equals 和 hashCode 的區(qū)別
==
在Java
中,分為基本數(shù)據(jù)類型和復(fù)合數(shù)據(jù)類型谬俄,基本數(shù)據(jù)類型包括byte
柏靶、short
、char
凤瘦、int
宿礁、long
、float
蔬芥、double
梆靖、boolean
這八種控汉。
- 對于基本數(shù)據(jù)類型,
==
比較的是它們的值返吻。 - 對于復(fù)合數(shù)據(jù)類型姑子,比較的是它們在內(nèi)存中的存放地址,即比較的是否是同一個對象测僵。
equals
Object
中equals
默認的實現(xiàn)是比較兩個對象是不是==
街佑,和==
的效果是相同的。
public boolean equals(Object obj) {
return (this == obj);
}
而有些時候捍靠,對于兩個不同的對象沐旨,我們又需要提供 邏輯 上是否相等的判斷方法,這時候就需要重寫equals
方法榨婆。Java
提供的某些類已經(jīng)重寫了equals
方法磁携,用于判斷"相等"的邏輯,例如Integer
良风。
public boolean equals(Object obj) {
if (obj instanceof Integer) {
return value == ((Integer)obj).intValue();
}
return false;
}
hashCode
hashCode
的目的是用于在對象進行散列的時候作為key
輸入谊迄,保證散列的存取性能。Object
的默認hashCode
實現(xiàn)為在對象的內(nèi)存地址上經(jīng)過特點的算法計算出烟央。
由此可見统诺,equals
和hashCode
的其實沒有什么關(guān)系。但是由于HashSet/HashMap
容器的存在疑俭,又需要保證:
- 對于
equals
相等兩個對象粮呢,其hashCode
返回的值一定相等 - 對于
equals
不同的對象要盡量做到hashCode
不同。
在 Java&Android 基礎(chǔ)知識梳理(8) - 容器類 中提到的HashMap
的實現(xiàn)怠硼,value
替換的條件是判斷key
:
//Value 替換的條件
//條件1:hash 值完全相同
//條件2:key 指向同一塊內(nèi)存地址 或者 key 的 equals 方法返回為 true
(e.hash == hash && ((k = e.key) == key || key.equals(k)))
假如我們只重寫了equals
方法鬼贱,而沒有重寫hashCode
方法移怯,就會導(dǎo)致邏輯上相等的兩個key
香璃,放在了容器中的不同位置。
2.2 Integer
存儲原理
-
int
屬于基本數(shù)據(jù)類型舟误,存儲在棧中葡秒。 -
Integer
屬于復(fù)合數(shù)據(jù)類型,引用存儲在棧中嵌溢,引用所指向的對象存儲在堆中眯牧。
缺省值
0
null
泛型支持
泛型支持Integer
,不支持int
int 與 Integer 之間的比較
//基本數(shù)據(jù)類型赖草。
int a1 = 128;
//非 new 出來的 Integer学少。
Integer a2 = 128;
//new 出來的 Integer。
Integer a3 = new Integer(128);
- 非
new
出來的Integer
與new
出來的Integer
不相等秧骑,前者指向存放它的常量池(數(shù)值位于-128
到127
之間)或者堆版确,后者指向堆中的另外一塊內(nèi)存扣囊。 - 兩個都是非
new
出來的Integer
,如果在-128
到127
之間绒疗,返回的是true
侵歇,否則返回的是false
,因為Java
在編譯Integer a2 = 128
的時候吓蘑,會翻譯成Integer.valueOf(128)
惕虑,而valueOf
函數(shù)會對-128
到127
之間的數(shù)進行緩存。
public static Integer valueOf(int i) {
//low = -128, high = 127.
if (i >= IntegerCache.low && i <= IntegerCache.high)
return IntegerCache.cache[i + (-IntegerCache.low)];
return new Integer(i);
}
- 兩個都是
new
出來的磨镶,返回false
溃蔫。 -
int
與Integer
相比,都為true
琳猫,因為會把Integer
自動拆箱為int
再去比較酒唉。
2.3 String
2.3.1 new String 和直接賦值的區(qū)別
new String
和直接賦值的區(qū)別:
-
String str1 = "ABC"
,可能創(chuàng)建一個或者不創(chuàng)建對象沸移,如果ABC
這個字符串在常量池中已經(jīng)存在了痪伦,那么str1
直接指向這個常量池中的對象。 -
String str2 = new String("ABC")
雹锣,至少創(chuàng)建一個對象网沾。一定會在堆中創(chuàng)建一個str2
中的String
對象,它的value
是ABC
蕊爵,如果ABC
這個字符串在常量池中不存在辉哥,會在池中創(chuàng)建一個對象。
例子 1
String s ="a" + "b" + "c" + "d"
只創(chuàng)建了一個對象攒射,在編譯器在編譯時優(yōu)化后醋旦,相當(dāng)于直接定義了一個abcd
的字符串。
例子 2
String ab = "ab";
String cd = "cd";
String abcd = ab + cd;
String s = "abcd";
ab
和cd
存儲的是兩個常量池中的對象会放,當(dāng)執(zhí)行ab + cd
時饲齐,首先會在堆中創(chuàng)建一個StringBuilder
類,同時用ab
指向的字符串對象完成初始化咧最,然后調(diào)用append
方法完成對cd
指向字符串的合并操作捂人,接著調(diào)用StringBuilder
的toString
方法在堆中創(chuàng)建一個String
對象,最后將剛生成的String
對象的地址存放在局部變量abcd
中矢沿。
2.3.2 String滥搭、StringBuilder、StringBuffer 的區(qū)別
對比
-
String
中的是常量數(shù)組捣鲸,只能被賦值一次瑟匆。 - 在編譯階段就能夠確定的字符串常量,沒有必要創(chuàng)建
String/StringBuffer
對象栽惶,直接使用字符串常量的+
效率更高愁溜。 -
StringBuffer
中的value[]
是一個很普通的數(shù)組无午,而且可以通過append
方法將新字符串加入到末尾,改變內(nèi)容和大小祝谚。 -
StringBuffer
允許多線程操作宪迟,其很多方法都被關(guān)鍵字synchronized
修飾,而StringBuilder
則不是交惯,如果不考慮線程安全次泽,StringBuilder
應(yīng)該是首選。
注意點
- 不停地創(chuàng)建對象是程序低效的原因席爽,因此我們應(yīng)該盡可能保證相同的字符串在堆中只創(chuàng)建一個
String
對象意荤。 - 當(dāng)調(diào)用
String
的intern
時,如果常量池已經(jīng)有了當(dāng)前String
的值只锻,那么返回這個常量指向的地址玖像;如果沒有,則將String
值加入到常量池中齐饮。 - String捐寥、StringBuffer、StringBuilder 詳細對比
2.3.3 String 為什么要設(shè)計成不可變類
常量池的需要
字符串常量池是Java
堆內(nèi)存的一個特殊區(qū)域祖驱,當(dāng)創(chuàng)建一個String
對象時握恳,假如字符串已經(jīng)存在于常量池中,則不會創(chuàng)建新的對象捺僻,而是直接引用已經(jīng)存在的對象乡洼。
String s1 = "abc";
String s2 = "abc";
s1
和s2
指向常量池中的同一個對象abc
,如果String
是可變類匕坯,s1
對其的修改將會影響到s2
束昵。
HashCode 緩存的需要
因為字符串不可變,在創(chuàng)建的時候HashCode
就被緩存葛峻,不需要重新計算锹雏。
多線程安全
由多個線程之間共享,不需要同步處理泞歉。
如何實現(xiàn)不可變
- 私有成員變量
-
public
的方法都是復(fù)制一份數(shù)據(jù) -
String
是final
逼侦,因此不可繼承 - 構(gòu)造函數(shù)深拷貝,進行
copy
而不是直接將value[]
賦值給內(nèi)部變量腰耙。
2.4 序列化 & 反序列化
Java&Android 基礎(chǔ)知識梳理(2) - 序列化
三、重要關(guān)鍵字
3.1 final
final
可以用于以下四個地方:
- 變量:靜態(tài)和非靜態(tài)
- 定義方法的參數(shù)
- 定義方法
- 定義類
3.1.1 變量
靜態(tài)變量
- 如果
final
修飾的是一個基本類型铲球,就表示這個變量被賦予的值是不可變的挺庞。 - 如果
final
修飾的是一個對象,就表示這個變量被賦予的引用是不可變的稼病。
非靜態(tài)變量
被final
修飾的變量必須被初始化选侨,初始化的方式有以下幾種:
- 在定義的時候初始化
- 非靜態(tài)
final
變量在初始化塊中初始化掖鱼,不可在靜態(tài)初始化塊中初始化 - 靜態(tài)
final
變量可以在靜態(tài)初始化塊中初始化。 - 非靜態(tài)
final
變量可以在類的構(gòu)造器中初始化援制,但是靜態(tài)final
變量不可以
3.1.2 方法
不可以被子類重寫戏挡,但是不影響被子類繼承。
3.1.3 類
不允許被繼承晨仑。
3.2 static
static 方法
- 靜態(tài)方法不依賴于任何對象就可以訪問褐墅,因此對于靜態(tài)方法來說,是沒有
this
的洪己。 - 靜態(tài)方法中不能訪問類的非靜態(tài)成員變量和非靜態(tài)成員方法妥凳。
static 變量
- 靜態(tài)變量被所有的對象所共享,在內(nèi)存中只有一個副本答捕,它當(dāng)且僅當(dāng)在類初次加載時被初始化逝钥。
- 非靜態(tài)變量是對象所擁有的,在創(chuàng)建對象的時候被初始化拱镐,存在多個副本艘款,各個對象擁有的副本互不影響。
-
static
成員變量的初始化順序按照定義的順序進行初始化沃琅。
static 代碼塊
-
static
塊可以置于類的任何地方磷箕,類中可以有多個static
塊。 - 在類初次被加載的時候阵难,會按照
static
塊的順序來執(zhí)行每個static
塊岳枷,并且只執(zhí)行一次。
四呜叫、內(nèi)部類
4.1 定義
內(nèi)部類的定義:在一個外部類的內(nèi)部再定義一個類空繁。
4.2 分類
- 成員內(nèi)部類:作為外部類的成員,可以直接使用外部類的所有成員和方法朱庆。
- 靜態(tài)內(nèi)部類:聲明為
static
的內(nèi)部類盛泡,成員內(nèi)部類不能有static
數(shù)據(jù)和static
方法,但嵌套內(nèi)部類可以娱颊。 - 局部內(nèi)部類:內(nèi)部類定義在方法和作用域內(nèi)傲诵。只在該方法或條件的作用域內(nèi)才能使用,退出作用域后無法使用箱硕。
- 匿名內(nèi)部類:匿名內(nèi)部類有幾個特點:不能加訪問修飾符拴竹;當(dāng)所在方法的形參需要被內(nèi)部類里面使用時,該形參必須為
final
剧罩。
4.3 作用
4.3.1 實現(xiàn)隱藏
外部頂級類即類名和文件名相同的只能使用public
和default
修飾栓拜,但內(nèi)部類可以是static
、public/default/protected/private
。
首先幕与,定義內(nèi)部類需要實現(xiàn)的接口:
/**
* @author lizejun
**/
public interface InnerInterface {
void call();
}
再定義一個包裝類:
/**
* @author lizejun
**/
public class Outer {
private class InnerImpl implements InnerInterface {
@Override
public void call() {
System.out.println("call inner");
}
}
public InnerInterface getInnerInterface() {
return new InnerImpl();
}
}
由于我們將InnerInterface
的實現(xiàn)類聲明為了private
挑势,因此外部并不知道它的存在,也就達到了隱藏的目的啦鸣。
/**
* @author lizejun
*/
public class MainApp {
public static void main(String[] args) {
Outer outer = new Outer();
InnerInterface inner = outer.getInnerInterface();
inner.call();
}
}
4.3.2 無條件地訪問外部類當(dāng)中的元素
/**
* @author lizejun
**/
public class Outer {
//外部類的私有變量潮饱。
private int outerSelfValue = 0;
private class InnerImpl implements InnerInterface {
@Override
public void call() {
//內(nèi)部類可以無條件地訪問。
System.out.println("call inner, outerValue=" + outerSelfValue);
}
}
public InnerInterface getInnerInterface() {
return new InnerImpl();
}
}
這僅限于非靜態(tài)內(nèi)部類诫给,它和靜態(tài)內(nèi)部類的區(qū)別是:
- 靜態(tài)內(nèi)部類沒有指向外部的引用
- 在任何非靜態(tài)內(nèi)部類中香拉,都不能有靜態(tài)變量、靜態(tài)方法或者靜態(tài)內(nèi)部類蝙搔。
- 創(chuàng)建非靜態(tài)內(nèi)部類缕溉,必須要通過外部類來創(chuàng)建,例如
Outer.InnerImpl outer = new Outer().new InnerImpl();
吃型;靜態(tài)內(nèi)部類則可以直接創(chuàng)建证鸥,Outer.InnerImpl outer = new Outer.InnerImpl();
- 靜態(tài)內(nèi)部類只可以訪問外部類的靜態(tài)方法和靜態(tài)變量。
4.3.3 實現(xiàn)多重繼承
由于Java
不允許多重繼承勤晚,因此假如我們希望一個類同時具備其它兩個類的功能時枉层,就可以采用內(nèi)部類來實現(xiàn)。
實現(xiàn)乘法的子類:
/**
* @author lizejun
**/
public class MultiCalculator {
public int multi(int a, int b) {
return a * b;
}
}
實現(xiàn)加法的子類:
/**
* @author lizejun
**/
public class PlusCalculator {
public int add(int a, int b) {
return a;
}
}
- 通過內(nèi)部類實現(xiàn)多重繼承
/**
* @author lizejun
**/
public class Calculator extends PlusCalculator {
class MultiCalculatorImpl extends MultiCalculator {
@Override
public int multi(int a, int b) {
return super.multi(a, b);
}
}
public int multi(int a, int b) {
return new MultiCalculatorImpl().multi(a, b);
}
}
4.3.4 避免修改接口而實現(xiàn)同一個類中兩種同名方法的調(diào)用
用于解決下面的困境:一個需要繼承另一個類赐写,還要實現(xiàn)一個接口鸟蜡,而繼承的類和接口里面有兩個同名的方法。那么我們調(diào)用該方法的時候挺邀,究竟是父類的揉忘,還是實現(xiàn)的接口呢,這時候就可以使用內(nèi)部類來解決這一問題端铛。
- 需要繼承的子類中有
call
方法
/**
* @author lizejun
**/
public class BaseOuter {
public void call() {
System.out.println("call baseOuter");
}
}
- 需要實現(xiàn)的接口泣矛,同樣有
call
方法
/**
* @author lizejun
**/
public interface InnerInterface {
void call();
}
- 采用內(nèi)部類的方式避免出現(xiàn)困惑
/**
* @author lizejun
**/
public class Outer extends BaseOuter {
private class InnerImpl implements InnerInterface {
@Override
public void call() {
//內(nèi)部類可以無條件地訪問。
System.out.println("call inner");
}
}
public InnerInterface getInnerInterface() {
return new InnerImpl();
}
}
- 調(diào)用方式
/**
* @author lizejun
*/
public class MainApp {
public static void main(String[] args) {
Outer outer = new Outer();
//1. 調(diào)用的是繼承父類的接口禾蚕。
outer.call();
//2. 調(diào)用的實現(xiàn)接口的方法您朽。
outer.getInnerInterface().call();
}
}
4.4 應(yīng)用場景
幕后英雄的用武之地——淺談 Java 內(nèi)部類的四個應(yīng)用場景
- 除了它的外部類,不再被其它的類使用
- 解決一些非面向?qū)ο蟮恼Z句塊
/**
* @author lizejun
**/
public interface InnerWorker {
void work();
}
/**
* @author lizejun
**/
public class Factory {
public void doWork(InnerWorker worker) {
try {
worker.work();
} catch (Exception exception) {
System.out.println("exception!");
} finally {
System.out.println("finally!");
}
}
}
/**
* @author lizejun
*/
public class MainApp {
public static void main(String[] args) {
Factory factory = new Factory();
factory.doWork(new InnerWorker() {
@Override
public void work() {
System.out.println("work1 work");
}
});
factory.doWork(new InnerWorker() {
@Override
public void work() {
System.out.println("work2 work");
}
});
}
}
- 一些多算法場合
- 適當(dāng)使用內(nèi)部類换淆,使得代碼更加靈活和具有擴展性
/**
* @author lizejun
**/
public interface Shape {
void draw();
}
/**
* @author lizejun
**/
public abstract class ShapeFactory {
private static HashMap<String, ShapeFactory> factories = new HashMap();
public static void addFactory(String id, ShapeFactory factory) {
factories.put(id, factory);
}
public static Shape createShape(String id) {
if (!factories.containsKey(id)) {
try {
Class.forName(id);
} catch (Exception e) {}
}
return factories.get(id).create();
}
protected abstract Shape create();
}
/**
* @author lizejun
*/
public class MainApp {
public static void main(String[] args) {
Shape shape = ShapeFactory.createShape(Circle.ID);
shape.draw();
}
}
4.5 內(nèi)部類和閉包
閉包就是把函數(shù)以及變量包起來哗总,使得變量的生存周期延長,閉包跟面向?qū)ο笫且豢脴渖系膬蓷l枝倍试,實現(xiàn)的功能是等價的讯屈。
涉及到閉包的兩種內(nèi)部是:局部內(nèi)部類和匿名內(nèi)部類。當(dāng)它們引用外部變量時易猫,外部的變量需要是final
的耻煤。
以下面這個例子為例具壮,定義一個內(nèi)部類的接口:
/**
* @author lizejun
**/
public interface InnerInterface {
void call();
}
/**
* @author lizejun
**/
public class InnerClose {
public void doClose(final int a) {
InnerInterface inner = new InnerInterface() {
@Override
public void call() {
System.out.println("a=" + a);
}
};
inner.call();
}
}
/**
* @author lizejun
*/
public class MainApp {
public static void main(String[] args) {
InnerClose close = new InnerClose();
close.doClose(1);
}
}
在編譯之后准颓,局部內(nèi)部類會生成獨立的InnerClose$1.class
文件哈蝇,而變量a
是方法級別的,方法運行完變量就銷毀了攘已,而局部內(nèi)部類對象還可能一直存在炮赦,不會隨著方法運行結(jié)束就馬上被銷毀。這時候就會出現(xiàn)样勃,局部內(nèi)部類對象需要訪問一個已經(jīng)不存在的局部變量a
吠勘。
因此,通過將變量聲明為final
峡眶,編譯器會將final
局部變量復(fù)制一份剧防,復(fù)制品作為局部內(nèi)部類中的成員,這樣辫樱,當(dāng)局部內(nèi)部類訪問局部變量時峭拘,其實真正訪問的是這個局部變量的復(fù)制品。
由于被final
修飾的變量賦值后不能再修改狮暑,所以就保證了復(fù)制品與原始變量的一致鸡挠,就好像是局部變量的 生命期變長了,這就是Java
的閉包搬男。
匿名內(nèi)部類為什么訪問外部類局部變量必須是 final 的
五拣展、抽象類 & 接口
5.1 區(qū)別
- 抽象類和接口都不能被實例化。
- 抽象類要被子類繼承缔逛,接口要被類實現(xiàn)备埃。
- 接口只能做方法的聲明,抽象類可以做方法的聲明褐奴,也可以做方法的實現(xiàn)按脚。
- 接口里定義的變量只能是公共的靜態(tài)常量,抽象類中的變量可以是普通變量歉糜。
- 抽象類里的抽象方法必須全部被子類實現(xiàn)乘寒;接口的接口方法必須全部被子類實現(xiàn),否則只能為抽象類匪补。
- 抽象類里可以沒有抽象方法伞辛。
- 如果一個類里有抽象方法,那么這個類只能是抽象類夯缺。
- 抽象方法要被實現(xiàn)蚤氏,所以不能是靜態(tài)的,也不能是私有的踊兜。
- 接口可繼承接口竿滨,并可多繼承接口,但類只能單繼承。
5.2 應(yīng)用場景
抽象類
在既需要統(tǒng)一的接口于游,又需要實例變量或缺省方法的情況下毁葱,可以使用:
- 定義了一組接口,但又不想強迫每個實現(xiàn)類都必須實現(xiàn)所有的接口贰剥。
- 某些場合下倾剿,只靠純粹的接口不能滿足類與類之間的協(xié)調(diào),還需要類中表示狀態(tài)的變量來區(qū)別不同的關(guān)系蚌成。
- 規(guī)范了一組相互協(xié)調(diào)的方法前痘,其中一些方法是共同的,與狀態(tài)無關(guān)的担忧,可以共享的芹缔,無需子類分別實現(xiàn);而另一些方法卻需要各個子類根據(jù)自己特定的狀態(tài)來實現(xiàn)特定的功能瓶盛。
接口
- 類與類之間需要特定的接口協(xié)調(diào)最欠,而不在乎其如何實現(xiàn)。
- 需要將一組類視為單一的類蓬网,而調(diào)用者只通過接口來與這組類發(fā)生聯(lián)系窒所。
六、編碼
6.1 為什么要編碼
- 計算機中存儲信息的最小單元是
8bit
帆锋,所以能表示的字符范圍是0~255
個吵取。 - 要表示的符號太多,無法用一個字節(jié)來完全表示锯厢。
- 要解決這個矛盾必須要一個新的數(shù)據(jù)結(jié)構(gòu)
char
皮官,從char
到byte
必須編碼。
6.2 編碼方式
ASCII 碼
ASCII
碼總共有128
個实辑,用一個字節(jié)的低7
位表示捺氢。
ISO-8859-1
在ASCII
碼基礎(chǔ)上制定了一系列標(biāo)準(zhǔn)來擴展ASCII
編碼,其仍然是單字節(jié)編碼剪撬,總共能表示256
個字符摄乒。
GB2312
雙字節(jié)編碼,總的范圍是A1~F7
残黑,從A1~A9
是符號區(qū)馍佑,總共包含682
個符號;從B0~F7
是漢字區(qū)梨水,包含6763
個漢字拭荤。
GBK
擴展GB2312
,加入更多的漢字疫诽,其編碼范圍是8140~FEFE
舅世,和GB2312
兼容旦委。
GB18030
我國的強制標(biāo)準(zhǔn),可能是單字節(jié)雏亚、雙字節(jié)或者四字節(jié)編碼缨硝,與GB2312
兼容。
Unicode 編碼集
ISO
試圖創(chuàng)建一個全新的語言字典评凝,將所有的語言互相翻譯追葡。String
在內(nèi)存中 不需要編碼格式腺律,它只是一個Unicode
字符串而已奕短。只有當(dāng)字符串需要在網(wǎng)絡(luò)中傳輸或要被寫入文件時,才需要編碼格式匀钧。
-
UTF-16
UTF-16
具體定義了Unicode
字符在計算機中的存取方法翎碑,它用兩個字節(jié)表示Unicode
轉(zhuǎn)化格式。 -
UTF-8
UTF-16
的缺點在于很大部分字符僅用一個字節(jié)就可以表示之斯,目前卻需要使用兩個日杈,而UTF-8
采用了變長技術(shù),不同類型的字符可以由1~6
個字節(jié)組成佑刷。- 如果一個字節(jié)莉擒,最高位為
0
,表示這是一個ASCII
字符瘫絮。 - 如果一個字節(jié)涨冀,以
11
開頭,連續(xù)的1
個數(shù)表示這個字符的字節(jié)數(shù)麦萤。 - 如果一個字節(jié)鹿鳖,以
10
開始,表示它不是首字節(jié)壮莹,需要向前查找才能得到當(dāng)前字符的首字節(jié)翅帜。
- 如果一個字節(jié)莉擒,最高位為
String s = "嚴";
//編碼。
byte[] b = s.getBytes("UTF-8");
//解碼命满。
String n = new String(b,"UTF-8");
6.3 對比
-
GB2312
與GBK
編碼規(guī)則類似涝滴,但是GBK
范圍更大,它能處理所有漢字字符胶台。 -
UTF-16
和UTF-8
都是處理Unicode
編碼歼疮,UTF-16
效率更高,它適合在本地磁盤和內(nèi)存之間使用概作。 -
UTF-16
不是在網(wǎng)絡(luò)之間傳輸腋妙,因為網(wǎng)絡(luò)傳輸容易損壞字節(jié)流,UTF-8
更適合網(wǎng)絡(luò)傳輸讯榕,對ASCII
字符采用單字節(jié)存儲骤素,單字節(jié)損毀不會影響后面其它字符匙睹。
6.4 參考文章
七、異常
Java
中定義了許多異常類济竹,并定義了Throwable
作為所有異常的超類痕檬,將異常劃分為兩類Error
和Exception
。
-
Error
:程序中無法處理的錯誤送浊,例如NoClassDefFoundError
梦谜、OutOfMemory
等,當(dāng)此類錯誤發(fā)生時袭景,JVM
將終止進程唁桩。 -
Exception
:程序本身可以處理的異常。- 運行時異常耸棒,
RuntimeException
及其子類荒澡,表示JVM
在運行時可能出現(xiàn)的錯誤,例如空指針与殃、數(shù)組越界等单山,一般是由邏輯錯誤引起。 - 受檢異常:除
RuntimeException
及其子類的異常幅疼。編譯器會檢查此類異常米奸,并提示你處理本類異常 - 要么使用try-catch
捕獲,要么使用throws
語句拋出爽篷,否則編譯不通過悴晰。
- 運行時異常耸棒,
八、注解
Java&Android 基礎(chǔ)知識梳理(1) - 注解
九狼忱、容器
Java&Android 基礎(chǔ)知識梳理(8) - 容器類
十膨疏、內(nèi)存區(qū)域
Java&Android 基礎(chǔ)知識梳理(3) - 內(nèi)存區(qū)域
十一、垃圾回收
Java&Android 基礎(chǔ)知識梳理(4) - 垃圾收集器與內(nèi)存分配策略
十二钻弄、類加載
Java&Android 基礎(chǔ)知識梳理(5) - 類加載&對象實例化
十三佃却、泛型
Java & Android 基礎(chǔ)知識梳理(12) - 泛型