Java知識面試題複習(四)Java常用API

manor的大數據奮鬥之路 2021-08-15 21:37:08 阅读数:611

本文一共[544]字,预计阅读时长:1分钟~
java java 常用 api

常用API

String相關

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

形式上: 字符常量是單引號引起的一個字符 字符串常量是雙引號引起的若幹個字符
含義上: 字符常量相當於一個整形值(ASCII值),可以參加錶達式運算 字符串常量代錶一個地址值(該字符串在內存中存放比特置)
占內存大小 字符常量只占兩個字節 字符串常量占若幹個字節(至少一個字符結束標志)

什麼是字符串常量池?

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

String 是最基本的數據類型嗎

不是。Java 中的基本數據類型只有 8 個 :byte、short、int、long、float、double、char、boolean;除了基本類型(primitive type),剩下的都是引用類型(referencetype),Java 5 以後引入的枚舉類型也算是一種比較特殊的引用類型。

這是很基礎的東西,但是很多初學者卻容易忽視,Java 的 8 種基本數據類型中不包括 String,基本數據類型中用來描述文本數據的是 char,但是它只能錶示單個字符,比如 ‘a’,‘好’ 之類的,如果要描述一段文本,就需要用多個 char 類型的變量,也就是一個 char 類型數組,比如“你好” 就是長度為2的數組 char[] chars = {‘你’,‘好’};

但是使用數組過於麻煩,所以就有了 String,String 底層就是一個 char 類型的數組,只是使用的時候開發者不需要直接操作底層數組,用更加簡便的方式即可完成對字符串的使用。

String有哪些特性

不變性:String 是只讀字符串,是一個典型的 immutable 對象,對它進行任何操作,其實都是創建一個新的對象,再把引用指向該對象。不變模式的主要作用在於當一個對象需要被多線程共享並頻繁訪問時,可以保證數據的一致性。

常量池優化:String 對象創建之後,會在字符串常量池中進行緩存,如果下次創建同樣的對象時,會直接返回緩存的引用。

final:使用 final 來定義 String 類,錶示 String 類不能被繼承,提高了系統的安全性。

String為什麼是不可變的嗎?

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

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

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

  1. String不可變但不代錶引用不可以變
String str = "Hello";
str = str + " World";
System.out.println("str=" + str);

結果:

str=Hello World

解析:

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

  1. 通過反射是可以修改所謂的“不可變”對象
// 創建字符串"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

結果:

s = Hello World
s = Hello_World

解析:

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

是否可以繼承 String 類
String 類是 final 類,不可以被繼承。

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

String s = new String(“xyz”);創建了幾個字符串對象
兩個對象,一個是靜態區的"xyz",一個是用new創建在堆上的對象。

String str1 = "hello"; //str1指向靜態區
String str2 = new String("hello"); //str2指向堆上的對象
String str3 = "hello";
String str4 = new String("hello");
System.out.println(str1.equals(str2)); //true
System.out.println(str2.equals(str4)); //true
System.out.println(str1 == str3); //true
System.out.println(str1 == str2); //false
System.out.println(str2 == str4); //false
System.out.println(str2 == "hello"); //false
str2 = str1;
System.out.println(str2 == "hello"); //true

如何將字符串反轉?

使用 StringBuilder 或者 stringBuffer 的 reverse() 方法。

示例代碼:

// StringBuffer reverse
StringBuffer stringBuffer = new StringBuffer();
stringBuffer. append("abcdefg");
System. out. println(stringBuffer. reverse()); // gfedcba
// StringBuilder reverse
StringBuilder stringBuilder = new StringBuilder();
stringBuilder. append("abcdefg");
System. out. println(stringBuilder. reverse()); // gfedcba

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

數組沒有 length()方法 ,有 length 的屬性。String 有 length()方法。JavaScript中,獲得字符串的長度是通過 length 屬性得到的,這一點容易和 Java 混淆。

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

indexOf():返回指定字符的索引。
charAt():返回指定索引處的字符。
replace():字符串替換。
trim():去除字符串兩端空白。
split():分割字符串,返回一個分割後的字符串數組。
getBytes():返回字符串的 byte 類型數組。
length():返回字符串長度。
toLowerCase():將字符串轉成小寫字母。
toUpperCase():將字符串轉成大寫字符。
substring():截取字符串。
equals():字符串比較。
在使用 HashMap 的時候,用 String 做 key 有什麼好處?
HashMap 內部實現是通過 key 的 hashcode 來確定 value 的存儲比特置,因為字符串是不可變的,所以當創建字符串時,它的 hashcode 被緩存下來,不需要再次計算,所以相比於其他對象更快。

String和StringBuffer、StringBuilder的區別是什麼?String為什麼是不可變的

可變性

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

線程安全性

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

性能

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

對於三者使用的總結

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

單線程操作字符串緩沖區 下操作大量數據 = StringBuilder

多線程操作字符串緩沖區 下操作大量數據 = StringBuffer

Date相關

包裝類相關
自動裝箱與拆箱
裝箱:將基本類型用它們對應的引用類型包裝起來;

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

int 和 Integer 有什麼區別

Java 是一個近乎純潔的面向對象編程語言,但是為了編程的方便還是引入了基本數據類型,但是為了能够將這些基本數據類型當成對象操作,Java 為每一個基本數據類型都引入了對應的包裝類型(wrapper class),int 的包裝類就是 Integer,從 Java 5 開始引入了自動裝箱/拆箱機制,使得二者可以相互轉換。

Java 為每個原始類型提供了包裝類型:

原始類型: boolean,char,byte,short,int,long,float,double

包裝類型:Boolean,Character,Byte,Short,Integer,Long,Float,Double

Integer a= 127 與 Integer b = 127相等嗎

對於對象引用類型:==比較的是對象的內存地址。
對於基本數據類型:==比較的是值。

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

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
}

原文鏈接:https://blog.csdn.net/ThinkWon/article/details/104390612

版权声明:本文为[manor的大數據奮鬥之路]所创,转载请带上原文链接,感谢。 https://gsmany.com/2021/08/20210815213646815T.html