11.1 Java 詳解 Object 和包裝類

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)扛稽。

  1. 構(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ù)值橙困。

  2. 共同的父類
    這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)的基本類型。

  1. compareTo() 方法
    每個(gè)包裝類都實(shí)現(xiàn)了Java API中的 Comparable 接口猫态∮度兀可以進(jìn)行包裝對(duì)象的比較披摄。方法返回值是int,如果返回值是 0勇凭,則相等疚膊;如果返回值小于 0,則此對(duì)象小于參數(shù)對(duì)象虾标;如果返回值大于 0寓盗,則此對(duì)象大于參數(shù)對(duì)象。

  2. 字符串轉(zhuǎn)換為基本數(shù)據(jù)類型
    每一個(gè)數(shù)值包裝類都提供一些靜態(tài) parseXXX(String) 方法將字符串轉(zhuǎn)換為對(duì)應(yīng)的基本數(shù)據(jù)類型璧函。

  3. 基本數(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 類型的包裝類。

  1. 構(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ì)象愕提。

  2. compareTo() 方法
    Boolean類 有 int compareTo(Boolean包裝類對(duì)象)方法馒稍,可以進(jìn)行包裝對(duì)象的比較。方法返回值是int浅侨,如果返回值是0纽谒,則相等;如果返回值小于0如输,則此對(duì)象小于參數(shù)對(duì)象鼓黔;如果返回值大于0,則此對(duì)象大于參數(shù)對(duì)象不见。

  3. 字符串轉(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è)問題:

  1. 無限乘以 0 會(huì)是什么惶翻?

  2. 無限除以 0 會(huì)是什么?

  3. 無限做除了乘以 0 以外的運(yùn)算結(jié)果是什么鹅心?

  4. 無限乘以0吕粗,結(jié)果為 NAN

System.out.println(Float.POSITIVE_INFINITY * 0); // output: NAN
System.out.println(Float.NEGATIVE_INFINITY * 0); // output: NAN
  1. 無限除以 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
  1. 無限做除了乘以 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

參考

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市盒延,隨后出現(xiàn)的幾起案子缩擂,更是在濱河造成了極大的恐慌,老刑警劉巖添寺,帶你破解...
    沈念sama閱讀 222,681評(píng)論 6 517
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件胯盯,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡计露,警方通過查閱死者的電腦和手機(jī)博脑,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,205評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來票罐,“玉大人叉趣,你說我怎么就攤上這事〗鹤梗” “怎么了君账?”我有些...
    開封第一講書人閱讀 169,421評(píng)論 0 362
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)沈善。 經(jīng)常有香客問我乡数,道長(zhǎng)椭蹄,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 60,114評(píng)論 1 300
  • 正文 為了忘掉前任净赴,我火速辦了婚禮绳矩,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘玖翅。我一直安慰自己翼馆,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 69,116評(píng)論 6 398
  • 文/花漫 我一把揭開白布金度。 她就那樣靜靜地躺著应媚,像睡著了一般。 火紅的嫁衣襯著肌膚如雪猜极。 梳的紋絲不亂的頭發(fā)上中姜,一...
    開封第一講書人閱讀 52,713評(píng)論 1 312
  • 那天,我揣著相機(jī)與錄音跟伏,去河邊找鬼丢胚。 笑死,一個(gè)胖子當(dāng)著我的面吹牛受扳,可吹牛的內(nèi)容都是我干的携龟。 我是一名探鬼主播,決...
    沈念sama閱讀 41,170評(píng)論 3 422
  • 文/蒼蘭香墨 我猛地睜開眼勘高,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼峡蟋!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起相满,我...
    開封第一講書人閱讀 40,116評(píng)論 0 277
  • 序言:老撾萬榮一對(duì)情侶失蹤层亿,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后立美,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體匿又,經(jīng)...
    沈念sama閱讀 46,651評(píng)論 1 320
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,714評(píng)論 3 342
  • 正文 我和宋清朗相戀三年建蹄,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了碌更。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,865評(píng)論 1 353
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡洞慎,死狀恐怖痛单,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情劲腿,我是刑警寧澤旭绒,帶...
    沈念sama閱讀 36,527評(píng)論 5 351
  • 正文 年R本政府宣布,位于F島的核電站,受9級(jí)特大地震影響挥吵,放射性物質(zhì)發(fā)生泄漏重父。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,211評(píng)論 3 336
  • 文/蒙蒙 一忽匈、第九天 我趴在偏房一處隱蔽的房頂上張望房午。 院中可真熱鬧,春花似錦丹允、人聲如沸郭厌。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,699評(píng)論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽折柠。三九已至,卻和暖如春批狐,著一層夾襖步出監(jiān)牢的瞬間液走,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,814評(píng)論 1 274
  • 我被黑心中介騙來泰國(guó)打工贾陷, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人嘱根。 一個(gè)月前我還...
    沈念sama閱讀 49,299評(píng)論 3 379
  • 正文 我出身青樓髓废,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親该抒。 傳聞我的和親對(duì)象是個(gè)殘疾皇子慌洪,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,870評(píng)論 2 361

推薦閱讀更多精彩內(nèi)容