泛型的?通配符扩展应用
<>中的?表示可以引用任意类型,?定义的变量主要用于引用,这就不能调用与参数类型有关的方法了
通配符的扩展
限定通配符的上限 <? extends
Xxx>表示包括Xxx和Xxx的子类
限定通配符的下限 <? super
Xxx>表示包括Xxx和Xxx的父类
编程实例
从一个HashMap中使用迭代的方法取出所有的Key和Value键值对
不能直接对HashMap实例对象迭代,没有实现Iterable接口,只能使用entrySet方法获得set类型的实例对象,这是要使用泛型来指定Key和Value的类型
自定义泛型
定义泛型方法
当我们不确定一个方法的返回值和参数类型时,就可以使用泛型来定义方法和参数,使用方法如下
将一个数组里面的任意两个元素的位置互换,这是由于我们不知道往其中添加的元素的类型,使用泛型来定义
private static <T> T swap(T[]
array,int i.int j){}这样就定义了一个泛型方法
异常也可以这样定义
public static <T extends
Exception> Xxx() throws T{
try{
}catch(Exception e)
}
}
在泛型中可以有多个类型参数,使用,分隔
类型推断有传播性
<T> void
copy1(Collection<T> dest,T[]
src){
0;i<src.length;i++){
void copy1(T[] dest,T[] src){
< src.length;i++){
src[i];
copy1(new Vector<String>(),new
String[10]());
copy2(new Date[10](),new String[10]());这里是取交集,Object
copy1(new Vector<Date>(),new
String[10]());这是不允许的,传播性使得T为Date类型,后面的T为String
类型参数的类型判断
根据调用泛型方法时实际传递的参数或返回值类型来判断
1.只用了一次容易知道,用了多次,但是都是同一种类型也容易
<T> void add(T x,T y){}
add(2,5.5f)此时是Number,编译没问题,运行有问题
<T> T add(T x,T y){}
定义泛型类型
crud对数据库的添删改查dao一般有五个方法,增删改查,查还有一个按条件查询
将类定义为泛型,类里面的方法使用的泛型都是同一个类型了,静态方法不可以使用这里定义的泛型
通过反射获得泛型的参数化类型
通过参数是没办法知道参数化类型的,但是使用参数化类型的方法,上面有获得参数类型的方法,所以通过反射获得方法之后调用该方法可以获得参数化类型的实际类型
框架一般使用这样的方法
类加载器
加载类的工具,系统默认主要有三个BootStrap,ExtClassLoder,AppClassLoder。类加载器也是类,但是BootStrap是负责最开始的加载工作的,所以不是类
AppClassLoder 管辖范围是classpath指定的所有jre或目录
ExtClassLoder
JRE/lib/ext/*.jar
只要是jar包,放在此目录下就会被此类加载器加载
BootStrap
JRE/lib/rt.jar
类加载器的委托机制
使用当前线程的类加载器,若是引用了其他类,其他类也会使用这个类的使用的类加载器去加载
也可以使用ClassLoder.ClassLoder()方法来指定类加载器
当使用类加载器时,会首先交给父类加载器去加载,没有找到会交给祖父类加载器去加载,没有找到会一级级的向下,直到指定的类加载器去加载
能不能自己编写一个java.lang.System类,这里是没有用的,类加载器加载的时钟是JRE/lib/rt.jar中的字节码。。。不会轮到classpath指定的所有jre或目录来加载
编写自己的类加载器
需要继承抽象类ClassLoder类,不需要重写loadClass方法,只需要重写findClass方法使得自己去寻找就行了,将class文件转换为字节码使用definclass()方法
模板设计模式