2021年最新Java面試題及答案整理 --- 基礎篇(一)

1.什麼是Java

Java是一門面向對象的高級編程語言,不只吸取了C++語言的各類優勢,好比繼承了C++語言面嚮對象的技術核心。還摒棄了C++裏難以理解的多繼承、指針等概念,,同時也增長了垃圾回收機制,釋放掉不被使用的內存空間,解決了管理內存空間的煩惱。java

所以Java語言具備功能強大和簡單易用兩個特徵。Java語言做爲靜態面向對象編程語言的表明,極好地實現了面向對象理論,容許程序員以優雅的思惟方式進行復雜的編程 。程序員

2. Java的特色有哪些

Java 語言是一種分佈式的面嚮對象語言,具備面向對象、平臺無關性、簡單性、解釋執行、多線程、安全性等不少特色,下面針對這些特色進行逐一介紹。web

1. 面向對象面試

Java 是一種面向對象的語言,它對對象中的類、對象、繼承、封裝、多態、接口、包等均有很好的支持。爲了簡單起見,Java 只支持類之間的單繼承,可是可使用接口來實現多繼承。使用 Java 語言開發程序,須要採用面向對象的思想設計程序和編寫代碼。編程

2. 平臺無關性數組

平臺無關性的具體表如今於,Java 是「一次編寫,處處運行(Write Once,Run any Where)」的語言,所以採用 Java 語言編寫的程序具備很好的可移植性,而保證這一點的正是 Java 的虛擬機機制。在引入虛擬機以後,Java 語言在不一樣的平臺上運行不須要從新編譯。tomcat

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 的「一次編寫,處處執行」正是它吸引衆多商家和編程人員的一大優點。

24W字Java面試手冊下載地址: https://shimo.im/docs/Wyj8QRp...

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。

這八種基本類型都有對應的包裝類分別爲:Byte、Short、Integer、Long、Float、Double、Character、Boolean

類型名稱 字節、位數 最小值 最大值 默認值 例子
byte字節 1字節,8位 -128(-2^7) 127(2^7-1) 0 byte a = 100,byte b = -50
short短整型 2字節,16位 -32768(-2^15) 32767(2^15 - 1) 0 short s = 1000,short r = -20000
int整形 4字節,32位 -2,147,483,648(-2^31) 2,147,483,647(2^31 - 1) 0 int a = 100000, int b = -200000
lang長整型 8字節,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
double雙精度 8字節,64位 double類型一樣不能表示精確的值,如貨幣 0.0d double d1 = 123.4
float單精度 4字節,32位 在儲存大型浮點數組的時候可節省內存空間 不一樣統計精準的貨幣值 0.0f float f1 = 234.5f
char字符 2字節,16位 \u0000(即爲0) \uffff(即爲65,535) 能夠儲存任何字符 char letter = 'A';
boolean布爾 返回true和false兩個值 這種類型只做爲一種標誌來記錄 true/false 狀況; 只有兩個取值:true 和 false; false boolean one = true

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

引用數據類型分3種:類,接口,數組;

簡單來講,只要不是基本數據類型.都是引用數據類型。 那他們有什麼不一樣呢?

一、從概念方面來講

1,基本數據類型:變量名指向具體的數值

2,引用數據類型:變量名不是指向具體的數值,而是指向存數據的內存地址,.也及時hash值

二、從內存的構建方面來講(內存中,有堆內存和棧內存二者)

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;
24W字Java面試手冊下載地址: https://shimo.im/docs/Wyj8QRp...

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. 爲何要有包裝類型?

讓基本數據類型也具備對象的特徵

基本類型 包裝器類型
boolean Boolean
char Character
int Integer
byte Byte
short Short
long Long
float Float
double Double

爲了讓基本類型也具備對象的特徵,就出現了包裝類型(如咱們在使用集合類型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);
}

兩者的區別:

  1. 聲明方式不一樣:基本類型不使用new關鍵字,而包裝類型須要使用new關鍵字來在堆中分配存儲空間
  2. 存儲方式及位置不一樣:基本類型是直接將變量值存儲在棧中,而包裝類型是將對象放在堆中,而後經過引用來使用;
  3. 初始值不一樣:基本類型的初始值如int爲0,boolean爲false,而包裝類型的初始值爲null;
  4. 使用方式不一樣:基本類型直接賦值直接使用就好,而包裝類型在集合如Collection、Map時會使用到。
24W字Java面試手冊下載地址: https://shimo.im/docs/Wyj8QRp...

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;

+=操做符會對右邊的表達式結果強轉匹配左邊的數據類型,因此沒錯.

11. 能將 int 強制轉換爲 byte 類型的變量嗎?若是該值大於 byte 類型的範圍,將會出現什麼現象?

咱們能夠作強制轉換,可是 Java 中 int 是 32 位的,而 byte 是 8 位的,因此,若是強制轉化,int 類型的高 24 位將會被丟棄,由於byte 類型的範圍是從 -128 到 127

12. Java程序是如何執行的

咱們平常的工做中都使用開發工具(IntelliJ IDEA 或 Eclipse 等)能夠很方便的調試程序,或者是經過打包工具把項目打包成 jar 包或者 war 包,放入 Tomcat 等 Web 容器中就能夠正常運行了,但你有沒有想過 Java 程序內部是如何執行的?其實不管是在開發工具中運行仍是在 Tomcat 中運行,Java 程序的執行流程基本都是相同的,它的執行流程以下:

  • 先把 Java 代碼編譯成字節碼,也就是把 .java 類型的文件編譯成 .class 類型的文件。這個過程的大體執行流程:Java 源代碼 -> 詞法分析器 -> 語法分析器 -> 語義分析器 -> 字符碼生成器 -> 最終生成字節碼,其中任何一個節點執行失敗就會形成編譯失敗;
  • 把 class 文件放置到 Java 虛擬機,這個虛擬機一般指的是 Oracle 官方自帶的 Hotspot JVM;
  • Java 虛擬機使用類加載器(Class Loader)裝載 class 文件;
  • 類加載完成以後,會進行字節碼效驗,字節碼效驗經過以後 JVM 解釋器會把字節碼翻譯成機器碼交由操做系統執行。但不是全部代碼都是解釋執行的,JVM 對此作了優化,好比,以 Hotspot 虛擬機來講,它自己提供了 JIT(Just In Time)也就是咱們一般所說的動態編譯器,它可以在運行時將熱點代碼編譯爲機器碼,這個時候字節碼就變成了編譯執行。Java 程序執行流程圖以下:

13. final 在 Java 中有什麼做用?

final做爲Java中的關鍵字能夠用於三個地方。用於修飾類、類屬性和類方法。

特徵:凡是引用final關鍵字的地方皆不可修改!

(1)修飾類:表示該類不能被繼承;

(2)修飾方法:表示方法不能被重寫;

(3)修飾變量:表示變量只能一次賦值之後值不能被修改(常量)。

14. final有哪些用法?

final也是不少面試喜歡問的地方,但我以爲這個問題很無聊,一般能回答下如下5點就不錯了:

  • 被final修飾的類不能夠被繼承
  • 被final修飾的方法不能夠被重寫
  • 被final修飾的變量不能夠被改變.若是修飾引用,那麼表示引用不可變,引用指向的內容可變.
  • 被final修飾的方法,JVM會嘗試將其內聯,以提升運行效率
  • 被final修飾的常量,在編譯階段會存入常量池中.

除此以外,編譯器對final域要遵照的兩個重排序規則更好:

在構造函數內對一個final域的寫入,與隨後把這個被構造對象的引用賦值給一個引用變量,這兩個操做之間不能重排序 初次讀一個包含final域的對象的引用,與隨後初次讀這個final域,這兩個操做之間不能重排序.

15. static都有哪些用法?

全部的人都知道static關鍵字這兩個基本的用法:靜態變量和靜態方法.也就是被static所修飾的變量/方法都屬於類的靜態資源,類實例所共享.

除了靜態變量和靜態方法以外,static也用於靜態塊,多用於初始化操做:

public calss PreCache{
    static{
        //執行相關操做
    }
}

此外static也多用於修飾內部類,此時稱之爲靜態內部類.

最後一種用法就是靜態導包,即import static.import static是在JDK 1.5以後引入的新特性,能夠用來指定導入某個類中的靜態資源,而且不須要使用類名,能夠直接使用資源名,好比:

import static java.lang.Math.*;
 
public class Test{
 
    public static void main(String[] args){
        //System.out.println(Math.sin(20));傳統作法
        System.out.println(sin(20));
    }
}

16. static和final區別

關鍵詞 修飾物 影響
final 變量 分配到常量池中,程序不可改變其值
final 方法 子類中將不能被重寫
final 不能被繼承
static 變量 分配在內存堆上,引用都會指向這一個地址而不會從新分配內存
static 方法塊 虛擬機優先加載
static 能夠直接經過類來調用而不須要new

17. 爲何有些java類要實現Serializable接口

爲了網絡進行傳輸或者持久化

什麼是序列化

將對象的狀態信息轉換爲能夠存儲或傳輸的形式的過程

除了實現Serializable接口還有什麼序列化方式

  • Json序列化
  • FastJson序列化
  • ProtoBuff序列化

18. 什麼是java序列化,如何實現java序列化?或者請解釋Serializable接口的做用。

咱們有時候將一個java對象變成字節流的形式傳出去或者從一個字節流中恢復成一個java對象,例如,要將java對象存儲到硬盤或者傳送給網絡上的其餘計算機,這個過程咱們能夠本身寫代碼去把一個java對象變成某個格式的字節流再傳輸。

可是,jre自己就提供了這種支持,咱們能夠調用OutputStreamwriteObject方法來作,若是要讓java幫咱們作,要被傳輸的對象必須實現serializable接口,這樣,javac編譯時就會進行特殊處理,編譯的類才能夠被writeObject方法操做,這就是所謂的序列化。須要被序列化的類必須實現Serializable接口,該接口是一個mini接口,其中沒有須要實現方法,implements Serializable只是爲了標註該對象是可被序列化的。

例如,在web開發中,若是對象被保存在了Session中,tomcat在重啓時要把Session對象序列化到硬盤,這個對象就必須實現Serializable接口。若是對象要通過分佈式系統進行網絡傳輸,被傳輸的對象就必須實現Serializable接口。

19. 什麼是內部類?內部類的做用

內部類的定義

將一個類定義在另外一個類裏面或者一個方法裏面,這樣的類稱爲內部類。

內部類的做用:

一、成員內部類 成員內部類能夠無條件訪問外部類的全部成員屬性和成員方法(包括private成員和靜態成員)。 當成員內部類擁有和外部類同名的成員變量或者方法時,會發生隱藏現象,即默認狀況下訪問的是成員內部類的成員。

二、局部內部類 局部內部類是定義在一個方法或者一個做用域裏面的類,它和成員內部類的區別在於局部內部類的訪問僅限於方法內或者該做用域內。

三、匿名內部類 匿名內部類就是沒有名字的內部類

四、靜態內部類 指被聲明爲static的內部類,他能夠不依賴內部類而實例,而一般的內部類須要實例化外部類,從而實例化。靜態內部類不能夠有與外部類有相同的類名。不能訪問外部類的普通成員變量,可是能夠訪問靜態成員變量和靜態方法(包括私有類型) 一個 靜態內部類去掉static 就是成員內部類,他能夠自由的引用外部類的屬性和方法,不管是靜態仍是非靜態。可是不能夠有靜態屬性和方法

24W字Java面試手冊下載地址: https://shimo.im/docs/Wyj8QRp...

20. Excption與Error包結構

Java可拋出(Throwable)的結構分爲三種類型:被檢查的異常(CheckedException)運行時異常(RuntimeException)錯誤(Error)

一、運行時異常

定義:RuntimeException及其子類都被稱爲運行時異常。

特色:Java編譯器不會檢查它。也就是說,當程序中可能出現這類異常時,假若既"沒有經過throws聲明拋出它",也"沒有用try-catch語句捕獲它",仍是會編譯經過。例如,除數爲零時產生的ArithmeticException異常,數組越界時產生的IndexOutOfBoundsException異常,fail-fast機制產生的ConcurrentModificationException異常(java.util包下面的全部的集合類都是快速失敗的,「快速失敗」也就是fail-fast,它是Java集合的一種錯誤檢測機制。當多個線程對集合進行結構上的改變的操做時,有可能會產生fail-fast機制。記住是有可能,而不是必定。例如:假設存在兩個線程(線程一、線程2),線程1經過Iterator在遍歷集合A中的元素,在某個時候線程2修改了集合A的結構(是結構上面的修改,而不是簡單的修改集合元素的內容),那麼這個時候程序就會拋出 ConcurrentModificationException 異常,從而產生fail-fast機制,這個錯叫併發修改異常。Fail-safe,java.util.concurrent包下面的全部的類都是安全失敗的,在遍歷過程當中,若是已經遍歷的數組上的內容變化了,迭代器不會拋出ConcurrentModificationException異常。若是未遍歷的數組上的內容發生了變化,則有可能反映到迭代過程當中。這就是ConcurrentHashMap迭代器弱一致的表現。ConcurrentHashMap的弱一致性主要是爲了提高效率,是一致性與效率之間的一種權衡。要成爲強一致性,就獲得處使用鎖,甚至是全局鎖,這就與Hashtable和同步的HashMap同樣了。)等,都屬於運行時異常。

常見的五種運行時異常:

  • ClassCastException(類轉換異常)
  • IndexOutOfBoundsException(數組越界)
  • NullPointerException(空指針異常)
  • ArrayStoreException(數據存儲異常,操做數組是類型不一致)
  • BufferOverflowException

二、被檢查異常

定義:Exception類自己,以及Exception的子類中除了"運行時異常"以外的其它子類都屬於被檢查異常。

特色 : Java編譯器會檢查它。 此類異常,要麼經過throws進行聲明拋出,要麼經過try-catch進行捕獲處理,不然不能經過編譯。例如,CloneNotSupportedException就屬於被檢查異常。

當經過clone()接口去克隆一個對象,而該對象對應的類沒有實現Cloneable接口,就會拋出CloneNotSupportedException異常。被檢查異常一般都是能夠恢復的。 如:

IOException

FileNotFoundException

SQLException

被檢查的異常適用於那些不是因程序引發的錯誤狀況,好比:讀取文件時文件不存在引起的FileNotFoundException。然而,不被檢查的異常一般都是因爲糟糕的編程引發的,好比:在對象引用時沒有確保對象非空而引發的NullPointerException

三、錯誤

定義 : Error類及其子類。

特色 : 和運行時異常同樣,編譯器也不會對錯誤進行檢查。

當資源不足、約束失敗、或是其它程序沒法繼續運行的條件發生時,就產生錯誤。程序自己沒法修復這些錯誤的。例如,VirtualMachineError就屬於錯誤。出現這種錯誤會致使程序終止運行。OutOfMemoryError、ThreadDeath。

Java虛擬機規範規定JVM的內存分爲了好幾塊,好比堆,棧,程序計數器,方法區等

24W字Java面試手冊下載地址: https://shimo.im/docs/Wyj8QRp...
相關文章
相關標籤/搜索