在泛型中可以同时有多个类型参数,在定义它们的尖括号中用逗号分开,例如:
public static <K,V> V getValue(K key){return map.get(key);}
如何自动将Object类型的对象转换成其他类型
public static void main(String[] args){
Object obj="wangli";
String x=autoConvert(obj);
}
private static <T> T autoConvert(Object obj){
return (T)obj;
}
定义一个方法,可以将任意类型的数组中的所有元素填充为相应类型的某个对象
private static <T> void fillArray(T[] a,T obj){
for(int i=0;i<a.length;i++){
a[i]=obj;
}
}
采用自定义泛型方法的方式打印出任意参数化类型的集合中的所有内容
在此情况下,通配符的方法要比下面的方法更有效,当一个类型变量用来表达两个参数之间或者参数和返回值之间的关系时,即同一个类型变量在方法签名的两处被使用,或者类型变量在方法体代码中也被使用而不是仅在签名的时候使用,才需要使用泛型方法。
public static <T> void pointCollection1(Collection<T> collection){
//collection.add("abc");
System.out.println(collection.size());
for(Object obj:collection){
System.out.println(obj);
}
}
把任意参数类型的集合中的数据安全地复制到相应类型的数组中
把任意参数类型的一个数组中的数据安全地复制到相应类型的另一个数组中
public static void main(String[] args){
copy1(new Vector<String>(),new String[10]);
copy2(new Date[10],new String[10]);
//copy1(new Vector<Date>(),new String[10]);//错误
}
public static <T> void copy1(Collection<T> desc,T[] src){
......
}
public static <T> void copy2(T[] desc,T[] src){
......
}
定义泛型类型
1、如果类的实例对象中的多处都要用到同一个泛型参数,即这些地方引用的泛型类型要保持同一个实际类型时,这时候就要采用泛型类型的方式进行定义,也就是类级别的泛型,语法格式为:
public class GenericDao<T>{
private T fleld1;
public void save(T obj){}
public T getById(int id){}
}
2、类级别的泛型是根据引用该类名时指定的类型信息来参数化类型变量的,以下两种方式都行:
GenericDao<String> dao=null;
new genericDao<String>();
3、在对泛型类型进行参数化时,类型参数的实例必须是引用类型,不能是基本类型。
当一个变量被声明为泛型时,只能被实例变量和方法调用(还有内嵌类型),而不是被静态变量和静态方法调用。因为静态成员是被所有参数化的类所共享的,所以静态成员不应该有类级别的类型参数。
例:
import java.util.Set;
public class GenericDao<T> {
public void add(T x){
}
public T findById(int id){
return null;
}
public void delete(T obj){
}
public void delete(int obj){
}
public void update(T obj){
}
public static <T> void update1(T obj){
}
public T findByUserName(String name){
return null;
}
public Set<T> findByConditions(String where){
return null;
}
}
public class GenericTest{
public static void main(String[] args){
GenericDao<ReflectPoint> dao=new GenericDao<ReflectPoint>();
dao.add(new ReflectPoint(3,3));
//String s=dao.findById(2);//错误
}
}
类中只有一个方法需要使用泛型时,那么使用的是类级别的泛型
通过反射获得泛型的实际类型参数
public static void main(String[] args){
//Vector<Date> v1=new Vector<Date>();
Method applyMethod = GenericTest.class.getMethod("applyVector", Vector.class);
Type[] types=applyMethod.getGenericParameterTypes();
ParameterizedType pType=(ParameterizedType)types[0];
System.out.println(pType.getRawType());
System.out.println(pType.getActualTypeArguments()[0]);
}
public static void applyVector(Vector<Date> v1){}
类加载器
java虚拟机中可以安装多个类加载器,系统默认三个主要的类加载器,每个类负责加载特定位置的类:BootStrap,ExtClassLoader,AppClassLoader
类加载器也是java类,因为其他事java类的类加载器本身也要被类加载器加载,显然必须有第一个类加载器不是java类,这正是BootStrap。
java虚拟机中的所有类装载器采用具有父子关系的树形结构进行组织,在实例化每个类装载器对象时,需要为其指定一个父级类装载器对象或者默认采用系统类装载器为其父级类加载
类加载器的委托机制
当java虚拟机要加载一个类时,到底派出哪个类加载器去加载呢?
1首先当前线程的类加载器去加载线程中的第一个类。
2如果类A中引用了类B,java虚拟机将使用加载类A的类装载器来加载类B。
3还可以直接调用ClassLoader.loadClass()方法来指定某个类加载器去加载某个类。
每个类加载器加载类时,又先委托给其上级类加载器。
类加载器之间的关系和管辖范围
BootStrap类加载器管辖范围JRE/lib/rt.jar
ExtClassLoader类加载管辖范围JRE/lib/ext/*.jar
AppClassLoader类加载器管辖范围CLASSPATH指定的所有jar或目录
如果BootStrap是爷爷的话,那么ExtClassLoader就是爸爸,AppClassLoader就是儿子
自定义的类加载器必须继承ClassLoader
首先编写一个对文件内容进行简单加密的程序.
public static void cypher(InputStream istream,OutputStream ostream) throws Exception{
/*
byte b=0;
while((b=(byte)istream.read())!=-1){
ostream.write(b^0*ff);
}
*/
int b=0;
while((b=istream.read())!=-1){
ostream.write(((byte)b)^0*ff);
}
}