黑馬程序員--數組的反射,反射的實現框架實例,配置文件加載

---------------------- android培訓java培訓、期待與您交流! ----------------------

數組的反射:

l 具有相同元素和維數類型的數組屬於同一個類型,就是具有相同的Class實例對象。

l 代表數組的Class實例對象的getSuperclass()方法返回的父類爲Object類對應的Calss

l 基本類型的一維數組可以被當作Object類型使用,不能當作Object[]類型使用,非基本類型的一維數組,既可以當作Object類型使用,又可以當作Object[]類型使用。

l Arrays.asList()方法處理int[]String[]時的差異;

package com.hncu.day2;

import java.util.Arrays;

public class ArrayReflectDemo {

	public static void main(String[] args) {
		int[] a = new int[]{3,5,8};
		String[] s = new String[]{"com","sun","ibm"};
		System.out.println(a.getClass().getSuperclass());
//打印class java.lang.Object
		System.out.println(s.getClass().getSuperclass());
//打印class java.lang.Object
		
		System.out.println(Arrays.asList(a));//[[I@dc8569]
		System.out.println(Arrays.asList(s));//[com, sun, ibm]

		/*asList()接受的參數是Object[]類型的數組,由於String[]屬於Object[] 而int[]不屬於Object[],
		 int[]會被當作一個對象類型,打印出該對象,而String會被打印出數組中的元素。
		 */
	}
}

打印數組對象以及對象中的內容:

import java.lang.reflect.Array;
import java.util.Arrays;

public class ArrayReflectDemo {

	public static void main(String[] args) {
		int[] a = new int[]{3,5,8};
		String[] s = new String[]{"com","sun","ibm"};
		printObject(a);
		printObject(s);
		printObject("hncu");
	}

	private static void printObject(Object obj) {
		Class cls = obj.getClass();
		if(cls.isArray()) {
			int len = Array.getLength(obj);
			for(int i=0;i<len;i++) {
				System.out.println(Array.get(obj,i));
			}
		}
		else {
			System.out.println(obj);
		}
	}
}
打印結果:
3
5
8
com
sun
ibm
Hncu


 

hashCode方法與HashSet

如果想查找一個集合中是否包含有某個對象,大概的程序代碼怎樣寫呢?當發現某個元素與要查找的對對象進行equals方法比較的結果相等時,則停止繼續查找並返回肯定的信息,否則返回否定的信息。如果是一個集合中有很多元素,譬如有一萬個元素,並且沒有包含要查找的對象時,則意味着你的程序需要從該集合中取出一萬個元素進行啄一的比較才能得到結論,有人發明了一種hashCode算法,來提高查找的效率,這種方式將集合分成若干個存儲區域,每個對象可以計算出一個哈希碼,可以將哈希碼分組,每組分別對應某個存儲區域,根據一個對象的哈希碼就可以確定該對象應該存儲在哪個區域,

hashSet就是採用哈希算法存儲對象的集合,它內部採用對某個數字n進行取餘的方式對哈希碼進行分組的劃分對象的存儲區域。Object中的hashCode用來返回對就java對象的哈希碼,從而提高查找的效率。

爲了保證一個類的實例對象能在HashSet正常存儲,要求這個類的兩個實例對象用equals()方法比較的結果相等時,它們的哈希碼也必須相等,也就是說,如果obj1.equals(obj2)的結果爲true,那麼一下表達式的結果頁要爲true

obj1.hashCode() == obj2.hashCode()

如果一個類的hashCode()方法沒有遵循上述要求,那麼,當這個的兩個實例對象用equals()方法比較的結果相等時,它們本來應該無法同時存儲進Set集合中,但是,如果將它們存儲進HashSet集合中時,由於它們的hashCode()方法的返回值不同,第二個對象首先按哈希碼計算可能會被放進與第一個對象不同的區域中,這樣,它就不可能與第一個對象進行equals方法比較了,也就可能被存儲進HashSet集合中了。Object類的hashCode()方法不能滿足對象被存入到HashSet中的要求,因爲它的返回值是通過對象的內存地址推算出來的,同一個對象在程序運行期間的任何時候返回的哈希值都是始終不變的,所以,只要是兩個不同的實例對象,即使它們的equals方法比較結果相等,它們默認的hashCode方法的返回值是不同的。

提示:

1)通常來說,一個類的兩個實例對象用equals()方法比較的結果相等時,它們的哈希碼也必須相等,但反之則不成立,即euqlas方法比較結果不相等的對象可以有相同的哈希碼,或者說哈希碼相同的兩個對象的equals方法比較的結果可以不等,例如,字符串“BB”"Aa"euqals方法比較結果肯定不相等,但它們的hashCode方法返回值卻相等。

2)當一個對象被存儲進HashSet集合中以後,就不能修改這個對象中的那些參與計算哈希值的字段了,否則,對象修改後的哈希值與最初存儲進HashSet集合中時的哈希值就不同了,在這種情況下,即使在cantains方法使用該對象的當前引用作爲的參數去HashSet集合中檢索對象,也將返回找不到對象的結果。這也會導致從HashSet集合中單獨刪除當前對象,從而造成內存泄露

package com.hncu.day2;

import java.util.Collection;
import java.util.HashSet;

public class ReflectDemo2 {
	
	private int x;
	private int y;
	
	/* (non-Javadoc)
	 * @see java.lang.Object#hashCode()
	 */
	@Override
	public int hashCode() {
		final int prime = 31;
		int result = 1;
		result = prime * result + x;
		result = prime * result + y;
		return result;
	}

	/* (non-Javadoc)
	 * @see java.lang.Object#equals(java.lang.Object)
	 */
	@Override
	public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (getClass() != obj.getClass())
			return false;
		ReflectDemo2 other = (ReflectDemo2) obj;
		if (x != other.x)
			return false;
		if (y != other.y)
			return false;
		return true;
	}

	public ReflectDemo2(int x, int y) {
		this.x = x;
		this.y = y;
	}
	
	
	public static void main(String[] args) {
		Collection<ReflectDemo2> collection = new HashSet<ReflectDemo2>();
		ReflectDemo2 ref1 = new ReflectDemo2(2,4);
		ReflectDemo2 ref2 = new ReflectDemo2(2,4);
		ReflectDemo2 ref3 = new ReflectDemo2(3,4);
		collection.add(ref1);
		collection.add(ref2);
		collection.add(ref3);
		ref3.x=6;
		collection.remove(ref3);//ref3修改了參與計算哈希值的字段X,所以哈希值也改變,該對象存放到別的區域中,打印結果爲2。
		System.out.println(collection.size());
		
		//覆蓋hashCode和equals後ref1和ref2就被當作同一個對象,無法同時存入集合中。打印結果爲2。
		//沒有覆蓋這兩個方法時,ref1和ref2是不同的對象,可以被存入集合中。
		//只覆蓋equals方法而不覆蓋hashCode方法,ref1和ref2的哈希值不同,會被當作兩個對象存入集合中
	}
}


反射的作用:實現框架功能

package com.hncu.day2;

import java.io.FileInputStream;
import java.io.InputStream;
import java.util.Collection;
import java.util.HashSet;
import java.util.Properties;

public class ReflectDemo2 {

	private int x;
	private int y;

	/*
	 * (non-Javadoc)
	 * 
	 * @see java.lang.Object#hashCode()
	 */
	@Override
	public int hashCode() {
		final int prime = 31;
		int result = 1;
		result = prime * result + x;
		result = prime * result + y;
		return result;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see java.lang.Object#equals(java.lang.Object)
	 */
	@Override
	public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (getClass() != obj.getClass())
			return false;
		ReflectDemo2 other = (ReflectDemo2) obj;
		if (x != other.x)
			return false;
		if (y != other.y)
			return false;
		return true;
	}

	public ReflectDemo2(int x, int y) {
		this.x = x;
		this.y = y;
	}

	public static void main(String[] args) throws Exception {
		InputStream ip = new FileInputStream("config.properties");
		Properties props = new Properties();
		props.load(ip);// 加載配置文件
		ip.close();
		String className = props.getProperty("className");
		Collection collection = (Collection) Class.forName(className)
				.newInstance();
		// new的是配置文件的中ArrayList,會被全部加進去

		ReflectDemo2 ref1 = new ReflectDemo2(2, 4);
		ReflectDemo2 ref2 = new ReflectDemo2(2, 4);
		ReflectDemo2 ref3 = new ReflectDemo2(3, 4);
		collection.add(ref1);
		collection.add(ref2);
		collection.add(ref3);

		System.out.println(collection.size());

	}

}


 

配置文件:config.properties(存放在當前項目的路徑下)

className=java.util.ArrayList

 

使用類加載器方法管理配置文件和資源。

方法一:

//使用類加載器加載配置文件,配置文件要放在Class文件所在的目錄。

InputStream ip=ReflectDemo2.class.getClassLoader().getResourceAsStream("config.properties");

方法二:沒有使用類加載器

InputStream ip = ReflectDemo2.class.getResourceAsStream("/config.properties");

//使用的絕對路徑

 

---------------------- android培訓java培訓、期待與您交流! ----------------------

 

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