接着前面面向對象來說吧~今天來說說String類。。其實String類也包含很多面向對象的知識的~
首先來問一個問題:我們在開發過程中,如果要使用一個類的話,就要創建對象,這句話沒什麼問題吧~在實際開發的時候確實是這樣的,只有創建了對象才能真正的去使用一個普通的類,我們一般創建對象,幾乎所有的類創建對象都是要通過new關鍵字來創建的~
問題就來了。。爲什麼我們的String可以直接寫成String str = "abc";這樣子呢?
當然String類也可以通過new來創建對象的。。。
其實也不難,我們看到它的源碼說明就知道的:
* Strings are constant; their values cannot be changed after they
* are created. String buffers support mutable strings.
* Because String objects are immutable they can be shared. For example:
* <p><blockquote><pre>
* String str = "abc";
* </pre></blockquote><p>
* is equivalent to:
* <p><blockquote><pre>
* char data[] = {'a', 'b', 'c'};
* String str = new String(data);
* </pre></blockquote><p>
進入String的源碼,最前面就能看到上面的文字的:大致的意思是,String的對象值其實是通過char[]數組來存儲的,String str = "abc";等同於char data[] = {'a', 'b', 'c'}; String str = new String(data);明白清晰了吧~
1、String類的定義:
public final class String
implements java.io.Serializable, Comparable<String>, CharSequence
問題:在開發過程中,我們可以繼承String類嗎?
答案:不行的,我們看定義就知道,String的定義使用了final修飾符,定義爲了終結類,所以String是不能做擴展的。
implements:這個關鍵字是用來表示實現接口作用的,意思就是Serializable、Comparable和CharSequence都是接口的。
查看接口源碼:
Comparable<T> :表示比較器作用,<T>採用了java泛型的形式
Serializable:
public interface Serializable {
}
我們可以看到Serializable接口裏面啥都木有,那爲什麼我們要實現這個接口呢?這個接口的作用是啥呢?
作用:java類的序列化,至於序列化,後面會詳細介紹。其實Serializable是java的一個標記接口,什麼叫標記接口?Serializable只是作爲一個標記的作用,關於它具體的功能和作用交給了JVM底層去實現了,實現了這個接口,只是通知JVM,String這個類可以序列化。
CharSequence:表示字符序列吧~這個沒啥好說的,String的存儲方式依賴於字符序列的~
2、屬性
private final char value[]; //String值就是存儲在value[]上的
private int hash; // Default to 0 表示hash值,
private static final long serialVersionUID = -6849794470754667710L;//序列化作用
private static final ObjectStreamField[] serialPersistentFields =
new ObjectStreamField[0];//序列化作用
我們只要瞭解String類的屬性就可以,幾乎都不會用到的,因爲都是定義成了private,私有化了~
3、構造方法這裏也只說幾個特殊的,一般在開發過程中也不會用到構造方法的,因爲很少使用new來創建String對象的,都是直接使用String str = "abc";這樣子的形式。。
在面試過程中,很多面試官會問到String str = new String("abc");這個創建了幾個對象?至於答案和解釋,這邊就不做介紹了,想知道的就去網上查找了解~這個涉及到底層的內存問題的,描述起來篇幅會很長的~
public String(String original) {
this.value = original.value;
this.hash = original.hash;
}
從上面可以看到,String兩個核心就是value和hash的,這兩個值基本決定了String對象的。
public String(char value[]) {
this.value = Arrays.copyOf(value, value.length);
}
這個是通過底層數組拷貝的方式創建,其實底層使用的是System.arrayCopy()這個方法,此方法使用了native修飾的,底層是由C/C++來實現的,其實就是一個拷貝的作用。
public String(byte bytes[], int offset, int length) {
checkBounds(bytes, offset, length);
this.value = StringCoding.decode(bytes, offset, length);
}
這個表示的是通過字節(byte)來構造字符串,其實底層的實現也是通過System.arrayCopy()這個方法的。
其他的基本也沒什麼好說的,瞭解一下就可以的。我們可以看到有些構造使用了@Deprecated註解,這個註解表示的過時,不推薦使用這個方法的。
4、常用方法
public int length() { //返回字符串長度
return value.length;
}
public boolean isEmpty() {//判斷字符串是不是爲空
return value.length == 0;
}
public char charAt(int index) {//字符串中的某個字符,index表示字符的位置
if ((index < 0) || (index >= value.length)) {
throw new StringIndexOutOfBoundsException(index);
}
return value[index];
}
public byte[] getBytes() {//獲取字節數組
return StringCoding.encode(value, 0, value.length);
}
public boolean equals(Object anObject) {//字符串比較,我們知道基本類型的比較都是通過==來做比較的,
//但是字符串需要使用此方法來做比較的
我們主要來驗證一下==和equals方法
package me.javen.oop;
public class StringDemo {
public static void main(String[] args) {
String str1 = "hello" ; // 直接賦值
String str2 = new String("hello") ; // 通過new賦值
String str3 = str2 ; // 傳遞引用
System.out.println("str1 == str2 --> " + (str1==str2)) ; // false
System.out.println("str1 == str3 --> " + (str1==str3)) ; // false
System.out.println("str2 == str3 --> " + (str2==str3)) ; // true
//以下通過equals方法
System.out.println("str1 equals str2 --> " + (str1.equals(str2))) ; // true
System.out.println("str1 equals str3 --> " + (str1.equals(str3))) ; // true
System.out.println("str2 equals str3 --> " + (str2.equals(str3))) ; // true
}
}
此外還有一個比較方法也用得比較多:
public boolean equalsIgnoreCase(String anotherString) {//不分大小寫比較
public boolean startsWith(String prefix) {//判斷字符串是不是以prefix開頭
public boolean endsWith(String suffix) {//判斷字符串是不是以suffix結尾
public int hashCode() {//獲取字符串的hash值
public int indexOf(String str) {//獲取字符str的起始位置,-1表示沒有這個字符
return indexOf(str, 0);
}
public String substring(int beginIndex, int endIndex) {//截取字符串beginIndex表示起始位置,endIndex表示結束位置
public String replaceAll(String regex, String replacement) {//字符串替換replacement替換regex
public String[] split(String regex) {//分隔字符串,regex表示分隔符
public String toLowerCase() {//將字符串全部轉換爲小寫
public String toUpperCase() {//將字符串全部轉換爲大寫
public String trim() {//去掉首尾空格,字符中間的空格不能去掉
public static String valueOf(Object obj) {//將obj轉換成字符串,這個可以傳遞任意類型,比如數字,字符,浮點數等等
此外還有其他的很多方法,這邊就不列舉出了,學習者可以通過代碼的方式去使用這些個方法,列舉出來的表示開發中常用的方法~