面試筆錄--java基礎(1)

1.JDK 和 JRE 有什麼區別?

JRE是Java Runtime Environment的縮寫,顧名思義是java運行時環境,包含了java虛擬機,java基礎類庫。是使用java語言編寫的程序運行所需要的軟件環境,是提供給想運行java程序的用戶使用的,還有所有的Java類庫的class文件,都在lib目錄下,並且都打包成了jar。

Jdk是Java Development Kit的縮寫,顧名思義是java開發工具包,是程序員使用java語言編寫java程序所需的開發工具包,是提供給程序員使用的。JDK包含了JRE,同時還包含了編譯java源碼的編譯器javac,還包含了很多java程序調試和分析的工具:jconsole,jvisualvm等工具軟件,還包含了java程序編寫所需的文檔和demo例子程序。

如果你需要運行java程序,只需安裝JRE就可以了。如果你需要編寫java程序,需要安裝JDK。

 

2.==和equals的區別

== 比較的是變量(棧)內存中存放的對象的(堆)內存地址,用來判斷兩個對象的地址是否相同,即是否是指相同一個對象。比較的是真正意義上的指針操作

==一般用於比較兩個對象的值是否相等,比較的是操作符兩端的操作數是否是同一個對象,兩邊的操作數必須是同一類型的(可以是父子類之間)才能編譯通過,比較的是地址,如果是具體的阿拉伯數字的比較,值相等則爲true;

equals比較的是兩個對象的內容是否相等,由於所有的類都是繼承自java.lang.Object類的,所以適用於所有對象,如果沒有對該方法進行覆蓋的話,調用的仍然是Object類中的方法,而Object中的equals方法返回的卻是==的判斷。

 

3.兩個對象的 hashCode()相同,則 equals()也一定爲 true,對嗎? No

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

在散列表中,

    1、如果兩個對象相等,那麼它們的hashCode()值一定要相同;

    2、如果兩個對象hashCode()相等,它們並不一定相等。

注意:這是在散列表中的情況。在非散列表中一定如此!

總而言之,就是一切取決於hashCode和equals怎麼重寫的,如果hashCode和equals都沒有重寫,就按上面的來

 

4.final 在 java 中有什麼作用?

1、final成員變量表示常量,如果final指針,那麼指針地址不可以改變,但是指針指向的對象可以改變

2、final類不能繼承

3、final方法不能重寫,但是可以繼承

3、final不能修飾構造函數

 

5.java 中的 Math.round(-1.5) 等於多少? -1

Math.round()的原理是對傳入的參數+0.5之後,再向下取整得到的數就是返回的結果,返回值爲long型。這裏的向下取整是說取比它小的第一個整數或者和它相等的整數。-1.5+0.5=-1向下取整爲-1,。

向下取整:Math.floor();Math.floor(1.3)=1

向上取整:Math.ceil(); Math.ceil(1.2)=2

 

6.String 屬於基礎的數據類型嗎?

很明顯不是,很簡單判斷方法,大寫開頭是類,小寫開頭是基本數據類型。

String是final修飾的java類,java中的基本類型一共有8個,它們分別爲:

1、字符類型:byte,char

2、基本整型:short,int,long

3、浮點型:float,double

4、布爾類型:boolean

 

7.java 中操作字符串都有哪些類?它們之間有什麼區別?

String、StringBuffer和StringBuilder

首先說運行速度,或者說是執行速度,在這方面運行速度快慢爲:
效率:StringBuilder > StringBuffer > String

  String最慢的原因:

  String爲字符串常量,而StringBuilder和StringBuffer均爲字符串變量,即String對象一旦創建之後該對象是不可更改的,但後兩者的對象是變量,是可以更改的。以下面一段代碼爲例:

    String str="abc";

    System.out.println(str);

    str=str+"de";

    System.out.println(str);

如果運行這段代碼會發現先輸出“abc”,然後又輸出“abcde”,好像是str這個對象被更改了,其實,這只是一種假象罷了,JVM對於這幾行代碼是這樣處理的,首先創建一個String對象str,並把“abc”賦值給str,然後在第三行中,其實JVM又創建了一個新的對象也名爲str,然後再把原來的str的值和“de”加起來再賦值給新的str,而原來的str就會被JVM的垃圾回收機制(GC)給回收掉了,所以,str實際上並沒有被更改,也就是前面說的String對象一旦創建之後就不可更改了。所以,Java中對String對象進行的操作實際上是一個不斷創建新的對象並且將舊的對象回收的一個過程,所以執行速度很慢。

而StringBuilder和StringBuffer的對象是變量,對變量進行操作就是直接對該對象進行更改,而不進行創建和回收的操作,所以速度要比String快很多。另外,有時候我們會這樣對字符串進行賦值:

    String str="abc"+"de";

    StringBuilder stringBuilder=new StringBuilder().append("abc").append("de");

    System.out.println(str);

    System.out.println(stringBuilder.toString());

這樣輸出結果也是“abcde”和“abcde”,但是String的速度卻比StringBuilder的反應速度要快很多,這是因爲第1行中的操作和

  String str="abcde";

  是完全一樣的,所以會很快,而如果寫成下面這種形式

    String str1="abc";

    String str2="de";

    String str=str1+str2;

那麼JVM就會像上面說的那樣,不斷的創建、回收對象來進行這個操作了。速度就會很慢。

 

2. 再來說線程安全

在線程安全上,StringBuilder是線程不安全的,而StringBuffer是線程安全的

如果一個StringBuffer對象在字符串緩衝區被多個線程使用時,StringBuffer中很多方法可以帶有synchronized關鍵字,所以可以保證線程是安全的,但StringBuilder的方法則沒有該關鍵字,所以不能保證線程安全,有可能會出現一些錯誤的操作。所以如果要進行的操作是多線程的,那麼就要使用StringBuffer,但是在單線程的情況下,還是建議使用速度比較快的StringBuilder。

 

8.String str="i"與 String str=new String("i")一樣嗎?

1.當使用String str="abc",這種方式時,先去內存的Heap中找是否存在"abc"這個字符串,若存在,則將地址引用。若不存在則創建。

2.當使用String str=new String("abc");時,不管事先是否存在"abc",每次都會創建其新的對象。

測試一下:

String s1="abc";

String s2="abc";

String s3=new String("abc");

String s4=new String("abc");

System.out.println(s1 == s2);

System.out.println(s2 == s3);

System.out.println(s1 == s3);

System.out.println(s4 == s3);

打印的結果爲:

true

false

false

false

 

9.如何將字符串反轉?

兩種好理解簡單的方法:

1、直接用StringBuffer自帶的方法

public static String reverse1(String s) {

    return new StringBuffer(s).reverse().toString();

 }

2、 把字符串轉換成字符數組首位對調位置

public static String reverse5(String orig) {

    char[] s = orig.toCharArray();

    int n = s.length - 1;

    int halfLength = n / 2;

    for (int i = 0; i <= halfLength; i++) {

        char temp = s[i];

        s[i] = s[n - i];

        s[n - i] = temp;

    }

    return new String(s);

 }

10.String 類的常用方法都有那些?

char charAt(int index);//返回指定索引處的 char 值。

int compareTo(String anotherString) ;//按字典順序比較兩個字符串。

String concat(String str) ;將指定字符串連接到此字符串的結尾。

boolean contains(CharSequence s);當且僅當此字符串包含指定的 char 值序列時,返回 true。

boolean endsWith(String suffix) ;//測試此字符串是否以指定的後綴結束。

boolean equals(Object anObject) ;//將此字符串與指定的對象比較。

byte[] getBytes();//使用平臺的默認字符集將此 String 編碼爲 byte 序列,並將結果存儲到一個新的 byte 數組中。

int  indexOf(int ch);//返回指定字符在此字符串中第一次出現處的索引。

int  lastIndexOf(int ch) ;//返回指定字符在此字符串中最後一次出現處的索引。

int  length();//返回此字符串的長度。

String[] split(String regex);//根據給定正則表達式的匹配拆分此字符串。

boolean  startsWith(String prefix);//測試此字符串是否以指定的前綴開始。

char[]  toCharArray();//將此字符串轉換爲一個新的字符數組。

String  toUpperCase();//使用默認語言環境的規則將此 String 中的所有字符都轉換爲大寫。

String trim();//返回字符串的副本,忽略前導空白和尾部空白。

String  toLowerCase(Locale locale);//使用給定 Locale 的規則將此 String 中的所有字符都轉換爲小寫。

11.抽象類必須要有抽象方法嗎?

抽象類可以不包含抽象方法,包含抽象方法的類一定是抽象類。

 

12.普通類和抽象類有哪些區別?

1、抽象類不能被實例化。

2、抽象類可以有構造函數,被繼承時子類必須繼承父類一個構造方法,抽象方法不能被聲明爲靜態。

3、抽象方法只需申明,而無需實現,抽象類中可以允許普通方法有主體

4、含有抽象方法的類必須申明爲抽象類

5、抽象的子類必須實現抽象類中所有抽象方法,否則這個子類也是抽象類。

13.抽象類能使用 final 修飾嗎?

java類一旦被聲明爲abstract(抽象類),必須要繼承或者匿名(其實匿名也是種繼承)才能使用。

而final則是讓該類無法被繼承,所以final是必然不能和abstract同時聲明的

但是private呢?一個類被聲明爲private的時候,它當然是內部類,內部類是可以被它的外部類訪問到的,所以,可以繼承,private和abstract不衝突。

 

14.接口和抽象類有什麼區別?

抽象類是用來捕捉子類的通用特性的 。它不能被實例化,只能被用作子類的超類。抽象類是被用來創建繼承層級裏子類的模板。

接口是抽象方法的集合。如果一個類實現了某個接口,那麼它就繼承了這個接口的抽象方法。這就像契約模式,如果實現了這個接口,那麼就必須確保使用這些方法。接口只是一種形式,接口自身不能做任何事情。

15.java 中 IO 流分爲幾種?

Java中的流,可以從不同的角度進行分類。

按照數據流的方向不同可以分爲:輸入流和輸出流。

按照處理數據單位不同可以分爲:字節流和字符流。

按照實現功能不同可以分爲:節點流和處理流。

 

16.BIO、NIO、AIO 有什麼區別?

  IO的方式通常分爲幾種,同步阻塞的BIO、同步非阻塞的NIO、異步非阻塞的AIO。 

 

17.java中多態是什麼?

答:方法的重寫Overriding和重載Overloading是Java多態性的不同表現.

發佈了39 篇原創文章 · 獲贊 25 · 訪問量 3萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章