Java學習筆記七(面向對象特徵之多態)

多態性:

多態性的理解:可以理解爲一個事物的多種形態;
何爲多態:父類的引用指向子類的對象;
多態的使用:(虛擬方法調用)
有了對象的多態性之後,我們在編譯期只能調用父類中聲明的方法,但在運行期,實際執行的是子類重寫父類的方法
總結:編譯看左邊,運行看右邊。
多態性使用的前提:①類的繼承關係②方法的重寫
注意:對象的多態性只使用於方法,不適用於屬性(也就是說屬性是編譯運行都看右邊)

public class PersonTest {
	
	
	public static void main(String[] args) {
		
		Person p1 = new Person();
		p1.eat();
		
		Man man = new Man();
		man.eat();
		man.age = 25;
		man.earnMoney();
		
		//*************************************************
		System.out.println("*******************");
		//對象的多態性:父類的引用指向子類的對象
		Person p2 = new Man();
//		Person p3 = new Woman();
		//多態的使用:當調用子父類同名同參數的方法時,實際執行的是子類重寫父類的方法 ---虛擬方法調用
		p2.eat();//男人多喫肉,長肌肉
		p2.walk();//男人霸氣的走路
		
//		p2.earnMoney();
		
		System.out.println(p2.id);//1001
		
	}
}
//多態性的使用舉例一:
public class AnimalTest {
	
	public static void main(String[] args) {
		
		AnimalTest test = new AnimalTest();
		test.func(new Dog());
		
		
		test.func(new Cat());
	}
	
	public void func(Animal animal){//Animal animal = new Dog();
		animal.eat();
		animal.shout();
		
		if(animal instanceof Dog){
			Dog d = (Dog)animal;
			d.watchDoor();
		}
	}
	
//	public void func(Dog dog){
//		dog.eat();
//		dog.shout();
//	}
//	public void func(Cat cat){
//		cat.eat();
//		cat.shout();
//	}
}


class Animal{
	
	
	public void eat(){
		System.out.println("動物:進食");
	}
	
	public void shout(){
		System.out.println("動物:叫");
	}
	
	
}

class Dog extends Animal{
	public void eat(){
		System.out.println("狗喫骨頭");
	}
	
	public void shout(){
		System.out.println("汪!汪!汪!");
	}
	
	public void watchDoor(){
		System.out.println("看門");
	}
}
class Cat extends Animal{
	public void eat(){
		System.out.println("貓喫魚");
	}
	
	public void shout(){
		System.out.println("喵!喵!喵!");
	}
}

//舉例二:

class Order{
	
	public void method(Object obj){
		
	}
}

//舉例三:
class Driver{
	
	public void doData(Connection conn){//conn = new MySQlConnection(); / conn = new OracleConnection();
		//規範的步驟去操作數據
//		conn.method1();
//		conn.method2();
//		conn.method3();
		
	}
	
}

面試題:多態是編譯時行爲還是運行時行爲?
程序證明如下:(運行時行爲)

//證明如下:
class Animal  {
 
	protected void eat() {
		System.out.println("animal eat food");
	}
}

class Cat  extends Animal  {
 
	protected void eat() {
		System.out.println("cat eat fish");
	}
}

class Dog  extends Animal  {
 
	public void eat() {
		System.out.println("Dog eat bone");

	}

}

class Sheep  extends Animal  {
 

	public void eat() {
		System.out.println("Sheep eat grass");

	}

 
}

public class InterviewTest {

	public static Animal  getInstance(int key) {
		switch (key) {
		case 0:
			return new Cat ();
		case 1:
			return new Dog ();
		default:
			return new Sheep ();
		}

	}

	public static void main(String[] args) {
		int key = new Random().nextInt(3);

		System.out.println(key);

		Animal  animal = getInstance(key);
		
		animal.eat();
		 
	}

}

Object類:

java.lang.Object類是所有類的根父類;如果在類的聲明中沒有使用extends表明其父類,則默認java.lang.Objece爲其父類;Object類中的功能(屬性和方法)具有通用性。
Object類中無屬性;
Object類中的方法包括:equals()、toString()、getClass()、hashCode()、clone()、finalize()、wait()、notify()、notifyAll();
並且在Object類中值聲明瞭一個空參的構造器。

面試題final、finally、finalize的區別:
待添加。

public class ObjectTest {

	public static void main(String[] args) {
		
		Order order = new Order();
		System.out.println(order.getClass());//class com.atguigu.java1.Order
		//System.out.println(order.getClass().getSuperclass());//class java.lang.Object

	}
}

class Order{
	
}

Object類的clone()的使用:

public class CloneTest {
	public static void main(String[] args) {
		Animal a1 = new Animal("花花");
		try {
			Animal a2 = (Animal) a1.clone();
			System.out.println("原始對象:" + a1);
			//原始對象:Animal [name=花花]
			a2.setName("毛毛");
			System.out.println("clone之後的對象:" + a2);
			//clone之後的對象:Animal [name=毛毛]
		} catch (CloneNotSupportedException e) {
			e.printStackTrace();
		}
	}
}

class Animal implements Cloneable{
	private String name;

	public Animal() {
		super();
	}

	public Animal(String name) {
		super();
		this.name = name;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	@Override
	public String toString() {
		return "Animal [name=" + name + "]";
	}
	
	@Override
	protected Object clone() throws CloneNotSupportedException {
		// TODO Auto-generated method stub
		return super.clone();
	}
	
}

Object類中的toString()方法:

當我們輸出一個對象的引用是,實際調用的就是當前對象的toString()方法;
Object類中toString()的定義:
public String toStrong(){
return getClass().getName() + ‘@’ + Inteager.toHexString(hashCode());
}
像String、Date、File、包裝類等都重寫了Object類中的toSring方法,使得在調用對象的toString方法是返回“實體內容”。

public class ToStringTest {
	public static void main(String[] args) {
		
		Customer cust1 = new Customer("Tom",21);
		System.out.println(cust1.toString());//com.atguigu.java1.Customer@15db9742-->Customer[name = Tom,age = 21]
		System.out.println(cust1);//com.atguigu.java1.Customer@15db9742-->Customer[name = Tom,age = 21]
		
		String str = new String("MM");
		System.out.println(str);//MM
		
		Date date = new Date(4534534534543L);
		System.out.println(date.toString());//Mon Sep 11 08:55:34 GMT+08:00 2113
		
	}
}

Finalize的使用:

public class FinalizeTest {
	public static void main(String[] args) {
		Person p = new Person("Peter", 12);
		System.out.println(p);
		p = null;//此時對象實體就是垃圾對象,等待被回收。但時間不確定。
		System.gc();//強制性釋放空間
	}
}

class Person{
	private String name;
	private int age;

	public Person(String name, int age) {
		super();
		this.name = name;
		this.age = age;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public int getAge() {
		return age;
	}
	public void setAge(int age) {
		this.age = age;
	}
	//子類重寫此方法,可在釋放對象前進行某些操作
	@Override
	protected void finalize() throws Throwable {
		System.out.println("對象被釋放--->" + this);
	}
	@Override
	public String toString() {
		return "Person [name=" + name + ", age=" + age + "]";
	}
	
}

面試題: == 和 equals() 區別:

一、回顧 == 的使用
== :運算符
1、可以使用在基本數據類型變量和引用數據類型變量中
2、 如果比較的是基本數據類型變量:比較兩個變量保存的數據是否相等。(不一定類型要相同)
如果比較的是引用數據類型變量:比較兩個對象的地址值是否相同.即兩個引用是否指向同一個對象實體
補充: == 符號使用時,必須保證符號左右兩邊的變量類型一致。

二、equals()方法的使用:
1、是一個方法,而非運算符
2、只能適用於引用數據類型
3、 Object類中equals()的定義:
public boolean equals(Object object){
return (object == this);
}

說明:Object類中定義的equals()和==的作用是相同的:比較兩個對象的地址值是否相同.即兩個引用是否指向同一個對象實體
4、 像String、Date、File、包裝類等都重寫了Object類中的equals()方法。重寫以後,比較的不是兩個引用的地址是否相同,而是比較兩個對象的"實體內容"是否相同。

5、通常情況下,我們自定義的類如果使用equals()的話,也通常是比較兩個對象的"實體內容"是否相同。那麼,我們就需要對Object類中的equals()進行重寫
重寫的原則:比較兩個對象的實體內容是否相同。

public class EqualsTest {
	public static void main(String[] args) {
		
		//基本數據類型
		int i = 10;
		int j = 10;
		double d = 10.0;
		System.out.println(i == j);//true
		System.out.println(i == d);//true
		
		boolean b = true;
//		System.out.println(i == b);
		
		char c = 10;
		System.out.println(i == c);//true
		
		char c1 = 'A';
		char c2 = 65;
		System.out.println(c1 == c2);//true
		
		//引用類型:
		Customer cust1 = new Customer("Tom",21);
		Customer cust2 = new Customer("Tom",21);
		System.out.println(cust1 == cust2);//false
		
		String str1 = new String("atguigu");
		String str2 = new String("atguigu");
		System.out.println(str1 == str2);//false
		System.out.println("****************************");
		System.out.println(cust1.equals(cust2));//false--->true
		System.out.println(str1.equals(str2));//true
		
		Date date1 = new Date(32432525324L);
		Date date2 = new Date(32432525324L);
		System.out.println(date1.equals(date2));//true
		
		
	}
}
//自動生成的equals()
	@Override
	public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (getClass() != obj.getClass())
			return false;
		Customer other = (Customer) obj;
		if (age != other.age)
			return false;
		if (name == null) {
			if (other.name != null)
				return false;
		} else if (!name.equals(other.name))
			return false;
		return true;
	}
	
	
	
	//重寫的原則:比較兩個對象的實體內容(即:name和age)是否相同
	//手動實現equals()的重寫
//	@Override
	public boolean equals(Object obj) {
	
	System.out.println("Customer equals()....");
		if (this == obj) {
            return true;
        }
		
		if(obj instanceof Customer){
			Customer cust = (Customer)obj;
			//比較兩個對象的每個屬性是否都相同
			if(this.age == cust.age && this.name.equals(cust.name)){
				return true;
			}else{
			return false;
		}
			
			//或
			return this.age == cust.age && this.name.equals(cust.name);
		}else{
			return false;
		
		}		
	}

單元測試:

Java中的JUnit單元測試

  • 步驟:

  • 1.選中當前工程 - 右鍵選擇:build path - add libraries - JUnit 4 - 下一步

  • 2.創建Java類,進行單元測試。

  • 此時的Java類要求:① 此類是public的 ②此類提供公共的無參的構造器

  • 3.此類中聲明單元測試方法。

  • 此時的單元測試方法:方法的權限是public,沒有返回值,沒有形參

  • 4.此單元測試方法上需要聲明註解:@Test,並在單元測試類中導入:import org.junit.Test;

  • 5.聲明好單元測試方法以後,就可以在方法體內測試相關的代碼。

  • 6.寫完代碼以後,左鍵雙擊單元測試方法名,右鍵:run as - JUnit Test

  • 說明:

  • 1.如果執行結果沒有任何異常:綠條

  • 2.如果執行結果出現異常:紅條

@Test
	public void testEquals(){
		String s1 = "MM";
		String s2 = "MM";
		System.out.println(s1.equals(s2));
		//ClassCastException的異常
//		Object obj = new String("GG");
//		Date date = (Date)obj;
		
		System.out.println(num);
		show();
	}

包裝類的使用:

java提供了八種基本數據類型對應的包裝類,使得基本數據類型的變量具有類的特徵;
要求掌握:
基本數據類型、包裝類和String三者之間的相互轉換;

public class MyWrapperTest {
	@Test
	// String -> 基本數據類型,引用數據類型
	public void test5() {
		String str = "123";
		int num1 = Integer.parseInt(str);
		System.out.println(num1);
		
		boolean flag = Boolean.parseBoolean(str);
		System.out.println(flag);
	}
	
	@Test
	// 基本數據類型、引用數據類型 -> String
	public void test4() {
		//方式一:
		int num2 = 98;
		String str2 = num2 + "";
		System.out.println(str2);
		
		//Integer內部定義了IntegerCache結構,IntegerCache中定義了Integer[],
		//保存了從-128~127範圍的整數。如果我們使用自動裝箱的方式,給Integer賦值的範圍在
		//-128~127範圍內時,可以直接使用數組中的元素,不用再去new了。目的:提高效率
		
		Integer in1 = 56;
		System.out.println(in1);
		String str3 = in1 +"";
		System.out.println(str3);
		//方式二
		int num3 = 78;
		String str4 = String.valueOf(num3);
		
		
		String str5 = String.valueOf(in1);
		System.out.println(str5);
	}
	@Test
	// 基本數據類型和引用數據類型之間的互換
	public void test3() {
		// 自動裝箱和自動拆箱
		int num = 12;
		Integer in = num;
		System.out.println(in);
		
		Integer in1 = 98;
		int num1 = in1;
		System.out.println(num1);
	}
	

}

關於包裝類使用的面試題

public class InterviewTest {

	@Test
	public void test1() {
		//如果表達式爲true,則執行表達式1。
		  //如果表達式爲false,則執行表達式2。
		  //表達式1 和表達式2要求是一致的。
		Object o1 = true ? new Integer(1) : new Double(2.0);
		System.out.println(o1);// 1.0

	}

	@Test
	public void test2() {
		Object o2;
		if (true)
			o2 = new Integer(1);
		else
			o2 = new Double(2.0);
		System.out.println(o2);// 1

	}

	@Test
	public void test3() {
		Integer i = new Integer(1);
		Integer j = new Integer(1);
		System.out.println(i == j);//false
		
		//Integer內部定義了IntegerCache結構,IntegerCache中定義了Integer[],
		//保存了從-128~127範圍的整數。如果我們使用自動裝箱的方式,給Integer賦值的範圍在
		//-128~127範圍內時,可以直接使用數組中的元素,不用再去new了。目的:提高效率
		
		Integer m = 1;
		Integer n = 1;
		System.out.println(m == n);//true

		Integer x = 128;//相當於new了一個Integer對象
		Integer y = 128;//相當於new了一個Integer對象
		System.out.println(x == y);//false
	}

}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章