天天看點

c++ double轉string_【轉】Java知識點集錦(1~40)

c++ double轉string_【轉】Java知識點集錦(1~40)

本文首發于公衆号:javaadu

1. 面向對象的特征有哪些方面?

  • 抽象:抽象是将一類對象的共同特征總結出來構造類的過程,包括資料抽象和行為抽象兩方面。抽象隻關注對象有哪些屬性和行為,并不關注這些行為的細節是什麼。
  • 繼承:繼承是從已有類得到繼承資訊建立新類的過程。提供繼承資訊的類被稱為父類(超類、基類);得到繼承資訊的類被稱為子類(派生類)。繼承讓變化中的軟體系統有了一定的延續性,同時繼承也是封裝程式中可變因素的重要手段(如果不能了解請閱讀閻宏博士的《Java與模式》或《設計模式精解》中關于橋梁模式的部分)。
  • 封裝:通常認為封裝是把資料和操作資料的方法綁定起來,對資料的通路隻能通過已定義的接口。面向對象的本質就是将現實世界描繪成一系列完全自治、封閉的對象。我們在類中編寫的方法就是對實作細節的一種封裝;我們編寫一個類就是對資料和資料操作的封裝。可以說,封裝就是隐藏一切可隐藏的東西,隻向外界提供最簡單的程式設計接口(可以想想普通洗衣機和全自動洗衣機的差别,明顯全自動洗衣機封裝更好是以操作起來更簡單;我們現在使用的智能手機也是封裝得足夠好的,因為幾個按鍵就搞定了所有的事情)。
  • 多态性:多态性是指允許不同子類型的對象對同一消息作出不同的響應。簡單的說就是用同樣的對象引用調用同樣的方法但是做了不同的事情。多态性分為編譯時的多态性和運作時的多态性。如果将對象的方法視為對象向外界提供的服務,那麼運作時的多态性可以解釋為:當A系統通路B系統提供的服務時,B系統有多種提供服務的方式,但一切對A系統來說都是透明的(就像電動刮胡刀是A系統,它的供電系統是B系統,B系統可以使用電池供電或者用交流電,甚至還有可能是太陽能,A系統隻會通過B類對象調用供電的方法,但并不知道供電系統的底層實作是什麼,究竟通過何種方式獲得了動力)。方法重載(overload)實作的是編譯時的多态性(也稱為前綁定),而方法重寫(override)實作的是運作時的多态性(也稱為後綁定)。運作時的多态是面向對象最精髓的東西,要實作多态需要做兩件事:1). 方法重寫(子類繼承父類并重寫父類中已有的或抽象的方法);2). 對象造型(用父類型引用引用子類型對象,這樣同樣的引用調用同樣的方法就會根據子類對象的不同而表現出不同的行為)。

2. 通路修飾符public,private,protected,以及不寫(預設)時的差別?

修飾符目前類同包子類其他包publicyyyyprotectedyyyxdefaultyyxxprivateyxxx

  • 類的成員不寫通路修飾時預設為default。預設對于同一個包中的其他類相當于公開(public),對于不是同一個包中的其他類相當于私有(private);
  • 受保護(protected)對子類相當于公開,對不是同一包中的沒有父子關系的類相當于私有。
  • Java中,外部類的修飾符隻能是public或預設,類的成員(包括内部類)的修飾符可以是以上四種。

3. String是基本資料類型嗎?

答:不是。Java中的基本資料類型隻有8個:byte、short、int、long、float、double、char、boolean;除了基本類型(primitive type)和枚舉類型(enumeration type),剩下的都是引用類型(reference type)。

4. float f = 3.4;是否正确?

答:不正确。3.4是雙精度數,将雙精度型(double)指派給浮點型(float)屬于下轉型(down-casting,也稱為窄化)會造成精度損失,是以需要強制類型轉換float f =(float)3.4;或者寫成float f =3.4F;。

5. short s1 = 1; s1 = s1 + 1;有錯嗎?short s1 = 1; s1 += 1;有錯嗎?

答:對于short s1 = 1; s1 = s1 + 1;由于1是int類型,是以s1+1運算結果也是int 型,需要強制轉換類型才能指派給short型;而short s1 = 1; s1 += 1;可以正确編譯,因為s1+= 1;相當于s1 = (short)(s1 + 1);其中有隐含的強制類型轉換。

6. Java有沒有goto?

答:goto 是Java中的保留字,在目前版本的Java中沒有使用。(根據James Gosling(Java之父)編寫的《The Java Programming Language》一書的附錄中給出了一個Java關鍵字清單,其中有goto和const,但是這兩個是目前無法使用的關鍵字,是以有些地方将其稱之為保留字,其實保留字這個詞應該有更廣泛的意義,因為熟悉C語言的程式員都知道,在系統類庫中使用過的有特殊意義的單詞或單詞的組合都被視為保留字)。

7. int和Integer有什麼差別?

答:Java是一個近乎純潔的面向對象程式設計語言,但是為了程式設計的友善還是引入了基本資料類型,但是為了能夠将這些基本資料類型當成對象操作,Java為每一個基本資料類型都引入了對應的包裝類型(wrapper class),int的包裝類就是Integer,從Java 5開始引入了自動裝箱/拆箱機制,使得二者可以互相轉換。

Java 為每個原始類型提供了包裝類型:

  • 原始類型: boolean,char,byte,short,int,long,float,double
  • 包裝類型:Boolean,Character,Byte,Short,Integer,Long,Float,Double

下列代碼可驗證自動裝箱/拆箱機制:

class AutoUnboxingTest { public static void main(String[] args) { Integer a = new Integer(3); Integer b = 3; // 将3自動裝箱成Integer類型 int c = 3; System.out.println(a == b); // false,兩個引用沒有引用同一對象 System.out.println(a == c); // true,a自動拆箱成int類型再和c比較 }}
           

另外,介紹一個相關的面試題,代碼如下所示:

public class Test03 { public static void main(String[] args) { Integer f1 = 100, f2 = 100, f3 = 150, f4 = 150; System.out.println(f1 == f2); System.out.println(f3 == f4); }}
           

分析:如果不明就裡很容易認為兩個輸出要麼都是true要麼都是false。首先需要注意的是f1、f2、f3、f4四個變量都是Integer對象引用,是以下面的==運算比較的不是值而是引用。裝箱的本質是什麼呢?當我們給一個Integer對象賦一個int值的時候,會調用Integer類的靜态方法valueOf,如果看看valueOf的源代碼就知道發生了什麼。

public static Integer valueOf(int i) { if (i >= IntegerCache.low && i <= IntegerCache.high) return IntegerCache.cache[i + (-IntegerCache.low)]; return new Integer(i);}
           

IntegerCache是Integer的内部類,其代碼如下所示:

/** * Cache to support the object identity semantics of autoboxing for values between * -128 and 127 (inclusive) as required by JLS. * * The cache is initialized on first usage. The size of the cache * may be controlled by the {@code -XX:AutoBoxCacheMax=} option. * During VM initialization, java.lang.Integer.IntegerCache.high property * may be set and saved in the private system properties in the * sun.misc.VM class. */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() { }}
           

簡單的說,如果整型字面量的值在-128到127之間,那麼不會new新的Integer對象,而是直接引用常量池中的Integer對象,是以上面的面試題中f1==f2的結果是true,而f3==f4的結果是false。

8. &和&&的差別?

答:&運算符有兩種用法:(1)按位與;(2)邏輯與。&&運算符是短路與運算。邏輯與跟短路與的差别是非常巨大的,雖然二者都要求運算符左右兩端的布爾值都是true整個表達式的值才是true。&&之是以稱為短路運算是因為,如果&&左邊的表達式的值是false,右邊的表達式會被直接短路掉,不會進行運算。很多時候我們可能都需要用&&而不是&,例如在驗證使用者登入時判定使用者名不是null而且不是空字元串,應當寫為:username != null &&!username.equals(""),二者的順序不能交換,更不能用&運算符,因為第一個條件如果不成立,根本不能進行字元串的equals比較,否則會産生NullPointerException異常。注意:邏輯或運算符(|)和短路或運算符(||)的差别也是如此。

9. 解釋記憶體中的棧(stack)、堆(heap)和靜态區(static area)的用法

答:通常我們定義一個基本資料類型的變量,一個對象的引用,還有就是函數調用的現場儲存都使用記憶體中的棧空間;而通過new關鍵字和構造器建立的對象放在堆空間;程式中的字面量(literal)如直接書寫的100、"hello"和常量都是放在靜态區中。棧空間操作起來最快但是棧很小,通常大量的對象都是放在堆空間,理論上整個記憶體沒有被其他程序使用的空間甚至硬碟上的虛拟記憶體都可以被當成堆空間來使用。

String str = new String("hello");
           

上面語句中的str放在棧上,用new建立出來的字元串對象放在堆上,而"hello"這個字面量放在靜态區。

10. Math.round(11.5) 等于多少?Math.round(-11.5)等于多少?

答:Math.round(11.5)的傳回值是12,Math.round(-11.5)的傳回值是-11。四舍五入的原理是在參數上加0.5然後進行下取整。

11. swtich 是否能作用在byte 上,是否能作用在long 上,是否能作用在String上?

答:在Java 5以前,switch(expr)中,expr隻能是byte、short、char、int。從Java 5開始,Java中引入了枚舉類型,expr也可以是enum類型,從Java 7開始,expr還可以是字元串(String),但是長整型(long)在目前所有的版本中都是不可以的。

12. 用最有效率的方法計算2乘以8?

答:2 << 3(左移3位相當于乘以2的3次方,右移3位相當于除以2的3次方)。

補充: 我們為編寫的類重寫hashCode方法時,可能會看到如下所示的代碼,其實我們不太了解為什麼要使用這樣的乘法運算來産生哈希碼(散列碼),而且為什麼這個數是個素數,為什麼通常選擇31這個數?前兩個問題的答案你可以自己百度一下,選擇31是因為可以用移位和減法運算來代替乘法,進而得到更好的性能。說到這裡你可能已經想到了:31 * num 等價于(num << 5) - num,左移5位相當于乘以2的5次方再減去自身就相當于乘以31,現在的VM都能自動完成這個優化。
public class PhoneNumber { private int areaCode; private String prefix; private String lineNumber; @Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + areaCode; result = prime * result + ((lineNumber == null) ? 0 : lineNumber.hashCode()); result = prime * result + ((prefix == null) ? 0 : prefix.hashCode()); return result; } @Override public boolean equals(Object obj) { if (this == obj) return true; if (obj == null) return false; if (getClass() != obj.getClass()) return false; PhoneNumber other = (PhoneNumber) obj; if (areaCode != other.areaCode) return false; if (lineNumber == null) { if (other.lineNumber != null) return false; } else if (!lineNumber.equals(other.lineNumber)) return false; if (prefix == null) { if (other.prefix != null) return false; } else if (!prefix.equals(other.prefix)) return false; return true; }}
           

自己寫hashcode和equals方法容易出錯,我一般使用commons-lang工具包中的工具:

  • org.apache.commons.lang.builder.EqualsBuilder
  • org.apache.commons.lang.builder.HashCodeBuilder

例子代碼如下:

package org.test.spittr.data;import org.apache.commons.lang.builder.EqualsBuilder;import org.apache.commons.lang.builder.HashCodeBuilder;import java.util.Date;public class Spittle { private final Long id; private final String message; private final Date time; private Double latitude; private Double longitude; public Spittle(String message, Date time) { this(message, time, null, null); } public Spittle(String message,Date time, Double latitude, Double longitude) { this.id = null; this.time = time; this.latitude = latitude; this.longitude = longitude; this.message = message; } @Override public boolean equals(Object obj) { return EqualsBuilder.reflectionEquals(this, obj, new String[]{"message
           

繼續閱讀