面向对象:包装类、对象处理、类成员
包裝類
Java是面向對象編程語言,但也包含了八種基本的數據類型,這八種基本的數據類型不支持面向對象的編程機制,基本的數據類型也不具備對象的特性:沒有成員變量、方法被調用。所有類型的變量都繼承Object類,都可以當成Object類型,但是基本的數據類型就不可以。為了解決這個問題,Java提供了包裝類的概念,成為基本數據類型的包裝類。
基本的數據類型 包裝類byte Byteshort Shortint Integerlong Longchar Characterfloat Floatdouble Doubleboolean Boolean自動拆裝箱:自動裝箱就是把一個基本的數據類型變量直接賦給對應的包裝類變量,或者賦給Object變量;自動拆箱與之相反,允許直接把包裝類對象直接賦給一個對應的基本類型變量。自動拆裝箱時必須注意類型匹配。
包裝類還可以實現基本類型變量和字符串之間的轉換,把字符串類型的值轉換為基本數據類型由兩種方式:包裝類提供的parseXxx(String s);利用包裝類提供的Xxx(String s)構造器
String提供了多個重載的valueOf()方法,用于將基本的數據類型轉換成字符串。如果希望把基本的數據類型轉換成字符串,更簡單的方式:與""進行連接運算,系統會自動把基本的數據類型轉換成字符串。
int i = 100; String s = i + "";包裝類型的變量是引用數據類型,但包裝類的實例可以與數值類型進行比較,這種比較是直接取出包裝類實例所包裝的數值類比較的。
Integer a = new Integet(6); System.out.println(a > 5);兩個包裝類的實例進行比較的情況比較復雜,因為包裝類的實例實際上是引用類型,兩個包裝類指向同一塊內存才會返回true。
(new Integer(100)) == (new Integer(100)) //返回false自動裝箱就是可以直接把一個基本類型賦給一個包裝類實例
Integer ina = 12; Integer inb = 12; (ina == inb) //返回true Integer inc = 128; Integer ind = 128; (inc == inb) //返回false這里可以看Integer的源碼
static final Integer[] cache = new Integer[-(-128) + 127 + 1]; static {for(int i = 0; i < cache.length; i++){cache[i] = new Integer(i - 128);} }可以看出系統把一個-128到127之間的整數自動裝箱成Integer實例,并放入一個cache數組中緩存起來,如果之后自動裝箱一個-128 到127之間的整數實際指向cache數組中。如果不在這個范圍,系統則會創建一個Integer實例。
處理對象
打印對象和toString()方法
class Person{private String name;public Person(String name){this.name = name;} } public class PrintObject{public static void main(String[] args){Person p = new Person();//這里打印的是對象p的類名 + @ + hashCode,這個是Object類默認的 System.out.println(p);} }重寫toString()方法
class Person{private String name;public Person(String name){this.name = name;}public String toString(){return "name的值為: " + name;} } public class PrintObject{public static void main(String[] args){Person p = new Person("李雷");//重寫了toString()方法之后可以直接打印對象//輸出的格式為重寫return中的 System.out.println(p);}Java測試兩個變量是否相等:一種是==運算符,一種是equals()方法。當使用==來判斷兩個變量是否相等時,如果是基本的數據類型,且都是數值型,則兩個變量的值相等就將返回true。
public class EqualsClass{public static void main(String[] args){int i = 65;float f = 65.0f;System.out.println(i == f); //返回true } }"hello"直接量和new String("hello")有什么區別?當Java程序直接使用形如hello的字符串直接量時,JVM將會使用常量池來管理這些字符串,再調用String類的構造器來創建一個新的String對象,新建的String對象被保存在堆內存中,也就是new String("hello")產生了兩個字符串對象。
常量池專門用于管理在編譯時被確定并被保存已編譯的.class文件中的一些數據,它包括了關于類、方法、接口中的常量,還包括字符串常量。
public class EqualsClass{public static void main(String[] args){String s1 = "abcd";String s2 = "ab" + "cd";String s3 = "abc";String s4 = "d";String s5 = s3 + s4;String s6 = new String("abcd");System.out.println(s1 == s2); //返回trueSystem.out.println(s1 == s5); //返回falseSystem.out.println(s1 == s6); //返回false } }JVM常量池保證相同的字符串常量只有一個,不會產生多個副本,上面程序中s1和s2的字符串在編譯時就可以確定下來,因此他們都將引向同一個字符串對象
使用new創建出來的字符串對象是運行時創建出來的,被保存在運行時內存區。
有時候只是要求它們引用字符串里包含的字符串序列相同即可認為相等,此時就可以利用equals()方法來進行判斷,如:
System.out.println(s1.equals(s6)); //返回true?
equals()方法是Object類提供的一個實例方法,因此所有引用變量都可調用該方法來判斷是否與其他引用相等。但使用這個方法判斷兩個對象是否相等和==沒有區別,同樣要求兩個引用變量指向同一個對象才會返回true。因此上面這里沒有實際意義,可采用重寫equals方法來實現。
String已經重寫了equals()方法,通過equals()比較返回true。
重寫equals()方法
public class EqualsClass{public boolean equals(Object obj){//如果兩個對象為同一對象if(this == obj){return true;}//只有當obj是this類對象if(obj != null && obj.getClass() == EqualsClass.class){EqualsClass eqc = (EqualsClass)obj;if(this.getIdStr().equals(eqc.getIdStr())){return true}return false;}}public static void main(String[] args){} }正確寫equals應該滿足一下條件:
自反省:任意x,x.equals(x)一定返回true
對稱性:任意x、y,x.equals(y)結果等于y.equals(x)
傳遞性:x.equals(y), y.equals(z),x.equals(z)結果意義
對于任何不是null,x.equals(null)返回true;
類成員
static修飾的成員就是類成員,static修飾的類成員屬于整個類。當通過對象類訪問類變量時,系統會在底層轉換為通過該類來訪問類變量。
對象實際上并不持有類變量,類變量是由該類持有的,同一個類的所有對象訪問類變量時,實際上訪問的都是該類所持有的變量。當通過對象訪問類成員時,實際上依然是委托給該類來訪問類成員。因此即使某個實例為null,它也可以訪問它所屬類的類成員。
public class NullStatic{private static void test(){System.out.println("null變量調用");}public static void main(String[] args){NullStatic ns = null;ns.test();} }對象訪問類成員實際還是委托類來訪問該成員,所以即使是對象的值為null,依然可以調用類成員。
靜態初始化塊也是類成員的一種,靜態初始化塊用于執行類初始化動作,系統會調用靜態初始化類對類進行初始化。一旦初始化結束后,靜態初始化塊將永遠不會獲得執行的機會。
對static關鍵字而言,類成員不能訪問實例成員。
final關鍵字可以用來修飾類、變量和方法。用final修飾表示一旦賦初值就不可改變。final修飾的成員變量必須由程序猿顯式指定初始化。
final修飾的類變量、實例變量能指定初始值的地方:
類變量:必須在靜態初始化塊中指定初始值或聲明該類變量時指定初始值,只能在三個地方中的一個指定;
實例變量:必須在非靜態初始化塊、聲明該實例變量或構造器中指定初值。
必須注意的是,不管在哪里指定初值,都必須遵循先賦值再引用的規則,沒有指定初值的變量不能被訪問。
系統不會對局部變量初始化,局部變量必須由程序猿顯式初始化。因此使用final修飾局部變量既可以在定義時指定,也可以不指定。如果不指定則必須在后面的代碼中指定,只能一次,不能重復賦值。
使用final修飾基本的數據類型,不能對基本的數據類型重新賦值,因此基本的數據類型不能改變。
修飾的是引用類型,final保證這個引用類型變量所引用的地址不能改變,即一直引用統一對象,但這個對象完全可以改變。
class Person{String name;int age;public Person(String name, int age){this.name = name;this.age = age;}public void setName(String name){this.name = name;}public void setAge(int age){this.age = age;} } public class FinalClass{public static void main(String[] args){final Person p = new Person("lilei", 18);System.out.println(p.name + "---" + p.age);//無法改變引用地址,但可以改變對象p.setName("hanmeimei");p.setAge(81);System.out.println(p.name + "---" + p.age);} }對于final變量來說,不管是類變量、實例變量還是局部變量,只要滿足1、使用final修飾;2、定義該final變量時指定了初值;3、該初始值可在編譯時確定下來,這種情況下變量相當于一個直接量。
final修飾符的一個重要用于是定義宏變量,當定義final變量時就為該變量指定了初始值,而且該初始值可以在編譯時確定下來,那么合格final變量本質上是一個宏變量,編譯器會在程序中所有用到該變量的地方替換成宏變量。
public static void main(String[] args){final int a = 5 + 2;final String str = "abc" + 99.0;final String str2 = "abc" + String.valueOf(99.0);//str與str2不相等,str在編譯時就可以確定值,所以是宏變量//str2必須在程序運行才能確定值,所以不是宏變量}?
final修飾的方法不可被重寫,final修飾的類不可以有子類,String是不可變類。
定義不可變類需要遵循:
1、使用private和final修飾該類的成員變量
2、提供帶參數構造器,用于根據傳入參數來初始化類里的成員變量
3、僅為該類成員變量提供getter方法,不為該類挺setter方法,普通方法無法修改final修飾的成員變量
4、有必要重寫hashcode和equals方法
?
轉載于:https://www.cnblogs.com/zaijie/p/11037672.html
總結
以上是生活随笔為你收集整理的面向对象:包装类、对象处理、类成员的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Appium国内下载地址
- 下一篇: 设计模式-Builder和Factory