傳智播客培訓2.19 泛型和反射
一、泛型
1. 為什麼使用泛型?
在jdk5以前,對象一旦存入集合就是去特性,變成Object類型
從集合取出元素時,就需要做強轉,
有的時候我們不確定集合中到底存儲的是什麼類型,強轉時容易出錯
在jdk5中,為了提供集合的安全性,定義了泛型,我們可以在使用集合時利用泛型
限定集合存入的數據類型
2. 用泛型的好處?
在迭代集合時,可以避免強轉的麻煩
將運行時期的錯誤轉移到編譯階段
3. 由於集合是用於存儲對象的,基本數據類型需要包裝後才能存入集合,所以
集合上使用的泛型必須是引用數據類型
4. 什麼情況下用泛型
如果一個類有兩個或多個方法的形參必須為同一種類型,或者方法的返回值必須為同一種類型
就可以使用泛型來解決
簡單來說,在一個類中多個方法使用的類型必須是同一種類型,但是可以為任意類型
5. List<T> 當中T稱為類型參數 List<String> 當中String 實際類型參數
6. 自定義泛型
在類的後麵自定義泛型,類型多處用到的類型需要是同一種類型
// 一個學生對象學習什麼就必須玩什麼
public class Student<T,E> {
// 使用類型參數
public T study(T t) {
return null;
}
public void play(T t) {
}
public void eat(E e) {
}
}
定義泛型方法, 方法的形參和返回值需要是同一種類型
// 求兩個數的最大數
// 判斷兩個對象中的較大者
public static <T> T getMax(T x, T y) {
/*if(x>y)
return x;
return y;*/
// TreeSet
// 判斷x對象是否具備比較的功能
if(x instanceof Comparable) {
Comparable com = (Comparable) x;
int num = com.compareTo(y);
if(num>0)
return x;
return y;
}
// 說明x不具備比較功能
throw new RuntimeException("對不起,比不了!");
}
public static <T> void reverse(T[] arr) {
int start = 0;
int end = arr.length - 1;
while(end>start) {
T temp = arr[start];
arr[start] = arr[end];
arr[end] = temp;
start++;
end--;
}
}
二、反射
1. 理解Class類
對象都是根據類創建出來的—>創建一個對象代表李四這個人—>李四(跑起來)
Person.class(描述所有和李四類似的事物的信息) à Person對象 à 李四(趙六、王五)
Class.class(描述字節碼這類事物的特征) –> Class對象—> Person.class字節碼(Student.class Boy.class String.class)
所有的Person對象能做的事情都用方法來描述,例如跑步用run方法描述
所有的Class對象(字節碼)能做的事情用方法來描述,例如創建對象用newInstance來描述
2. 通過反射獲得Class對象
三種方式獲得
// 1. 根據給定的類名來獲得
String methodname = "run";
String classname = "cn.itcast.reflect.Person"; // 來自配置文件
Class clazz = Class.forName(classname); // 此對象代表Person.class
Object obj = clazz.newInstance(); // 創建對象
// 2. 如果拿到了對象,不知道是什麼類型
Object obj = new Person();
Class clazz1 = obj.getClass(); // 獲得對象具體的類型
// 3. 如果是明確地獲得某個類的Class對象
Class clazz2 = Person.class; // 主要用於傳參
// 在java中所有的類型都會對應一個Class對象 int Integer
Class intClazz = int.class;
Class intarrClazz = int[].class;
Class voidClazz = void.class;
3. 反射能做什麼事情
// 調用任何一個對象的任何方法
// 讀取配置文件獲得如下信息
String classname = "cn.itcast.reflect.Student";
String methodname = "study";
// 把Person的run方法調用
// 1.創建Person對象
Class clazz = Class.forName(classname); // 此對象代表Person.class
Object obj = clazz.newInstance(); // 創建對象
// 2.獲得表示run方法的對象
Method runMethod = clazz.getMethod(methodname);
// 3.通過Person對象來調用run方法
4. 通過反射獲得類的成員變量
// 獲得代表某個屬性的Field對象
Class clazz = Person.class;
Field[] fields = clazz.getDeclaredFields();
for(Field field : fields) {
String name = field.getName(); // 獲得屬性名
Class type = field.getType(); // 獲得屬性的類型
System.out.println("屬性名:" + name + "屬性類型:" + type);
}
// 獲得對象的某個指定的屬性,並為該屬性賦值
// 明確告訴你,獲得name屬性
String fieldname = "name";
Object obj = new Person();
// 1. 獲得Class對象(類)
Class clazz1 = obj.getClass();
// 2. 獲得指定的屬性
Field nameField = clazz1.getDeclaredField(fieldname);
// 3. 為屬性賦值
// 私有屬性不行,因為java虛擬機會檢查訪問權限
// 如果一定要訪問,就需要取消java訪問檢查
nameField.setAccessible(true);
nameField.set(obj, "zhangsan");
/*
Person p = (Person) obj;
System.out.println(p.getName());*/
Object value = nameField.get(obj); // 獲得指定對象上該字段的值
System.out.println(value);
5. 通過反射獲得類的構造方法
// 獲得類
Class clazz = Person.class;
// 獲得類的所有構造函數
Constructor[] constructors = clazz.getConstructors();
for(Constructor con : constructors) {
// 遍曆參數類型
Class[] parameterTypes = con.getParameterTypes();
for(Class type : parameterTypes)
System.out.print(type.getName() + " ");
System.out.println();
}
// 獲得指定的構造函數,創建對象
// 要求調用參數為 String int 的構造函數
// 1. 反射出指定的構造函數
Constructor con = clazz.getConstructor(String.class, int.class);
// 2. 調用構造函數創建對象
Object obj = con.newInstance("wangwu", 23);
System.out.println(obj); // toString
6. 通過反射獲得類的成員方法
Class clazz = Person.class;
// 獲得類的所有方法
Method[] methods = clazz.getDeclaredMethods();
for(Method m : methods) {
String name = m.getName(); // 方法名
System.out.print("方法名:" + name);
// 參數類型
System.out.print(", 參數類型依次為:");
Class[] types = m.getParameterTypes();
for(Class type : types)
System.out.print(type.getName() + " ");
// 返回值類型
Class returnType = m.getReturnType();
System.out.print(",返回值類型:" + returnType.getName());
System.out.println();
}
// 反射出指定的方法,調用
// 創建一個對象
Object obj = clazz.newInstance();
// 調用play方法
Method playMethod = clazz.getMethod("play", String.class);
playMethod.invoke(obj, "zhangsan");
// 調用eat方法
Method eatMethod = clazz.getMethod("eat");
eatMethod.invoke(null);
// 調用sleep方法
Method sleepMethod = clazz.getMethod("sleep", String[].class);
String[] arr = {"a","b"};
sleepMethod.invoke(obj, (Object)arr); // 符合1.4和1.5的語法
最後更新:2017-04-02 06:51:36