java面向物件(下)
Java 的包裝類
- 包裝類:可以把8個基本型別的值包裝成物件使用
- 自動拆箱:包裝類物件賦給對應的基本型別變數
- 自動裝箱:基本型別變數賦給對應的包裝類引用變數
- 基本資料和對應的包裝類關係: 基本資料型別 包裝類 byte--------------------------------------------Byte short-------------------------------------------Short int-----------------------------------------------Integer long---------------------------------------------Long char--------------------------------------------Character float--------------------------------------------Float double-----------------------------------------Double Boolean---------------------------------------Boolean
- 包裝類可實現基本型別變數和基本字串之間的轉換:
- 利用包裝類提供的parseXxx(String s)靜態方法 (除了Character外)
- 利用包裝類提供的Xxx(String s)構造器。
- String類提供了多個過載valueOf()方法,用於將基本類轉換成字串
/*包裝類*/ class Primitive2String { public static void main(String[] args) { String intStr = "123"; //把一個特定字串轉換成int變數 int it1 = Integer.parseInt(intStr); int it2 = new Integer(intStr); System.out.println(it2); //把一個特定字串轉換成float變數 String floatStr = "4.56"; float ft1 = Float.parseFloat(floatStr); float ft2 = new Float(floatStr); System.out.println(ft2); //把一個float轉換String型別。 String ftStr = String.valueOf(2.34f); System.out.println(ftStr); //把一個double型的轉換成String型別 String doStr = String.valueOf(3.344); System.out.println(doStr); //把一個boolean變數轉換成String型別 String boolStr = String.valueOf(true); System.out.println(boolStr.toUpperCase()); } } 結果: 123 4.56 2.34 3.344 TRUE
處理物件
- 列印物件和toString()方法
當直接用輸出語句列印一個物件時 輸出的格式:類名[email protected]+hashCode 這是因為每個物件裡面有一個預設的toString方法,上面的結果是toString方法的返回值。 比如下面的程式碼是相同的: System.out.println§; System.out.println(p.toString());
- toString()是Object裡的一個例項方法,所有的java類都是Object的子類,因此所有的java物件都具有toString()方法。
- toString()方法是一個自我描述的方法。當程式設計師列印該物件時,系統就會輸出該物件的自我描述。告訴外界該物件具有的資訊。
- 一般情況下,都要重寫toString()方法
==和equals方法
- 判斷變數是否相等有兩種方式
- ==
- equals方法。
- 對於數值只要相等 就返回 true
- 對於引用型別,只有他們指向同一個物件 ==判斷才會返回true
- ==不能用於比較型別上沒有父子關係的兩個物件。
- equals方法是Object提供的一個例項方法 ,一般情況下和==無區別
- 當用戶需要自定義判斷方法是 ,可以重寫equals()方法來實現。
- 而String類已經重寫了equals方法,String的equals方法判斷是兩個字串相等的標準是,只要兩個字串包含的字元序列相同 就返回true 否則返回false。
/*equals方法重寫*/
class Person
{
private String name;
private String idStr;
public Person(){}
public Person(String name,String idStr)
{
this.name = name;
this.idStr=idStr;
}
public String getIdStr()
{
return idStr;
}
public void setIdStr(String idStr)
{
this.idStr = idStr;
}
public String getName()
{
return name;
}
public void setName(String name)
{
this.name = name;
}
//這裡重寫equals方法
public boolean equals(Object obj)
{
//相同的物件
if (this == obj)
{
return true;
}
//當obj為person的物件時
if (obj != null && obj.getClass() == Person.class)
{
Person personObj = (Person)obj;
//並且當idStr與obj物件的idStr相同時才可判斷兩者相同
if (this.getIdStr().equals(personObj.getIdStr()))
{
if (this.getName().equals(personObj.getName()))
{
return true;
}
return false;
}
return false;
}
return false;
}
}
class OverrideEqualsRight
{
public static void main(String[] args)
{
Person p1 = new Person("XXX","04161032");
Person p2 = new Person("XXX","04161032");
Person p3 = new Person("ZZZ","04161020");
//判斷
System.out.println("p1是否與p2相等?"+p1.equals(p2));
System.out.println("p1是否與p3相等?"+p1.equals(p3));
}
}
結果:
p1是否與p2相等?true
p1是否與p3相等?false
- 這裡要求寫equals方法是滿足 自反性 對稱性 傳遞性 一致性 對於任意不是null的x 則x.equals(null)一定返回false。
final關鍵字
- final修飾類 則該類不能被繼承
- final修飾方法 則該方法不能被覆蓋或者重寫
- final修飾變數 則該變數不能被重新賦值。因為該變數是常量。
- 修飾成員變數 同final修飾變數。
- 修飾引用型別 則引用型別的地址不能變,物件裡面的內容可以變
抽象類
- 抽象方法:使用關鍵字abstract來修飾的方法,而且不含有方法體。
- 要求:抽象方法不能有方法體 即沒有花括號包括花括號,直接在()後面加一個;就行。
抽象方法和空方法體 不是一個個概念;例如 抽象方法:public abstract void text(); 空方法體:public void test(){}
-
抽象類:必須使用abstract修飾符來修飾,而且不能被例項化,即無法使用new關鍵字建立新的物件例項。主要用途是被子類繼承呼叫。抽象類可以含有成員變數 方法(普通方法 ,抽象方法) ,構造器,初始化塊,內部類(介面 ,列舉)5種成分,抽象類的構造器不能用於建立例項,含有抽象方法的類(包括直接定義一個抽象方法,或者繼承了一個父類 但沒有完全實現父類包含的方法,或者實現了一個介面,但沒有完全實現介面包含的抽象方法)只能被定義成抽象類。
-
抽象類的子類 如果不重寫父類方法 則子類仍是抽象類 如果重寫父類的抽象方法,則子類為具體類 ,實現子類的方法靠 多型實現。
-
歸納:抽象類有得有失
- 得 :抽象類多了一個能力抽象類可以含有抽象方法
- 抽象類失去了一個能力,不能建立例項。
-
利用抽象類和抽象方法 可以很好的發揮多型的優勢.
-
使用abstract修飾類 表明這個類只能被繼承,修飾方法表明這個方法只能由子類重寫(實現) 而final修飾類不能被繼承 ,final修飾方法不能被重寫。因此final和abstract永遠不可能同時使用.
-
abstract 不能修飾變數 不能修飾構造器
-
static修飾方法是 表明屬於類本身 即通過類呼叫方法 ,但是如果被定義為抽象方法,會導致使用類來呼叫該方法時出現錯誤。 因此static和abstract必能同時修飾一個方法。但是可以同時修飾一個內部類
-
abstract修飾的方法必須被子類重寫才有意義,private修飾方法 不能被子類呼叫 就是說 abstract和private不能修飾同一個方法。
lambda表示式
引入匿名內部類知識: /* 匿名內部類 就是內部類的簡化寫法。
前提:存在一個類或者介面
這裡的類可以是具體類也可以是抽象類。
格式:
new 類名或者介面名(){
重寫方法;
}
本質是什麼呢?
是一個繼承了該類或者實現了該介面的子類匿名物件。
interface Inter {
public abstract void show();
public abstract void show2();
}
class Outer {
public void method() {
//一個方法的時候
/*
new Inter() {
public void show() {
System.out.println("show");
}
}.show();
*/
//二個方法的時候
/*
new Inter() {
public void show() {
System.out.println("show");
}
public void show2() {
System.out.println("show2");
}
}.show();
new Inter() {
public void show() {
System.out.println("show");
}
public void show2() {
System.out.println("show2");
}
}.show2();
*/
//匿名內部類引入
//如果我是很多個方法,就很麻煩了
//那麼,我們有沒有改進的方案呢?
Inter i = new Inter() { //多型
public void show() {
System.out.println("show");
}
public void show2() {
System.out.println("show2");
}
};
i.show();
i.show2();
}
}
class InnerClassDemo6 {
public static void main(String[] args) {
Outer o = new Outer();
o.method();
}
}
/*
匿名內部類在開發中的使用 (升級)
*/
interface Person {
public abstract void study();
}
class PersonDemo {
//介面名作為形式引數
//其實這裡需要的不是介面,而是該介面的實現類的物件
public void method(Person p) {
p.study();
}
}
//實現類 //被匿名內部類代替
class Student implements Person {
public void study() {
System.out.println("好好學習,天天向上");
}
}
class InnerClassTest2 {
public static void main(String[] args) {
//測試
PersonDemo pd = new PersonDemo();
Person p = new Student();
pd.method(p);
System.out.println("--------------------");
代替原來實現介面類的類
//匿名內部類在開發中的使用
//匿名內部類的本質是繼承類或者實現了介面的子類匿名物件
pd.method(new Person(){
public void study() {
System.out.println("好好學習,天天向上");
}
});
}
}
/*
匿名內部類在開發中的使用 (升級)
*/
interface Person {
public abstract void study();
}
class PersonDemo {
//介面名作為形式引數
//其實這裡需要的不是介面,而是該介面的實現類的物件
public void method(Person p) {
p.study();
}
}
//實現類 //被匿名內部類代替
class Student implements Person {
public void study() {
System.out.println("好好學習,天天向上");
}
}
class InnerClassTest2 {
public static void main(String[] args) {
//測試
PersonDemo pd = new PersonDemo();
Person p = new Student();
pd.method(p);
System.out.println("--------------------");
代替原來實現介面類的類
//匿名內部類在開發中的使用
//匿名內部類的本質是繼承類或者實現了介面的子類匿名物件
pd.method(new Person(){
public void study() {
System.out.println("好好學習,天天向上");
}
});
}
}
- 進入lambda表示式:
- 這個表示式和匿名內部類有相同的作用(都是用來代替實現介面類) 但是要比匿名內部類簡單的多。
話不多說 看程式碼:
interface command
{
//接口裡定義的process 方法用於封裝“出路行為”
void process(int[] target);
}
public class ProcessArray
{
public void process(int[] target , command cmd)
{
cmd.process(target);
}
}
//這個是要被匿名內部類和lambda代替的東東
public class PrintCommand implaments Command
{
public void process(int[] target )
{
for(int tmp :target)
{
System.out.println("遍歷"+tmp);
}
}
}
/*這是普通寫*/
public class CommandTest
{
public static void main(Strint[] args)
{
ProcessArray pa = new ProcessArray();
int[] target = {3,-4,6,4};
pa.process(target , new PrintCommand());
}
}
/*這是匿名內部類寫(代替實現介面的類)*/
public class CommandTest1
{
public static void main(Strint[] args)
{
ProcessArray pr = new ProcessArray();
int[] target = {3.-4.6.4};
pa.process(target , new Command())
{
public void process(int[] target)
{
for(int tmp : target)
{
System.out.println("遍歷:"+tmp);
}
}
}
}
}
/*使用lambda表示式((終極版)仍然代替實現介面的類)*/
public class CommandTest2
{
public static void main(Strint[] args)
{
ProcessArray pr = new ProcessArray();
int[] array = {3.-4.6.4};
pa.process(array ,(int[] target)->{
for(int tmp : target)
{
System.out.println("遍歷"+tmp);
}
});
}
}
- lambda表示式允許使用更簡潔的程式碼來建立只有一個抽象方法的介面(函式式介面)
- 它由三部分組成 1.形參列表。允許省略形參型別。如果只有一個形參 也可以省略() 2.箭頭 (->)。 3.程式碼塊。
- lambda表示式和匿名內部類的聯絡:
- 聯絡:
- 都可以直接訪問(預設final修飾)區域性變數,以及外部類的成員變數 (例項變數和類變數)
- lambda建立的物件和匿名內部類生成的物件一樣 都可以直接呼叫從介面中繼承的預設方法
- 聯絡: