一、泛型
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的语法