1. 程式人生 > 其它 >2021精選 Java面試題附答案 1-10

2021精選 Java面試題附答案 1-10

1.什麼是Java

Java是一門面向物件的高階程式語言,不僅吸收了C++語言的各種優點,比如繼承了C++語言面嚮物件的技術核心。還摒棄了C++裡難以理解的多繼承、指標等概念,,同時也增加了垃圾回收機制,釋放掉不被使用的記憶體空間,解決了管理記憶體空間的煩惱。

因此Java語言具有功能強大和簡單易用兩個特徵。Java語言作為靜態面向物件程式語言的代表,極好地實現了面向物件理論,允許程式設計師以優雅的思維方式進行復雜的程式設計 。

2. Java的特點有哪些

Java 語言是一種分散式的面嚮物件語言,具有面向物件、平臺無關性、簡單性、解釋執行、多執行緒、安全性等很多特點,下面針對這些特點進行逐一介紹。

1. 面向物件

Java 是一種面向物件的語言,它對物件中的類、物件、繼承、封裝、多型、介面、包等均有很好的支援。為了簡單起見,Java 只支援類之間的單繼承,但是可以使用介面來實現多繼承。使用 Java 語言開發程式,需要採用面向物件的思想設計程式和編寫程式碼。

2. 平臺無關性

平臺無關性的具體表現在於,Java 是“一次編寫,到處執行(Write Once,Run any Where)”的語言,因此採用 Java 語言編寫的程式具有很好的可移植性,而保證這一點的正是 Java 的虛擬機器機制。在引入虛擬機器之後,Java 語言在不同的平臺上執行不需要重新編譯。

Java 語言使用 Java 虛擬機器機制遮蔽了具體平臺的相關資訊,使得 Java 語言編譯的程式只需生成虛擬機器上的目的碼,就可以在多種平臺上不加修改地執行。

3. 簡單性

Java 語言的語法與 C 語言和 C++ 語言很相近,使得很多程式設計師學起來很容易。對 Java 來說,它捨棄了很多 C++ 中難以理解的特性,如操作符的過載和多繼承等,而且 Java 語言不使用指標,加入了垃圾回收機制,解決了程式設計師需要管理記憶體的問題,使程式設計變得更加簡單。

4. 解釋執行

Java 程式在 Java 平臺執行時會被編譯成位元組碼檔案,然後可以在有 Java 環境的作業系統上執行。在執行檔案時,Java 的直譯器對這些位元組碼進行解釋執行,執行過程中需要加入的類在連線階段被載入到執行環境中。

5. 多執行緒

Java 語言是多執行緒的,這也是 Java 語言的一大特性,它必須由 Thread 類和它的子類來建立。Java 支援多個執行緒同時執行,並提供多執行緒之間的同步機制。任何一個執行緒都有自己的 run() 方法,要執行的方法就寫在 run() 方法體內。

6. 分散式

Java 語言支援 Internet 應用的開發,在 Java 的基本應用程式設計介面中就有一個網路應用程式設計介面,它提供了網路應用程式設計的類庫,包括 URL、URLConnection、Socket 等。Java 的 RIM 機制也是開發分散式應用的重要手段。

7. 健壯性

Java 的強型別機制、異常處理、垃圾回收機制等都是 Java 健壯性的重要保證。對指標的丟棄是 Java 的一大進步。另外,Java 的異常機制也是健壯性的一大體現。

8. 高效能

Java 的高效能主要是相對其他高階指令碼語言來說的,隨著 JIT(Just in Time)的發展,Java 的執行速度也越來越高。

9. 安全性

Java 通常被用在網路環境中,為此,Java 提供了一個安全機制以防止惡意程式碼的攻擊。除了 Java 語言具有許多的安全特性以外,Java 還對通過網路下載的類增加一個安全防範機制,分配不同的名字空間以防替代本地的同名類,幷包含安全管理機制。

Java 語言的眾多特性使其在眾多的程式語言中佔有較大的市場份額,Java 語言對物件的支援和強大的 API 使得程式設計工作變得更加容易和快捷,大大降低了程式的開發成本。Java 的“一次編寫,到處執行”正是它吸引眾多商家和程式設計人員的一大優勢。

3. JDK和JRE和JVM的區別

1. JDK

JDK(Java SE Development Kit),Java標準的開發包,提供了編譯、執行Java程式所需要的各種工具和資源,包括了Java編譯器、Java執行時環境、以及常用的Java類庫等。

2. JRE

JRE(Java Runtime Environment),Java執行時環境,用於解釋執行Java的位元組碼檔案。普通使用者只需要安裝JRE來執行Java程式即可,而作為一名程式設計師必須安裝JDK,來編譯、除錯程式。

3. JVM

JVM(Java Virtual Mechinal),Java虛擬機器,是JRE的一部分。它是整個Java實現跨平臺的核心,負責解釋執行位元組碼檔案,是可執行Java位元組碼檔案的虛擬計算機。所有平臺上的JVM向編譯器提供相同的介面,而編譯器只需要面向虛擬機器,生成虛擬機器能識別的程式碼,然後由虛擬機器來解釋執行。

當使用Java編譯器編譯Java程式時,生成的是與平臺無關的位元組碼,這些位元組碼只面向JVM。也就是說JVM是執行Java位元組碼的虛擬機器。

不同平臺的JVM是不同的,但是他們都提供了相同的介面。JVM是Java程式跨平臺的關鍵部分,只要為不同平臺實現了相同的虛擬機器,編譯後的Java位元組碼就可以在該平臺上執行。

為什麼要採用位元組碼:

在 Java 中,JVM 可以理解的程式碼就叫做位元組碼(即Java原始碼經過虛擬機器編譯器編譯後副檔名為.class的檔案),它不面向任何特定的處理器,只面向虛擬機器。Java 語言通過位元組碼的方式,在一定程度上解決了傳統解釋型語言執行效率低的問題,同時又保留了解釋型語言可移植的特點。所以 Java 程式執行時比較高效,而且,由於位元組碼並不針對一種特定的機器,因此,Java 程式無須重新編譯便可在多種不同作業系統的計算機上執行。

什麼是跨平臺:

所謂跨平臺性,是指java語言編寫的程式,一次編譯後,可以在多個系統平臺上執行。

實現原理:Java程式是通過java虛擬機器在系統平臺上執行的,只要該系統可以安裝相應的java虛擬機器,該系統就可以執行java程式。

Java 程式從原始碼到執行需要三步:

4. 總結

(1)JDK 用於開發,JRE 用於執行java程式 ;如果只是執行Java程式,可以只安裝JRE,無序安裝JDK。

(2)JDk包含JRE,JDK 和 JRE 中都包含 JVM。

(3)JVM 是 Java 程式語言的核心並且具有平臺獨立性。

4. Oracle JDK 和 OpenJDK 的對比

Oracle JDK版本將每三年釋出一次,而OpenJDK版本每三個月釋出一次;

OpenJDK 是一個參考模型並且是完全開源的,而Oracle JDK是OpenJDK的一個實現,並不是完全開源的;

Oracle JDK 比 OpenJDK 更穩定。OpenJDK和Oracle JDK的程式碼幾乎相同,但Oracle JDK有更多的類和一些錯誤修復。因此,如果您想開發企業/商業軟體,我建議您選擇Oracle JDK,因為它經過了徹底的測試和穩定。某些情況下,有些人提到在使用OpenJDK 可能會遇到了許多應用程式崩潰的問題,但是,只需切換到Oracle JDK就可以解決問題;

在響應性和JVM效能方面,Oracle JDK與OpenJDK相比提供了更好的效能;

Oracle JDK不會為即將釋出的版本提供長期支援,使用者每次都必須通過更新到最新版本獲得支援來獲取最新版本;

Oracle JDK根據二進位制程式碼許可協議獲得許可,而OpenJDK根據GPL v2許可獲得許可。

5. Java有哪些資料型別

Java有 8 種基本資料型別,分別為:

6 種數字型別 (四個整數形,兩個浮點型):byte、short、int、long、float、double

1 種字元型別:char

1 種布林型:boolean。

byte:

byte 資料型別是8位、有符號的,以二進位制補碼錶示的整數;

最小值是-128(-2^7)

最大值是127(2^7-1)

預設值是0

byte 型別用在大型陣列中節約空間,主要代替整數,因為 byte 變數佔用的空間只有 int 型別的四分之一;

例子:byte a = 100,byte b = -50。

short:

short 資料型別是 16 位、有符號的以二進位制補碼錶示的整數

最小值是-32768(-2^15)

最大值是32767(2^15 - 1)

Short 資料型別也可以像 byte 那樣節省空間。一個short變數是int型變數所佔空間的二分之一;

預設值是0

例子:short s = 1000,short r = -20000。

int:

int 資料型別是32位、有符號的以二進位制補碼錶示的整數;

最小值是-2,147,483,648(-2^31)

最大值是2,147,483,647(2^31 - 1)

一般地整型變數預設為 int 型別;

預設值是0

例子:int a = 100000, int b = -200000。

long:

注意:Java 裡使用 long 型別的資料一定要在數值後面加上 L,否則將作為整型解析

long 資料型別是 64 位、有符號的以二進位制補碼錶示的整數;

最小值是-9,223,372,036,854,775,808(-2^63)

最大值是9,223,372,036,854,775,807(2^63 -1)

這種型別主要使用在需要比較大整數的系統上;

預設值是0L

例子: long a = 100000L,Long b = -200000L。

"L"理論上不分大小寫,但是若寫成"l"容易與數字"1"混淆,不容易分辯。所以最好大寫。

float:

float 資料型別是單精度、32位、符合IEEE 754標準的浮點數;

float 在儲存大型浮點陣列的時候可節省記憶體空間;

預設值是0.0f

浮點數不能用來表示精確的值,如貨幣;

例子:float f1 = 234.5f。

double:

double 資料型別是雙精度、64 位、符合IEEE 754標準的浮點數;

浮點數的預設型別為double型別;

double型別同樣不能表示精確的值,如貨幣;

預設值是0.0d

例子:double d1 = 123.4。

char:

char型別是一個單一的 16 位 Unicode 字元;

最小值是\u0000(即為 0);

最大值是\uffff(即為 65535);

char 資料型別可以儲存任何字元;

例子:char letter = 'A';(單引號

boolean:

boolean資料型別表示一位的資訊;

只有兩個取值:true 和 false;

這種型別只作為一種標誌來記錄 true/false 情況;

預設值是false

例子:boolean one = true。

6. Java中引用資料型別有哪些,它們與基本資料型別有什麼區別?

引用資料型別分3種:類,介面,陣列;

簡單來說,只要不是基本資料型別.都是引用資料型別。 那他們有什麼不同呢?

1、從概念方面來說

1,基本資料型別:變數名指向具體的數值

2,引用資料型別:變數名不是指向具體的數值,而是指向存資料的記憶體地址,.也及時hash值

2、從記憶體的構建方面來說(記憶體中,有堆記憶體和棧記憶體兩者)

1,基本資料型別:被建立時,在棧記憶體中會被劃分出一定的記憶體,並將數值儲存在該記憶體中.

2,引用資料型別:被建立時,首先會在棧記憶體中分配一塊空間,然後在堆記憶體中也會分配一塊具體的空間用來儲存資料的具體資訊,即hash值,然後由棧中引用指向堆中的物件地址.

舉個例子

//基本資料型別作為方法引數被呼叫

public class Main{

public static void main(String[] args){

//基本資料型別

int i = 1;

int j = 1;

double d = 1.2;

//引用資料型別

String str = "Hello";

String str1= "Hello";

}

}

由上圖可知,基本資料型別中會存在兩個相同的1,而引用型型別就不會存在相同的資料。

假如"hello"的引用地址是xxxxx1,宣告str變數並其賦值"hello"實際上就是讓str變數引用了"hello"的記憶體地址,這個記憶體地址就儲存在堆記憶體中,是不會改變的,當再次宣告變數str1也是賦值為"hello"時,此時就會在堆記憶體中查詢是否有"hello"這個地址,如果堆記憶體中已經存在這個地址了,就不會再次建立了,而是讓str1變數也指向xxxxx1這個地址,如果沒有的話,就會重新建立一個地址給str1變數。

7. 從使用方面來說

1,基本資料型別:判斷資料是否相等,用和!=判斷。

2,引用資料型別:判斷資料是否相等,用equals()方法,和!=是比較數值的。而equals()方法是比較記憶體地址的。

補充:資料型別選擇的原則

如果要表示整數就使用int,表示小數就使用double;

如果要描述日期時間數字或者表示檔案(或記憶體)大小用long;

如果要實現內容傳遞或者編碼轉換使用byte;

如果要實現邏輯的控制,可以使用booleam;

如果要使用中文,使用char避免中文亂碼;

如果按照儲存範圍:byte < int < long < double;

8. Java中的自動裝箱與拆箱

什麼是自動裝箱拆箱?

從下面的程式碼中就可以看到裝箱和拆箱的過程

//自動裝箱

Integer total = 99;

//自定拆箱

int totalprim = total;

裝箱就是自動將基本資料型別轉換為包裝器型別;拆箱就是自動將包裝器型別轉換為基本資料型別。

在Java SE5之前,自動裝箱要這樣寫:Integer i =new` `Integer(10``);

對於Java的自動裝箱和拆箱,我們看看原始碼編譯後的class檔案,其實裝箱呼叫包裝類的valueOf方法,拆箱呼叫的是Integer.Value方法,下面就是變編譯後的程式碼:

常見面試一:

這段程式碼輸出什麼?

public class Main {

  public static void main(String[] args) {



    Integer i1 = 100;

    Integer i2 = 100;

    Integer i3 = 200;

    Integer i4 = 200;



    System.out.println(i1==i2);

    System.out.println(i3==i4);

  }

}

答案是:

true

false

為什麼會出現這樣的結果?輸出結果表明i1和i2指向的是同一個物件,而i3和i4指向的是不同的物件。此時只需一看原始碼便知究竟,下面這段程式碼是Integer的valueOf方法的具體實現:

public static Integer valueOf(int i) {

    if(i >= -128 && i <= IntegerCache.high)

      return IntegerCache.cache[i + 128];

    else

      return new Integer(i);

  }

private static class IntegerCache {

    static final int high;

    static final Integer cache[];

    static {

      final int low = -128;

      // high value may be configured by property

      int h = 127;

      if (integerCacheHighPropValue != null) {

        // Use Long.decode here to avoid invoking methods that

        // require Integer's autoboxing cache to be initialized

        int i = Long.decode(integerCacheHighPropValue).intValue();

        i = Math.max(i, 127);

        // Maximum array size is Integer.MAX_VALUE

        h = Math.min(i, Integer.MAX_VALUE - -low);

      }

      high = h;

      cache = new Integer[(high - low) + 1];

      int j = low;

      for(int k = 0; k < cache.length; k++)

        cache[k] = new Integer(j++);

    }

    private IntegerCache() {}

  }

從這2段程式碼可以看出,在通過valueOf方法建立Integer物件的時候,如果數值在[-128,127]之間,便返回指向IntegerCache.cache中已經存在的物件的引用;否則建立一個新的Integer物件。

上面的程式碼中i1和i2的數值為100,因此會直接從cache中取已經存在的物件,所以i1和i2指向的是同一個物件,而i3和i4則是分別指向不同的物件。

常見面試二:

public class Main {

  public static void main(String[] args) {



    Double i1 = 100.0;

    Double i2 = 100.0;

    Double i3 = 200.0;

    Double i4 = 200.0;



    System.out.println(i1==i2);

    System.out.println(i3==i4);

  }

}

輸出結果為:

false

false

原因很簡單,在某個範圍內的整型數值的個數是有限的,而浮點數卻不是。

9. 為什麼要有包裝型別?

讓基本資料型別也具有物件的特徵

為了讓基本型別也具有物件的特徵,就出現了包裝型別(如我們在使用集合型別Collection時就一定要使用包裝型別而非基本型別)因為容器都是裝object的,這是就需要這些基本型別的包裝器類了。

自動裝箱:new Integer(6);,底層呼叫:Integer.valueOf(6)

自動拆箱:int i = new Integer(6);,底層呼叫i.intValue();方法實現。

Integer i = 6;

Integer j = 6;

System.out.println(i==j);

答案在下面這段程式碼中找:

public static Integer valueOf(int i) {

  if (i >= IntegerCache.low && i <= IntegerCache.high)

    return IntegerCache.cache[i + (-IntegerCache.low)];

  return new Integer(i);

}

二者的區別:

宣告方式不同:基本型別不使用new關鍵字,而包裝型別需要使用new關鍵字來在堆中分配儲存空間

儲存方式及位置不同:基本型別是直接將變數值儲存在棧中,而包裝型別是將物件放在堆中,然後通過引用來使用;

初始值不同:基本型別的初始值如int為0,boolean為false,而包裝型別的初始值為null;

使用方式不同:基本型別直接賦值直接使用就好,而包裝型別在集合如Collection、Map時會使用到。

10. a=a+b與a+=b有什麼區別嗎?

+=操作符會進行隱式自動型別轉換,此處a+=b隱式的將加操作的結果型別強制轉換為持有結果的型別,而a=a+b則不會自動進行型別轉換.如:

byte a = 127;

byte b = 127;

b = a + b; // 報編譯錯誤:cannot convert from int to byte

b += a;

以下程式碼是否有錯,有的話怎麼改?

short s1= 1;

s1 = s1 + 1;

有錯誤.short型別在進行運算時會自動提升為int型別,也就是說s1+1的運算結果是int型別,而s1是short型別,此時編譯器會報錯.

正確寫法:

short s1= 1;

s1 += 1;

+=操作符會對右邊的表示式結果強轉匹配左邊的資料型別,所以沒錯.

從頭到腳,注重細節

認真學習,找到工作

面試心不慌,答題手不晃

面試通過,記得點贊