面試基礎題集錦-持續更新

Thread類的sleep()方法和對象的wait()方法均可以讓線程暫停執行,它們有什麼區別? 

sleep()方法(休眠)是線程類(Thread)的靜態方法,調用此方法會讓當前線程暫停執行指定的時間,將執行機會(CPU)讓給其餘線程,可是對象的鎖依然保持,所以休眠時間結束後會自動恢復(線程回到就緒狀態,請參考第66題中的線程狀態轉換圖)。wait()是Object類的方法,調用對象的wait()方法致使當前線程放棄對象的鎖(線程暫停執行),進入對象的等待池(wait pool),只有調用對象的notify()方法(或notifyAll()方法)時才能喚醒等待池中的線程進入等鎖池(lock pool),若是線程從新得到對象的鎖就能夠進入就緒狀態。java

日期和時間

Java的時間日期API一直以來都是被詬病的東西,爲了解決這一問題,Java 8中引入了新的時間日期API,其中包括LocalDate、LocalTime、LocalDateTime、Clock、Instant等類,這些的類的設計都使用了不變模式,所以是線程安全的設計。面試

建立java.util.Calendar 實例,調用其get()方法傳入不一樣的參數便可得到參數所對應的值。Java 8中可使用java.time.LocalDateTimel來獲取。編程

public class DateTimeTest {
    public static void main(String[] args) {
        Calendar cal = Calendar.getInstance();
        System.out.println(cal.get(Calendar.YEAR));
        System.out.println(cal.get(Calendar.MONTH));    // 0 - 11
        System.out.println(cal.get(Calendar.DATE));
        System.out.println(cal.get(Calendar.HOUR_OF_DAY));
        System.out.println(cal.get(Calendar.MINUTE));
        System.out.println(cal.get(Calendar.SECOND));

        // Java 8
        LocalDateTime dt = LocalDateTime.now();
        System.out.println(dt.getYear());
        System.out.println(dt.getMonthValue());     // 1 - 12
        System.out.println(dt.getDayOfMonth());
        System.out.println(dt.getHour());
        System.out.println(dt.getMinute());
        System.out.println(dt.getSecond());
    }
}

如下方法都可得到該毫秒數。安全

Calendar.getInstance().getTimeInMillis(); ide

System.currentTimeMillis(); 函數

Clock.systemDefaultZone().millis(); // Java 8性能

獲取某月最後一天

Calendar time = Calendar.getInstance(); ui

time.getActualMaximum(Calendar.DAY_OF_MONTH);spa

利用java.text.DataFormat 的子類(如SimpleDateFormat類)中的format(Date)方法可將日期格式化。Java 8中能夠用線程

格式化時間日期

class DateFormatTest {

    public static void main(String[] args) {
        SimpleDateFormat oldFormatter = new SimpleDateFormat("yyyy/MM/dd");
        Date date1 = new Date();
        System.out.println(oldFormatter.format(date1));

        // Java 8
        DateTimeFormatter newFormatter = DateTimeFormatter.ofPattern("yyyy/MM/dd");
        LocalDate date2 = LocalDate.now();
        System.out.println(date2.format(newFormatter));
    }
}

打印昨天的當前時刻

class YesterdayCurrent {
    public static void main(String[] args){
        Calendar cal = Calendar.getInstance();
        cal.add(Calendar.DATE, -1);
        System.out.println(cal.getTime());

        LocalDateTime today = LocalDateTime.now();
        LocalDateTime yesterday = today.minusDays(1);
        System.out.println(yesterday);
    }
}

如何實現字符串的反轉及替換? 

方法不少,能夠本身寫實現也可使用String或StringBuffer/StringBuilder中的方法。有一道很常見的面試題是用遞歸實現字符串反轉,代碼以下所示:

public static String reverse(String originStr) {
        if(originStr == null || originStr.length() <= 1) 
            return originStr;
        return reverse(originStr.substring(1)) + originStr.charAt(0);
    }
 

類初始化順序示例

class A {

    static {
        System.out.print("1");
    }

    public A() {
        System.out.print("2");
    }
}

class B extends A{

    static {
        System.out.print("a");
    }

    public B() {
        System.out.print("b");
    }
}

public class Hello {

    public static void main(String[] args) {
        A ab = new B();
        ab = new B();
    }

}

執行結果:1a2b2b。建立對象時構造器的調用順序是:先初始化靜態成員,而後調用父類構造器,再初始化非靜態成員,最後調用自身構造器。

靜態嵌套類(Static Nested Class)和內部類(Inner Class)的不一樣? 

Static Nested Class是被聲明爲靜態(static)的內部類,它能夠不依賴於外部類實例被實例化。而一般的內部類須要在外部類實例化後才能實例化。

面向對象的特徵有哪些方面?

- 抽象:抽象是將一類對象的共同特徵總結出來構造類的過程,包括數據抽象和行爲抽象兩方面。抽象只關注對象有哪些屬性行爲,並不關注行爲的細節

- 繼承:繼承是從已有類獲得繼承信息建立新類的過程。提供繼承信息的類被稱爲父類(超類、基類);獲得繼承信息的類被稱爲子類(派生類)。 

- 封裝:一般認爲封裝是把數據和操做數據的方法綁定起來,對數據的訪問只能經過已定義的接口。面向對象的本質就是將現實世界描繪成一系列徹底自治、封閉的對象。咱們在類中編寫的方法就是對實現細節的一種封裝;咱們編寫一個類就是對數據和數據操做的封裝。能夠說,封裝就是隱藏一切可隱藏的東西,只向外界提供最簡單的編程接口能夠想一想java和彙編的差異,明顯java封裝更好所以操做起來更簡單。

- 多態性:多態性是指容許不一樣子類型的對象對同一消息做出不一樣的響應。簡單的說就是用一樣的對象引用調用一樣的方法可是作了不一樣的事情。多態性分爲編譯時的多態性和運行時的多態性方法重載(overload)實現的是編譯時的多態性(也稱爲前綁定),而方法重寫(override)實現的是運行時的多態性(也稱爲後綁定)。運行時的多態是面向對象最精髓的東西,要實現多態須要作兩件事:1). 方法重寫(子類繼承父類並重寫父類中已有的或抽象的方法);2). 對象造型(用父類型引用子類型對象,這樣一樣的引用調用一樣的方法就會根據子類對象的不一樣而表現出不一樣的行爲)。

訪問修飾符public,private,protected,以及不寫(默認)時的區別?

修飾符 當前類 同 包 子 類 其餘包
public
protected ×
default × ×
private × × ×

類的成員不寫訪問修飾時默認爲default。默認對於同一個包中的其餘類至關於公開(public),對於不是同一個包中的其餘類至關於私有(private)。受保護(protected)對子類至關於公開,對不是同一包中的沒有父子關係的類至關於私有。Java中,外部類的修飾符只能是public或默認,類的成員(包括內部類)的修飾符能夠是以上四種。

String 是最基本的數據類型嗎?

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

解釋內存中的棧(stack)、堆(heap)和靜態區(static area)的用法。

一般咱們定義一個基本數據類型的變量,一個對象的引用,還有就是函數調用的現場保存都使用內存中的棧空間;而經過new關鍵字和構造器建立的對象放在堆空間;程序中的字面量(literal)如直接書寫的100、」hello」和常量都是放在靜態區中。棧空間操做起來最快可是棧很小,一般大量的對象都是放在堆空間,硬盤上的虛擬內存均可以被當成堆空間來使用。

String str = new String("hello");

上面的語句中變量str放在棧上,用new建立出來的字符串對象放在堆上,而」hello」這個字面量放在靜態區。較新版本的Java(從Java 6的某個更新開始)中使用了一項叫」逃逸分析」的技術,能夠將一些局部對象放在棧上以提高對象的操做性能。

Math.round(11.5) 等於多少?Math.round(-11.5)等於多少?

Math.round(11.5)的返回值是12,Math.round(-11.5)的返回值是-11。四捨五入的原理是在參數上加0.5而後進行取整。

switch 是否能做用在byte 上,是否能做用在long 上,是否能做用在String上?

在Java 5之前,switch(expr)中,expr只能是byte、short、char、int。從Java 5開始,Java中引入了枚舉類型,expr也能夠是enum類型,從Java 7開始,expr還能夠是字符串(String),可是長整型(long)在目前全部的版本中都是不能夠的。

用最有效率的方法計算2乘以8? hashcode計算的時候prime爲何一般選擇31這個數?

2 << 3(左移3位至關於乘以2的3次方,右移3位至關於除以2的3次方)。選擇31是由於能夠用移位和減法運算來代替乘法,從而獲得更好的性能。31 * num 等價於(num << 5) – num。

在Java中,如何跳出當前的多重嵌套循環?

在最外層循環前加一個標記如A,而後用break A;能夠跳出多重循環。(Java中支持帶標籤的break和continue語句,做用有點相似於C和C++中的goto語句,可是就像要避免使用goto同樣,應該避免使用帶標籤的break和continue,由於它不會讓你的程序變得更優雅,不少時候甚至有相反的做用,因此這種語法其實不知道更好)

兩個對象值相同(x.equals(y) == true),但卻可有不一樣的hash code,這句話對不對?

不對,若是兩個對象x和y知足x.equals(y) == true,它們的哈希碼(hash code)應當相同。Java對於eqauls方法和hashCode方法是這樣規定的:(1)若是兩個對象相同(equals方法返回true),那麼它們的hashCode值必定要相同;(2)若是兩個對象的hashCode相同,它們並不必定相同。固然,你未必要按照要求去作,可是若是你違背了上述原則就會發如今使用容器時,相同的對象能夠出如今Set集合中,同時增長新元素的效率會大大降低(對於使用哈希存儲的系統,若是哈希碼頻繁的衝突將會形成存取性能急劇降低)。

首先equals方法必須知足自反性(x.equals(x)必須返回true)、對稱性(x.equals(y)返回true時,y.equals(x)也必須返回true)、傳遞性(x.equals(y)和y.equals(z)都返回true時,x.equals(z)也必須返回true)和一致性(當x和y引用的對象信息沒有被修改時,屢次調用x.equals(y)應該獲得一樣的返回值),並且對於任何非null值的引用x,x.equals(null)必須返回false。實現高質量的equals方法的訣竅包括:1. 使用==操做符檢查」參數是否爲這個對象的引用」;2. 使用instanceof操做符檢查」參數是否爲正確的類型」;3. 對於類中的關鍵屬性,檢查參數傳入對象的屬性是否與之相匹配;4. 編寫完equals方法後,問本身它是否知足對稱性、傳遞性、一致性;5. 重寫equals時老是要重寫hashCode;6. 不要將equals方法參數中的Object對象替換爲其餘的類型,在重寫時不要忘掉@Override註解。

是否能夠繼承String類?

String 類是final類,不能夠被繼承。繼承String自己就是一個錯誤的行爲,對String類型最好的重用方式是關聯關係(Has-A)和依賴關係(Use-A)而不是繼承關係(Is-A)。

String和StringBuilder、StringBuffer的區別?

Java平臺提供了兩種類型的字符串:String和StringBuffer/StringBuilder,它們能夠儲存和操做字符串。其中String是隻讀字符串,也就意味着String引用的字符串內容是不能被改變的。而StringBuffer/StringBuilder類表示的字符串對象能夠直接進行修改。StringBuilder是Java 5中引入的,它和StringBuffer的方法徹底相同,區別在於它是在單線程環境下使用的,由於它的全部方面都沒有被synchronized修飾,所以它的效率也比StringBuffer要高。

相關文章
相關標籤/搜索