1. 程式人生 > >java面向物件(下)

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建立的物件和匿名內部類生成的物件一樣 都可以直接呼叫從介面中繼承的預設方法