阿里P8架構師爆出:就是依靠這套面試題進的阿里,進阿里不再難!

前言

這個是對基礎的一個考察,考察的知識點比較多,而且比較雜,一個內推人員告訴我,要準備接下來的面試,還是技術面,主要是使用到的技術的一個考察,而且基礎比較重要。因此,這兩天整理的步伐會加快

本套面試題還是從網絡收集,非原創,每一個知識點,我都沒有直接複製,大致看了一下如何描述的更加清楚怎麼來。

一、java概述

1、什麼是編程?

編程就是讓計算機為解決某個問題而使用某種程序設計語言編寫程序代碼,並最終得到結果的過程。

為了使計算機能夠理解人的意圖,人類就必須要將需解決的問題的思路、方法、和手段通過計算機能夠理解的形式告訴計算機,使得計算機能夠根據人的指令一步一步去工作,完成某種特定的任務。這種人和計算機之間交流的過程就是編程。

2、什麼是Java

Java是一門面向對象編程語言,不僅吸收了C++語言的各種優點,還摒棄了C++裡難以理解的多繼承、指針等概念,因此Java語言具有功能強大和簡單易用兩個特徵。Java語言作為靜態面向對象編程語言的代表,極好地實現了面向對象理論,允許程序員以優雅的思維方式進行復雜的編程 。

3、JVM、JRE和JDK的關係

(1)JVM

Java Virtual Machine是Java虛擬機,Java程序需要運行在虛擬機上,不同的平臺有自己的虛擬機,因此Java語言可以實現跨平臺。

(2)JRE

Java Runtime Environment包括Java虛擬機和Java程序所需的核心類庫等。核心類庫主要是java.lang包:包含了運行Java程序必不可少的系統類,如基本數據類型、基本數學函數、字符串處理、線程、異常處理類等,系統缺省加載這個包

如果想要運行一個開發好的Java程序,計算機中只需要安裝JRE即可。

(3)JDK

Java Development Kit是提供給Java開發人員使用的,其中包含了Java的開發工具,也包括了JRE。所以安裝了JDK,就無需再單獨安裝JRE了。其中的開發工具:編譯工具(javac.exe),打包工具(jar.exe)等

JVM&JRE&JDK關係圖

阿里P8架構師爆出:就是依靠這套面試題進的阿里,進阿里不再難!

4、什麼是跨平臺性?原理是什麼

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

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

5、Java語言有哪些特點

(1)簡單易學(Java語言的語法與C語言和C++語言很接近)

(2)面向對象(封裝,繼承,多態)

(3)平臺無關性(Java虛擬機實現平臺無關性)

(4)支持網絡編程且方便(Java語言誕生本身就是為簡化網絡編程設計的)

(5)支持多線程(多線程機制使應用程序在同一時間並行執行多項任)

(6)健壯性(Java語言的強類型機制、異常處理、垃圾的自動收集等)

(7)安全性

6、什麼是字節碼?採用字節碼的最大好處是什麼

字節碼:Java源代碼經過虛擬機編譯器編譯後產生的文件(即擴展為.class的文件),它不面向任何特定的處理器,只面向虛擬機。

採用字節碼的好處:

Java語言通過字節碼的方式,在一定程度上解決了傳統解釋型語言執行效率低的問題,同時又保留了解釋型語言可移植的特點。所以Java程序運行時比較高效,而且,由於字節碼並不專對一種特定的機器,因此,Java程序無須重新編譯便可在多種不同的計算機上運行。

7、java編譯器和解釋器的關係和區別?

Java源程序經過編譯器編譯後變成字節碼,字節碼由虛擬機解釋執行,虛擬機將每一條要執行的字節碼送給解釋器,解釋器將其翻譯成特定機器上的機器碼,然後在特定的機器上運行,這就是上面提到的Java的特點的編譯與解釋並存的解釋。

<code>Java源代碼---->編譯器---->jvm可執行的Java字節碼(即虛擬指令)---->jvm---->jvm中解釋器----->機器可執行的二進制機器碼---->程序運行。/<code>

8、什麼是Java程序的主類?應用程序和小程序的主類有何不同?

一個程序中可以有多個類,但只能有一個類是主類。在Java應用程序中,這個主類是指包含main()方法的類。而在Java小程序中,這個主類是一個繼承自系統類JApplet或Applet的子類。應用程序的主類不一定要求是public類,但小程序的主類要求必須是public類。主類是Java程序執行的入口點。

9、Java和C++的區別

(1)都是面向對象的語言,都支持封裝、繼承和多態

(2)Java不提供指針來直接訪問內存,程序內存更加安全

(3)Java的類是單繼承的,C++支持多重繼承;雖然Java的類不可以多繼承,但是接口可以多繼承。

(4)Java有自動內存管理機制,不需要程序員手動釋放無用內存

10、Oracle JDK 和 OpenJDK 的對比

(1)Oracle JDK版本將每三年發佈一次,而OpenJDK版本每三個月發佈一次;

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

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

(4)在響應性和JVM性能,Oracle JDK與OpenJDK相比提供了更好的性能;

(5)Oracle JDK不會為即將發佈的版本提供長期支持,用戶每次都必須通過更新到最新版本獲得支持來獲取最新版本;

(6)Oracle JDK根據二進制代碼許可協議獲得許可,而OpenJDK根據GPL v2許可獲得許可。

11、面向對象和麵向過程的區別

面向對象和麵向過程的區別

(1)面向過程:

優點:性能比面向對象高,因為類調用時需要實例化,開銷比較大,比較消耗資源;比如單片機、嵌入式開發、Linux/Unix等一般採用面向過程開發,性能是最重要的因素。

缺點:沒有面向對象易維護、易複用、易擴展

(2)面向對象:

優點:易維護、易複用、易擴展,由於面向對象有封裝、繼承、多態性的特性,可以設計出低耦合的系統,使系統更加靈活、更加易於維護

缺點:性能比面向過程低

面向過程是具體化的,流程化的,解決一個問題,你需要一步一步的分析,一步一步的實現。

面向對象是模型化的,你只需抽象出一個類,這是一個封閉的盒子,在這裡你擁有數據也擁有解決問題的方法。需要什麼功能直接使用就可以了,不必去一步一步的實現,至於這個功能是如何實現的,管我們什麼事?我們會用就可以了。

12、什麼是多態機制,你如何理解的?Java語言是如何實現多態的?

所謂多態就是指程序中定義的引用變量所指向的具體類型和通過該引用變量發出的方法調用在編程時並不確定,而是在程序運行期間才確定,即一個引用變量倒底會指向哪個類的實例對象,該引用變量發出的方法調用到底是哪個類中實現的方法,必須在由程序運行期間才能決定。

多態分為編譯時多態和運行時多態。其中編輯時多態是靜態的,主要是指方法的重載,它是根據參數列表的不同來區分不同的函數,通過編輯之後會變成兩個不同的函數,在運行時談不上多態。而運行時多態是動態的,它是通過動態綁定來實現的,也就是我們所說的多態性。

13、靜態變量和實例變量區別

(1)靜態變量:靜態變量由於不屬於任何實例對象,屬於類的,所以在內存中只會有一份,在類的加載過程中,JVM只為靜態變量分配一次內存空間。

(2)實例變量:每次創建對象,都會為每個對象分配成員變量內存空間,實例變量是屬於實例對象的,在內存中,創建幾次對象,就有幾份成員變量。

14、我們為什麼要使用內部類呢?因為它有以下優點:

  • 一個內部類對象可以訪問創建它的外部類對象的內容,包括私有數據!
  • 內部類不為同一包的其他類所見,具有很好的封裝性;
  • 內部類有效實現了“多重繼承”,優化 java 單繼承的缺陷。
  • 匿名內部類可以很方便的定義回調。

15、局部內部類和匿名內部類訪問局部變量的時候,為什麼變量必須要加上final?

為什麼要加final呢?是因為生命週期不一致, 局部變量直接存儲在棧中,當方法執行結束後,非final的局部變量就被銷燬。而局部內部類對局部變量的引用依然存在,如果局部內部類要調用局部變量時,就會出錯。加了final,可以確保局部內部類使用的變量與外層的局部變量區分開,解決了這個問題。

16、重載(Overload)和重寫(Override)的區別。重載的方法能否根據返回類型進行區分?

方法的重載和重寫都是實現多態的方式,區別在於前者實現的是編譯時的多態性,而後者實現的是運行時的多態性。

重載:發生在同一個類中,方法名相同參數列表不同(參數類型不同、個數不同、順序不同),與方法返回值和訪問修飾符無關,即重載的方法不能根據返回類型進行區分

重寫:發生在父子類中,方法名、參數列表必須相同,返回值小於等於父類,拋出的異常小於等於父類,訪問修飾符大於等於父類(里氏代換原則);如果父類方法訪問修飾符為private則子類中就不是重寫。

二、基礎語法

1、java基本數據的數據範圍

這個主要是每個數據類型佔據幾個字節。

阿里P8架構師爆出:就是依靠這套面試題進的阿里,進阿里不再難!

2、switch 是否能作用在 byte 上,是否在 long 上,是否能作用在 String 上

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

3、float f=3.4;是否正確?

不正確。3.4 是雙精度數,將雙精度型(double)賦值給浮點型(float)屬於下轉型(down-casting,也稱為窄化)會造成精度損失,因此需要強制類型轉換float f =(float)3.4; 或者寫成 float f =3.4F;。

4、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);其中有隱含的強制類型轉換。正確。

5、Java語言採用何種編碼方案?有何特點?

Java語言採用Unicode編碼標準,Unicode(標準碼),它為每個字符制訂了一個唯一的數值,因此在任何的語言,平臺,程序都可以放心的使用。

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

阿里P8架構師爆出:就是依靠這套面試題進的阿里,進阿里不再難!

這個圖我覺得可以這樣記,從上往下,從左往右範圍越來越大,還有從右往左從上往下三個X。

7、&和&&的區別

&運算符有兩種用法:(1)按位與;(2)邏輯與。

&&運算符是短路與運算。邏輯與跟短路與的差別是非常巨大的,雖然二者都要求運算符左右兩端的布爾值都是true 整個表達式的值才是 true。&&之所以稱為短路運算,是因為如果&&左邊的表達式的值是 false,右邊的表達式會被直接短路掉,不會進行運算。

三、關鍵字

1、final 有什麼用?

用於修飾類、屬性和方法;

  • 被final修飾的類不可以被繼承
  • 被final修飾的方法不可以被重寫
  • 被final修飾的變量不可以被改變,被final修飾不可變的是變量的引用,而不是引用指向的內容,引用指向的內容是可以改變的

2、final finally finalize區別

(1)final可以修飾類、變量、方法,修飾類表示該類不能被繼承、修飾方法表示該方法不能被重寫、修飾變量表示該變量是一個常量不能被重新賦值。

(2)finally一般作用在try-catch代碼塊中,在處理異常的時候,通常我們將一定要執行的代碼方法finally代碼塊中,表示不管是否出現異常,該代碼塊都會執行,一般用來存放一些關閉資源的代碼。

(3)finalize是一個方法,屬於Object類的一個方法,而Object類是所有類的父類,該方法一般由垃圾回收器來調用,當我們調用System.gc() 方法的時候,由垃圾回收器調用finalize(),回收垃圾,一個對象是否可回收的最後判斷。

3、this關鍵字的用法

this是自身的一個對象,代表對象本身,可以理解為:指向對象本身的一個指針。

this的用法在java中大體可以分為3種:

(1)普通的直接引用,this相當於是指向當前對象本身。

(2)形參與成員名字重名,用this來區分:

<code>public Person(String name, int age) {
    this.name = name;
    this.age = age;
}/<code>

(3)引用本類的構造函數

<code>class Person{
    private String name;
    private int age;

    public Person() {
    }

    public Person(String name) {
        this.name = name;
    }
    public Person(String name, int age) {
        this(name);
        this.age = age;
    }
}/<code>

4、super關鍵字的用法

super可以理解為是指向自己超(父)類對象的一個指針,而這個超類指的是離自己最近的一個父類。

super也有三種用法:

(1)普通的直接引用

與this類似,super相當於是指向當前對象的父類的引用,這樣就可以用super.xxx來引用父類的成員。

(2)子類中的成員變量或方法與父類中的成員變量或方法同名時,用super進行區分

<code>class Person{
    protected String name;
    public Person(String name) {
        this.name = name;
    }
}

class Student extends Person{
    private String name;
    public Student(String name, String name1) {
        super(name);
        this.name = name1;
    }
    public void getInfo(){
        System.out.println(this.name);      //Child
        System.out.println(super.name);     //Father
    }

}
public class Test {
    public static void main(String[] args) {
       Student s1 = new Student("Father","Child");
       s1.getInfo();

    }
}/<code>

(3)引用父類構造函數

  • super(參數):調用父類中的某一個構造函數(應該為構造函數中的第一條語句)。
  • this(參數):調用本類中另一種形式的構造函數(應該為構造函數中的第一條語句)。

5、this與super的區別

(1)super: 它引用當前對象的直接父類中的成員(用來訪問直接父類中被隱藏的父類中成員數據或函數,基類與派生類中有相同成員定義時如:super.變量名 super.成員函數據名(實參)

(2)this:它代表當前對象名(在程序中易產生二義性之處,應使用this來指明當前對象;如果函數的形參與類中的成員數據同名,這時需用this來指明成員變量名)

(3)super()和this()類似,區別是,super()在子類中調用父類的構造方法,this()在本類內調用本類的其它構造方法。

(4)super()和this()均需放在構造方法內第一行。

(5)儘管可以用this調用一個構造器,但卻不能調用兩個。

(6)this和super不能同時出現在一個構造函數里面,因為this必然會調用其它的構造函數,其它的構造函數必然也會有super語句的存在,所以在同一個構造函數里面有相同的語句,就失去了語句的意義,編譯器也不會通過。

(7)this()和super()都指的是對象,所以,均不可以在static環境中使用。包括:static變量,static方法,static語句塊。

(8)從本質上講,this是一個指向本對象的指針, 然而super是一個Java關鍵字。

6、static存在的主要意義

static的主要意義是在於創建獨立於具體對象的域變量或者方法。以致於即使沒有創建對象,也能使用屬性和調用方法!

static關鍵字還有一個比較關鍵的作用就是 用來形成靜態代碼塊以優化程序性能。static塊可以置於類中的任何地方,類中可以有多個static塊。在類初次被加載的時候,會按照static塊的順序來執行每個static塊,並且只會執行一次。

為什麼說static塊可以用來優化程序性能,是因為它的特性:只會在類加載的時候執行一次。因此,很多時候會將一些只需要進行一次的初始化操作都放在static代碼塊中進行。

static的獨特之處:

(1)被static修飾的變量或者方法是獨立於該類的任何對象,也就是說,這些變量和方法不屬於任何一個實例對象,而是被類的實例對象所共享。

(2)在該類被第一次加載的時候,就會去加載被static修飾的部分,而且只在類第一次使用時加載並進行初始化,注意這是第一次用就要初始化,後面根據需要是可以再次賦值的。

(3)static變量值在類加載的時候分配空間,以後創建類對象的時候不會重新分配。賦值的話,是可以任意賦值的!

(4)被static修飾的變量或者方法是優先於對象存在的,也就是說當一個類加載完畢之後,即便沒有創建對象,也可以去訪問。

1、靜態只能訪問靜態。2、非靜態既可以訪問非靜態,也可以訪問靜態。

四、常見面試題(非常重要)

1、== 和 equals 的區別是什麼

(1)== : 它的作用是判斷兩個對象的地址是不是相等。即,判斷兩個對象是不是同一個對象。(基本數據類型 == 比較的是值,引用數據類型 == 比較的是內存地址)

(2)equals() : 它的作用也是判斷兩個對象是否相等。但它有兩種使用情況:

情況1:類沒有覆蓋 equals() 方法。則通過 equals() 比較該類的兩個對象時,等價於通過“==”比較這兩個對象。

情況2:類覆蓋了 equals() 方法。一般,我們都覆蓋 equals() 方法來兩個對象的內容相等;若它們的內容相等,則返回 true (即,認為這兩個對象相等)。

2、hashCode 與 equals (重要)

這個問題首先考慮另外一個問題?HashSet如何檢查重複?兩個對象的 hashCode() 相同,則 equals() 也一定為 true,對嗎?

或者另外一個面試題:面試官可能會問你:“你重寫過 hashcode 和 equals 麼,為什麼重寫equals時必須重寫hashCode方法?”

答:

hashCode()介紹

hashCode() 的作用是獲取哈希碼,也稱為散列碼;它實際上是返回一個int整數。這個哈希碼的作用是確定該對象在哈希表中的索引位置。hashCode() 定義在JDK的Object.java中,這就意味著Java中的任何類都包含有hashCode()函數。

散列表存儲的是鍵值對(key-value),它的特點是:能根據“鍵”快速的檢索出對應的“值”。這其中就利用到了散列碼!(可以快速找到所需要的對象)

為什麼要有 hashCode

我們以“HashSet 如何檢查重複”為例子來說明為什麼要有 hashCode

當你把對象加入 HashSet 時,HashSet 會先計算對象的 hashcode 值來判斷對象加入的位置,同時也會與其他已經加入的對象的 hashcode 值作比較,如果沒有相符的hashcode,HashSet會假設對象沒有重複出現。但是如果發現有相同 hashcode 值的對象,這時會調用 equals()方法來檢查 hashcode 相等的對象是否真的相同。如果兩者相同,HashSet 就不會讓其加入操作成功。如果不同的話,就會重新散列到其他位置。(摘自我的Java啟蒙書《Head first java》第二版)。這樣我們就大大減少了 equals 的次數,相應就大大提高了執行速度。

hashCode()與equals()的相關規定

(1)如果兩個對象相等,則hashcode一定也是相同的

(2)兩個對象相等,對兩個對象分別調用equals方法都返回true

(3)兩個對象有相同的hashcode值,它們也不一定是相等的

因此,equals 方法被覆蓋過,則 hashCode 方法也必須被覆蓋

hashCode() 的默認行為是對堆上的對象產生獨特值。如果沒有重hashCode(),則該 class 的兩個對象無論如何都不會相等(即使這兩個對象指向相同的數據)

對象的相等 比的是內存中存放的內容是否相等而 引用相等 比較的是他們指向的內存地址是否相等。

3、當一個對象被當作參數傳遞到一個方法後,此方法可改變這個對象的屬性,並可返回變化後的結果,那麼這裡到底是值傳遞還是引用傳遞

是值傳遞。Java 語言的方法調用只支持參數的值傳遞。當一個對象實例作為一個參數被傳遞到方法中時,參數的值就是對該對象的引用。對象的屬性可以在被調用過程中被改變,但對對象引用的改變是不會影響到調用者的

4、為什麼 Java 中只有值傳遞

值傳遞和引用傳遞有什麼區別

(1)值傳遞:指的是在方法調用時,傳遞的參數是按值的拷貝傳遞,傳遞的是值的拷貝,也就是說傳遞後就互不相關了。

(2)引用傳遞:指的是在方法調用時,傳遞的參數是按引用進行傳遞,其實傳遞的引用的地址,也就是變量所對應的內存空間的地址。傳遞的是值的引用,也就是說傳遞前和傳遞後都指向同一個引用(也就是同一個內存空間)。

按值調用(call by value)表示方法接收的是調用者提供的值,而按引用調用(call by reference)表示方法接收的是調用者提供的變量地址。一個方法可以修改傳遞引用所對應的變量值,而不能修改傳遞值調用所對應的變量值。

Java程序設計語言總是採用按值調用。也就是說,方法得到的是所有參數值的一個拷貝,也就是說,方法不能修改傳遞給它的任何參數變量的內容。

5、JDK 中常用的包有哪些?

(1)java.lang:這個是系統的基礎類;

(2)java.io:這裡面是所有輸入輸出有關的類,比如文件操作等;

(3)java.nio:為了完善 io 包中的功能,提高 io 包中性能而寫的一個新包;

(4)java.net:這裡面是與網絡有關的類;

(5)java.util:這個是系統輔助類,特別是集合類;

(6)java.sql:這個是數據庫操作的類。

6、import java和javax有什麼區別?

剛開始的時候 JavaAPI 所必需的包是 java 開頭的包,javax 當時只是擴展 API 包來說使用。然而隨著時間的推移,javax 逐漸的擴展成為 Java API 的組成部分。但是,將擴展從 javax 包移動到 java 包將是太麻煩了,最終會破壞一堆現有的代碼。因此,最終決定 javax 包將成為標準API的一部分。

所以,實際上java和javax沒有區別。這都是一個名字。

7、java 中 IO 流分為幾種?

(1)按照流的流向分,可以分為輸入流和輸出流;

(2)按照操作單元劃分,可以劃分為字節流和字符流;

(3)按照流的角色劃分為節點流和處理流。

Java Io流共涉及40多個類,這些類看上去很雜亂,但實際上很有規則,而且彼此之間存在非常緊密的聯繫, Java I0流的40多個類都是從如下4個抽象類基類中派生出來的。

(1)InputStream/Reader: 所有的輸入流的基類,前者是字節輸入流,後者是字符輸入流。

(2)OutputStream/Writer: 所有輸出流的基類,前者是字節輸出流,後者是字符輸出流。

按操作方式分類結構圖:

阿里P8架構師爆出:就是依靠這套面試題進的阿里,進阿里不再難!

8、BIO,NIO,AIO 有什麼區別?

詳細回答

(1)BIO (Blocking I/O): 同步阻塞I/O模式,數據的讀取寫入必須阻塞在一個線程內等待其完成。在活動連接數不是特別高(小於單機1000)的情況下,這種模型是比較不錯的,可以讓每一個連接專注於自己的 I/O 並且編程模型簡單,也不用過多考慮系統的過載、限流等問題。線程池本身就是一個天然的漏斗,可以緩衝一些系統處理不了的連接或請求。但是,當面對十萬甚至百萬級連接的時候,傳統的 BIO 模型是無能為力的。因此,我們需要一種更高效的 I/O 處理模型來應對更高的併發量。

(2)NIO (New I/O): NIO是一種同步非阻塞的I/O模型,在Java 1.4 中引入了NIO框架,對應 java.nio 包,提供了 Channel , Selector,Buffer等抽象。NIO中的N可以理解為Non-blocking,不單純是New。它支持面向緩衝的,基於通道的I/O操作方法。NIO提供了與傳統BIO模型中的 Socket 和 ServerSocket 相對應的 SocketChannel 和 ServerSocketChannel 兩種不同的套接字通道實現,兩種通道都支持阻塞和非阻塞兩種模式。阻塞模式使用就像傳統中的支持一樣,比較簡單,但是性能和可靠性都不好;非阻塞模式正好與之相反。對於低負載、低併發的應用程序,可以使用同步阻塞I/O來提升開發速率和更好的維護性;對於高負載、高併發的(網絡)應用,應使用 NIO 的非阻塞模式來開發

(3)AIO (Asynchronous I/O): AIO 也就是 NIO 2。在 Java 7 中引入了 NIO 的改進版 NIO 2,它是異步非阻塞的IO模型。異步 IO 是基於事件和回調機制實現的,也就是應用操作之後會直接返回,不會堵塞在那裡,當後臺處理完成,操作系統會通知相應的線程進行後續的操作。AIO 是異步IO的縮寫,雖然 NIO 在網絡操作中,提供了非阻塞的方法,但是 NIO 的 IO 行為還是同步的。

9、Files的常用方法都有哪些?

(1)Files. exists():檢測文件路徑是否存在。

(2)Files. createFile():創建文件。

(3)Files. createDirectory():創建文件夾。

(4)Files. delete():刪除一個文件或目錄。

(5)Files. copy():複製文件。

(6)Files. move():移動文件。

(7)Files. size():查看文件個數。

(8)Files. read():讀取文件。

(9)Files. write():寫入文件。

五、反射機制

1、什麼是反射機制?

JAVA反射機制是在運行狀態中,對於任意一個類,都能夠知道這個類的所有屬性和方法;對於任意一個對象,都能夠調用它的任意一個方法和屬性;這種動態獲取的信息以及動態調用對象的方法的功能稱為java語言的反射機制。

靜態編譯和動態編譯

靜態編譯:在編譯時確定類型,綁定對象

動態編譯:運行時確定類型,綁定對象

反射機制優缺點

優點:運行期類型的判斷,動態加載類,提高代碼靈活度。

缺點:性能瓶頸:反射相當於一系列解釋操作,通知 JVM 要做的事情,性能比直接的java代碼要慢很多。

2、反射機制的應用場景有哪些?

舉例:

①我們在使用JDBC連接數據庫時使用Class.forName()通過反射加載數據庫的驅動程序;

②Spring框架也用到很多反射機制,最經典的就是xml的配置模式。Spring 通過 XML 配置模式裝載 Bean 的過程:

1) 將程序內所有 XML 或 Properties 配置文件加載入內存中;

2)Java類裡面解析xml或properties裡面的內容,得到對應實體類的字節碼字符串以及相關的屬性信息;

3)使用反射機制,根據這個字符串獲得某個類的Class實例;

4)動態配置實例的屬性

3、java中如何實現反射

(1)通過new對象實現反射機制

(2)通過路徑實現反射機制

(3)通過類名實現反射機制

<code>public class Student {
    private int id;
    String name;
    protected boolean sex;
    public float score;
}
public class Get {
    //獲取反射機制三種方式
    public static void main(String[] args) throws ClassNotFoundException {
        //方式一(通過建立對象)
        Student stu = new Student();
        Class classobj1 = stu.getClass();
        System.out.println(classobj1.getName());
        //方式二(所在通過路徑-相對路徑)
        Class classobj2 = Class.forName("fanshe.Student");
        System.out.println(classobj2.getName());
        //方式三(通過類名)
        Class classobj3 = Student.class;
        System.out.println(classobj3.getName());
    }
}/<code>

六、常見API

1、字符型常量和字符串常量的區別

(1)形式上: 字符常量是單引號引起的一個字符 字符串常量是雙引號引起的若干個字符

(2)含義上: 字符常量相當於一個整形值(ASCII值),可以參加表達式運算 字符串常量代表一個地址值(該字符串在內存中存放位置)

(3)佔內存大小 字符常量只佔一個字節 字符串常量佔若干個字節(至少一個字符結束標誌)

2、什麼是字符串常量池?

字符串常量池位於堆內存中,專門用來存儲字符串常量,可以提高內存的使用率,避免開闢多塊空間存儲相同的字符串,在創建字符串時 JVM 會首先檢查字符串常量池,如果該字符串已經存在池中,則返回它的引用,如果不存在,則實例化一個字符串放到池中,並返回其引用。

3、String為什麼是不可變的嗎?

簡單來說就是String類利用了final修飾的char類型數組存儲字符,源碼如下:

<code>/** The value is used for character storage. */
private final char value[];/<code>

String真的是不可變的嗎?

我覺得如果別人問這個問題的話,回答不可變就可以了。下面只是給大家看兩個有代表性的例子:

1) String不可變但不代表引用不可以變

<code>String str = "Hello";
str = str + " World";
System.out.println("str=" + str);/<code>

實際上,原來String的內容是不變的,只是str由原來指向"Hello"的內存地址轉為指向"Hello World"的內存地址而已,也就是說多開闢了一塊內存區域給"Hello World"字符串。

2) 通過反射是可以修改所謂的“不可變”對象

<code>// 創建字符串"Hello World", 並賦給引用s
String s = "Hello World";
System.out.println("s = " + s); // Hello World
// 獲取String類中的value字段
Field valueFieldOfString = String.class.getDeclaredField("value");
// 改變value屬性的訪問權限
valueFieldOfString.setAccessible(true);
// 獲取s對象上的value屬性的值
char[] value = (char[]) valueFieldOfString.get(s);
// 改變value所引用的數組中的第5個字符
value[5] = '_';
System.out.println("s = " + s); // Hello_World/<code>

用反射可以訪問私有成員, 然後反射出String對象中的value屬性, 進而改變通過獲得的value引用改變數組的結構。但是一般我們不會這麼做,這裡只是簡單提一下有這個東西。

4、String str="i"與 String str=new String(“i”)一樣嗎?

不一樣,因為內存的分配方式不一樣。String str="i"的方式,java 虛擬機會將其分配到常量池中;而 String str=new String(“i”) 則會被分到堆內存中。

5、String s = new String(“xyz”);創建了幾個字符串對象

兩個對象,一個是靜態區的"xyz",一個是用new創建在堆上的對象。

6、數組有沒有 length()方法?String 有沒有 length()方法

數組沒有 length()方法 ,有 length 的屬性。String 有 length()方法。

7、在使用 HashMap 的時候,用 String 做 key 有什麼好處?

HashMap 內部實現是通過 key 的 hashcode 來確定 value 的存儲位置,因為字符串是不可變的,所以當創建字符串時,它的 hashcode 被緩存下來,不需要再次計算,所以相比於其他對象更快。

8、String和StringBuffer、StringBuilder的區別是什麼?

(1)可變性

String類中使用字符數組保存字符串,private final char value[],所以string對象是不可變的。StringBuilder與StringBuffer都繼承自AbstractStringBuilder類,在AbstractStringBuilder中也是使用字符數組保存字符串,char[] value,這兩種對象都是可變的。

(2)線程安全性

String中的對象是不可變的,也就可以理解為常量,線程安全。AbstractStringBuilder是StringBuilder與StringBuffer的公共父類,定義了一些字符串的基本操作,如expandCapacity、append、insert、indexOf等公共方法。StringBuffer對方法加了同步鎖或者對調用的方法加了同步鎖,所以是線程安全的。StringBuilder並沒有對方法進行加同步鎖,所以是非線程安全的。

(3)性能

每次對String 類型進行改變的時候,都會生成一個新的String對象,然後將指針指向新的String 對象。StringBuffer每次都會對StringBuffer對象本身進行操作,而不是生成新的對象並改變對象引用。相同情況下使用StirngBuilder 相比使用StringBuffer 僅能獲得10%~15% 左右的性能提升,但卻要冒多線程不安全的風險。

對於三者使用的總結

(1)如果要操作少量的數據用 = String

(2)單線程操作字符串緩衝區 下操作大量數據 = StringBuilder

(3)多線程操作字符串緩衝區 下操作大量數據 = StringBuffer

回答的時候,線程安全性和性能是最關鍵的。

9、什麼是自動裝箱與拆箱?

裝箱:將基本類型用它們對應的引用類型包裝起來;

拆箱:將包裝類型轉換為基本數據類型;

10、int 和 Integer 有什麼區別?Integer a= 127 與 Integer b = 127相等嗎

(1)對於對象引用類型:==比較的是對象的內存地址。

(2)對於基本數據類型:==比較的是值。

如果整型字面量的值在-128到127之間,那麼自動裝箱時不會new新的Integer對象,而是直接引用常量池中的Integer對象,超過範圍 a1==b1的結果是false

<code>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比較
    System.out.println(b == c); // true

    Integer a1 = 128;
    Integer b1 = 128;
    System.out.println(a1 == b1); // false

    Integer a2 = 127;
    Integer b2 = 127;
    System.out.println(a2 == b2); // true
}/<code>

金三銀四已經泡湯了,備戰金九銀十的小夥伴要注意了,很多小夥伴都在準備跳槽。

在這裡,我為大家準備了一份2020年最新最全的《Java面試題及答案V3.0》,這套電子書涵蓋了諸多後端技術棧的面試題和答案,相信可以幫助大家在最短的時間內複習Java後端的大多數面試題,從而拿到自己心儀的offer。

廢話不多說,先來看下這套面試題的目錄吧:

  • Java基礎
  • Java集合
  • Java併發
  • Java虛擬機
  • 微服務
  • Spring
  • Netty
  • 網絡編程
  • Kafka
  • Zookeeper
  • 設計模式
  • 數據結構與算法
  • 分佈式緩存
  • MongoDB
  • 消息隊列
  • 數據庫
  • 負載均衡


以下是目錄部分截圖:

阿里P8架構師爆出:就是依靠這套面試題進的阿里,進阿里不再難!

阿里P8架構師爆出:就是依靠這套面試題進的阿里,進阿里不再難!


如果獲得這份優質的電子書呢?

很簡單,轉發+評論,關注小編,私信小編回覆“學習”二字,既可以免費獲得這份最新最全的面試題及答案。

此外,為了幫助大家順利找到工作,我為大家準備了一份

大廠Java面試真題(附答案),這份真題涵蓋了設計模式、JVM、框架、數據庫、Dubbo、分佈式、性能優化、併發編程等多個領域,已經分門別類,連答案都給你了。

阿里P8架構師爆出:就是依靠這套面試題進的阿里,進阿里不再難!

如何獲得這份高質量的大廠面試真題呢?

轉發關注小編,後臺私信回覆“學習”二字,即可獲得這份優質的大廠真題和答案。


分享到:


相關文章: