java.lang.Object 類
所有 Java 類的最終祖先绷旗,編譯系統(tǒng)默認(rèn)繼承 Object 類,Object 類包含了所有 Java 類的公共屬性和方法。
-
Object()
: 構(gòu)造方法 getClass():Class<?>
-
public boolean equals(Object obj)
:該方法本意用于兩個(gè)對(duì)象的“深度”比較,也就是比較兩對(duì)象封裝的數(shù)據(jù)是否相等它碎;而比較運(yùn)算符“==”在比較兩對(duì)象變量時(shí),只有當(dāng)兩個(gè)對(duì)象引用指向同一對(duì)象時(shí)才為真值显押。但在Object類中链韭,equals方法是采用“==”運(yùn)算進(jìn)行比較; hashCode()
-
public String toString()
:該方法返回對(duì)象的字符串描述,建議所有子類都重寫此方法煮落。如果沒有覆蓋toString()方法,默認(rèn)的字符串是“類名@對(duì)象的十六進(jìn)制哈希碼”踊谋。 -
wait()
,wait(long)
,wait(long, int)
讓當(dāng)前線程進(jìn)入阻塞狀態(tài) -
notify()
,notifyAll
喚醒阻塞狀態(tài)的線程
protected Object clone()
: 克隆對(duì)象
protected void finalize()
: 該方法Java垃圾回收程序在刪除對(duì)象前自動(dòng)執(zhí)行蝉仇。不建議開發(fā)者直接調(diào)用.
哈希碼(hashCode),每個(gè) Java 對(duì)象都有哈希碼(hashCode)屬性,哈希碼可以用來標(biāo)識(shí)對(duì)象轿衔,提高對(duì)象在集合操作中的執(zhí)行效率沉迹。
小技巧:為了減輕書寫重復(fù) equals 和 hashCode 代碼的復(fù)旦,可以借助一些公共的類庫(kù)進(jìn)行輔助工作害驹,例如使用 guava 來做生成這兩個(gè)方法鞭呕。
// Personal 類的 equals方法
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
TPersonal temp = (Personal) o;
return Objects.equal(ContNo, temp.ContNo) &&
Objects.equal(CvaliDate, temp.CvaliDate) &&
Objects.equal(ContState, temp.ContState) &&
Objects.equal(AppName, temp.AppName);
google/guava: Google core libraries for Java
https://github.com/google/guava
包裝類
在Java中 8 種基本數(shù)據(jù)類型不屬于類,不具備“對(duì)象”的特征宛官,沒有成員變量和方法葫松,不方便進(jìn)行面向?qū)ο蟮牟僮鳌榇说紫矗琂ava 提供包裝類(Wrapper Class)來將基本數(shù)據(jù)類型包裝成類腋么。
包裝類也都很好記,除了 Integer 和 Character 外亥揖,其他類名稱與基本類型基本一樣珊擂,只是首字母大寫。
基本數(shù)據(jù)類型 包裝類
boolean -> Boolean
byte -> Byte
char -> Character
short -> Short
int -> Integer
long -> Long
float -> Float
double -> Double
數(shù)值包裝類
這些數(shù)值包裝類(Byte费变、Short摧扇、Integer、Long挚歧、Float和Double)都有一些相同特點(diǎn)扛稽。
構(gòu)造方法類似
每一個(gè)數(shù)值包裝類都有兩個(gè)構(gòu)造方法,以 Integer 為例昼激,Integer 構(gòu)造方法如下:
Integer(int value):通過指定一個(gè)數(shù)值構(gòu)造 Integer 對(duì)象庇绽。
Integer(String s):通過指定一個(gè)字符串 s 構(gòu)造對(duì)象,s 是十進(jìn)制字符串表示的數(shù)值橙困。共同的父類
這6個(gè)數(shù)值包裝類有一個(gè)共同的父類——Number瞧掺,Number 是一個(gè)抽象類,除了這6個(gè)子類還有:AtomicInteger凡傅、AtomicLong辟狈、BigDecimal 和 BigInteger。Number 是抽象類夏跷,要求它的子類必須實(shí)現(xiàn)如下6個(gè)方法:
package java.lang;
public abstract class Number implements java.io.Serializable {
public abstract int intValue();
public abstract long longValue();
public abstract float floatValue();
public abstract double doubleValue();
public byte byteValue() {
return (byte)intValue();
}
public short shortValue() {
return (short)intValue();
}
}
包裝類與基本類型的轉(zhuǎn)換代碼結(jié)構(gòu)是類似的哼转,每種包裝類都有一個(gè)靜態(tài)方法 valueOf(),接受基本類型槽华,返回引用類型壹蔓,也都有一個(gè)實(shí)例方法 xxxValue() 返回對(duì)應(yīng)的基本類型。
compareTo() 方法
每個(gè)包裝類都實(shí)現(xiàn)了Java API中的 Comparable 接口猫态∮度兀可以進(jìn)行包裝對(duì)象的比較披摄。方法返回值是int,如果返回值是 0勇凭,則相等疚膊;如果返回值小于 0,則此對(duì)象小于參數(shù)對(duì)象虾标;如果返回值大于 0寓盗,則此對(duì)象大于參數(shù)對(duì)象。字符串轉(zhuǎn)換為基本數(shù)據(jù)類型
每一個(gè)數(shù)值包裝類都提供一些靜態(tài) parseXXX(String) 方法將字符串轉(zhuǎn)換為對(duì)應(yīng)的基本數(shù)據(jù)類型璧函。基本數(shù)據(jù)類型轉(zhuǎn)換為字符串
每一個(gè)數(shù)值包裝類都提供一些靜態(tài) toString() 方法實(shí)現(xiàn)將基本數(shù)據(jù)類型數(shù)值轉(zhuǎn)換為字符串傀蚌。對(duì)于 Integer 類型,字符串表示除了默認(rèn)的十進(jìn)制外柳譬,還可以表示為其他進(jìn)制喳张,如二進(jìn)制、八進(jìn)制和十六進(jìn)制美澳,包裝類有靜態(tài)方法進(jìn)行相互轉(zhuǎn)換销部。舉例Integer.toOctalString(15)
的輸出結(jié)果為八進(jìn)制的 17。
那到底應(yīng)該用靜態(tài)的 valueOf 方法制跟,還是使用 new 創(chuàng)建包裝類型呢舅桩?
一般建議使用 valueOf 方法。new 每次都會(huì)創(chuàng)建一個(gè)新對(duì)象雨膨,而除了 Float 和 Double 外的其他包裝類擂涛,都會(huì)緩存包裝類對(duì)象,減少需要?jiǎng)?chuàng)建對(duì)象的次數(shù)聊记,節(jié)省空間撒妈,提升性能。實(shí)際上排监,從 Java 9 開始狰右,這些構(gòu)造方法已經(jīng)被標(biāo)記為過時(shí)了,因此更加推薦使用靜態(tài)的 valueOf 方法舆床。
Character 類
Character 類是 char 類型的包裝類棋蚌。Character 類常用方法如下:
- Character(char value):構(gòu)造方法,通過 char 值創(chuàng)建一個(gè)新的 Character 對(duì)象挨队。
- char charValue():返回此 Character 對(duì)象的值谷暮。
- int compareTo(Character anotherCharacter):方法返回值是 int,如果返回值是0盛垦,則相等湿弦;如果返回值小于 0,則此對(duì)象小于參數(shù)對(duì)象腾夯;如果返回值大于0省撑,則此對(duì)象大于參數(shù)對(duì)象赌蔑。
Boolean 類
Boolean類是 boolean 類型的包裝類。
構(gòu)造方法
Boolean 類有兩個(gè)構(gòu)造方法竟秫,構(gòu)造方法定義如下:
Boolean(boolean value):通過一個(gè) boolean 值創(chuàng)建 Boolean 對(duì)象。
Boolean(String s):通過字符串創(chuàng)建 Boolean 對(duì)象跷乐。s 不能為null肥败,s如果是忽略大小寫"true"則轉(zhuǎn)換為 true 對(duì)象,其他字符串都轉(zhuǎn)換為 false 對(duì)象愕提。compareTo() 方法
Boolean類 有 int compareTo(Boolean包裝類對(duì)象)方法馒稍,可以進(jìn)行包裝對(duì)象的比較。方法返回值是int浅侨,如果返回值是0纽谒,則相等;如果返回值小于0如输,則此對(duì)象小于參數(shù)對(duì)象鼓黔;如果返回值大于0,則此對(duì)象大于參數(shù)對(duì)象不见。字符串轉(zhuǎn)換為 boolean 類型
- Boolean包裝類都提供靜態(tài) parseBoolean() 方法實(shí)現(xiàn)將字符串轉(zhuǎn)換為對(duì)應(yīng)的 boolean 類型澳化,方法定義如下:
- static boolean parseBoolean(String s):將字符串轉(zhuǎn)換為對(duì)應(yīng)的 boolean 類。s 不能為 null稳吮,s如果是忽略大小寫"true"則轉(zhuǎn)換為true缎谷,其他字符串都轉(zhuǎn)換為false。
常用常量
包裝類中除了定義靜態(tài)方法和實(shí)例方法外灶似,還定義了一些靜態(tài)變量列林。對(duì)于Boolean類型,有:Boolean.TRUE酪惭,Boolean.FALSE希痴。
所有數(shù)值類型都定義了 MAX_VALUE和 MIN_VALUE,表示能表示的最大/最小值撞蚕。
Float和Double還定義了一些特殊數(shù)值润梯,比如正無窮、負(fù)無窮甥厦、非數(shù)值纺铭。
Float 和 Double 中的常量非數(shù)值 NAN、無窮 INFINITY
java 浮點(diǎn)數(shù)運(yùn)算中有兩個(gè)特殊的情況:非數(shù)值 NAN刀疙、無窮 INFINITY舶赔。
1、INFINITY:
在浮點(diǎn)數(shù)運(yùn)算時(shí)谦秧,有時(shí)我們會(huì)遇到除數(shù)為 0 的情況竟纳,那 java 是如何解決的呢撵溃?
我們知道,在整型運(yùn)算中锥累,除數(shù)是不能為 0 的缘挑,否則直接運(yùn)行異常。但是在浮點(diǎn)數(shù)運(yùn)算中桶略,引入了無限這個(gè)概念语淘,我們來看一下 Double 和 Float 中的定義。
Double:
public static final double POSITIVE_INFINITY = 1.0 / 0.0;
public static final double NEGATIVE_INFINITY = -1.0 / 0.0;
Float:
public static final float POSITIVE_INFINITY = 1.0f / 0.0f;
public static final float NEGATIVE_INFINITY = -1.0f / 0.0f;
那么這些值對(duì)運(yùn)算會(huì)有什么影響呢际歼?
我們先思考一下下面幾個(gè)問題:
無限乘以 0 會(huì)是什么惶翻?
無限除以 0 會(huì)是什么?
無限做除了乘以 0 以外的運(yùn)算結(jié)果是什么鹅心?
無限乘以0吕粗,結(jié)果為 NAN
System.out.println(Float.POSITIVE_INFINITY * 0); // output: NAN
System.out.println(Float.NEGATIVE_INFINITY * 0); // output: NAN
- 無限除以 0,結(jié)果不變旭愧,還是無限
System.out.println((Float.POSITIVE_INFINITY / 0) == Float.POSITIVE_INFINITY); // output: true
System.out.println((Float.NEGATIVE_INFINITY / 0) == Float.NEGATIVE_INFINITY); // output: true
- 無限做除了乘以 0 以外的運(yùn)算颅筋,結(jié)果還是無限
System.out.println(Float.POSITIVE_INFINITY == (Float.POSITIVE_INFINITY + 10000)); // output: true
System.out.println(Float.POSITIVE_INFINITY == (Float.POSITIVE_INFINITY - 10000)); // output: true
System.out.println(Float.POSITIVE_INFINITY == (Float.POSITIVE_INFINITY * 10000)); // output: true
System.out.println(Float.POSITIVE_INFINITY == (Float.POSITIVE_INFINITY / 10000)); // output: true
要判斷一個(gè)浮點(diǎn)數(shù)是否為 INFINITY,可用 isInfinite 方法
// output: true
System.out.println(Double.isInfinite(Float.POSITIVE_INFINITY));
2榕茧、NAN
java 中的 NAN 是這么定義的:
public static final double NaN = 0.0d / 0.0;
NAN 表示非數(shù)字垃沦,它與任何值都不相等,甚至不等于它自己用押,所以要判斷一個(gè)數(shù)是否為 NAN 要用 isNAN 方法:
System.out.println(Double.isNaN(Float.NaN)); // output: true
自動(dòng)裝箱/拆箱
Java 5 之后提供了拆箱(unboxing)功能肢簿,拆箱能夠?qū)b類對(duì)象自動(dòng)轉(zhuǎn)換為基本數(shù)據(jù)類型的數(shù)值,而不需要使用 intValue() 或 doubleValue() 等方法蜻拨。類似 Java 5 還提供了相反功能池充,自動(dòng)裝箱( autoboxing ),裝箱能夠自動(dòng)地將基本數(shù)據(jù)類型的數(shù)值自動(dòng)轉(zhuǎn)換為包裝類對(duì)象缎讼,而不需要使用構(gòu)造方法收夸。
注意: 以下會(huì)運(yùn)行期異常 NullPointerException
Integer obj = null;
int intVar = obj;
包裝類的常量池
在前面,我們提到血崭,創(chuàng)建包裝類對(duì)象時(shí)卧惜,可以使用靜態(tài)的 valueOf 方法,也可以直接使用 new夹纫,但建議使用 valueOf 方法咽瓷,為什么呢?我們來看 Integer 的 valueOf 的代碼(基于Java 8):
public static Integer valueOf(int i) {
if (i >= IntegerCache.low && i <= IntegerCache.high)
return IntegerCache.cache[i + (-IntegerCache.low)];
return new Integer(i);
}
private static class IntegerCache {
static final int low = -128;
static final int high;
static final Integer cache[];
static {
// high value may be configured by property
int h = 127;
String integerCacheHighPropValue =
sun.misc.VM.getSavedProperty("java.lang.Integer.IntegerCache.high");
if (integerCacheHighPropValue != null) {
try {
int i = parseInt(integerCacheHighPropValue);
i = Math.max(i, 127);
// Maximum array size is Integer.MAX_VALUE
h = Math.min(i, Integer.MAX_VALUE - (-low) -1);
} catch( NumberFormatException nfe) {
// If the property cannot be parsed into an int, ignore it.
}
}
high = h;
cache = new Integer[(high - low) + 1];
int j = low;
for(int k = 0; k < cache.length; k++)
cache[k] = new Integer(j++);
// range [-128, 127] must be interned (JLS7 5.1.7)
assert IntegerCache.high >= 127;
}
private IntegerCache() {}
}
IntegerCache 表示 Integer 緩存舰讹,其中的 cache 變量是一個(gè)靜態(tài) Integer 數(shù)組茅姜,在靜態(tài)初始化代碼塊中被初始化,默認(rèn)情況下月匣,保存了-128~127共256個(gè)整數(shù)對(duì)應(yīng)的 Integer 對(duì)象钻洒。
在 valueOf 代碼中奋姿,如果數(shù)值位于被緩存的范圍,即默認(rèn) -128~127素标,則直接從Integer-Cache 中獲取已預(yù)先創(chuàng)建的 Integer 對(duì)象称诗,只有不在緩存范圍時(shí),才通過new創(chuàng)建對(duì)象头遭。
通過共享常用對(duì)象粪狼,可以節(jié)省內(nèi)存空間,由于 Integer 是不可變的任岸,所以緩存的對(duì)象可以安全地被共享。Boolean狡刘、Byte享潜、Short、Long嗅蔬、Character 都有類似的實(shí)現(xiàn)剑按。這種共享常用對(duì)象的思路,是一種常見的設(shè)計(jì)思路澜术,它有一個(gè)名字艺蝴,叫享元模式,英文叫 Flyweight鸟废,即共享的輕量級(jí)元素猜敢。
面試題
// 三種四舍五入的方法
System.out.println(Math.round(12.6)); // 記住是四舍五入即可
System.out.println(Math.round(-12.6)); // 記住規(guī)則: 四舍五入的取反 等于 取反的四舍五入
// 結(jié)果 13 -13
System.out.println(Math.floor(12.6)); // 牢記結(jié)果趨向于坐標(biāo)軸的反方向
System.out.println(Math.floor(-12.6));
// 結(jié)果 12.0 -13.0
System.out.println((int)12.6); // 記得取整數(shù)位即可
System.out.println((int)-12.6);
// 結(jié)果 12 -12
System.out.println(1.0 / 0);
// 結(jié)果為 Infinity
參考
丁振凡編著,《Java語言程序設(shè)計(jì)(第2版)》華東交大版,2014.9
第 16 章 Java常用類-圖靈社區(qū)
http://www.ituring.com.cn/book/tupubarticle/17712