1.Java泛型?
泛型(Generic type 或者 generics)是对 Java 语言的类型系统的一种扩展,以支持创建可以按类型进行参数化的类。可以把类型参数看作是使用参数化类型时指定的类型的一个占位符,就像方法的形式参数是运行时传递的值的占位符一样。
在Java SE 1.5之前,没有泛型的情况的下,通过对类型Object的引用来实现参数的“任意化”,“任意化”带来的缺点是要做显式的强制类型转换,而这种转换是要求开发者对实际参数类型可以预知的情况下进行的。对于强制类型转换错误的情况,编译器可能不提示错误,在运行的时候才出现异常,这是一个安全隐患。
泛型的好处是在编译的时候检查类型安全,并且所有的强制转换都是自动和隐式的,提高代码的重用率。
泛型(Generic type 或者 generics)是对 Java 语言的类型系统的一种扩展,以支持创建可以按类型进行参数化的类。可以把类型参数看作是使用参数化类型时指定的类型的一个占位符,就像方法的形式参数是运行时传递的值的占位符一样。
在Java SE 1.5之前,没有泛型的情况的下,通过对类型Object的引用来实现参数的“任意化”,“任意化”带来的缺点是要做显式的强制类型转换,而这种转换是要求开发者对实际参数类型可以预知的情况下进行的。对于强制类型转换错误的情况,编译器可能不提示错误,在运行的时候才出现异常,这是一个安全隐患。
泛型的好处是在编译的时候检查类型安全,并且所有的强制转换都是自动和隐式的,提高代码的重用率。
注意:Java的泛型不同于C++,可以说是表面上的,只针对编译器;
它的应用省略了反射技术时候类型的转换,但是因为编译成字节码后,会去掉泛型的类型信息,
所以我们可以跳过编译器,通过反射向技术指定类型的容器中加入其他类型的元素
ArrayList<Integer> collections = new ArrayList<Integer>();
collections.getClass().getMethod("add", Object.class)
.invoke(collections, "abc");
System.out.println(collections.get(0));
HashMap的迭代遍历:
//HashMap 的迭代遍历
HashMap<String, Integer> map = new HashMap<String,Integer>();
map.put("daoqin", 25);
map.put("bifei", 23);
map.put("flaygo", 23);
Set<Map.Entry<String, Integer>> entrySet = map.entrySet();
// for(Map.Entry<String, Integer> entry:entrySet){
// System.out.println(entry.getKey() + "::" + entry.getValue());
// }
Iterator<Map.Entry<String, Integer>> itor = entrySet.iterator();
while(itor.hasNext()){
Map.Entry<String, Integer> entry = itor.next();
System.out.println(entry.getKey() + "::" + entry.getValue());
}
通过反射获得范型的实际类型参数
Vector<Date> v1 = new Vector<Date>();
Method applyMethod = GenericTest.class.getMethod("applyVector", Vector.class);
Type[] type = applyMethod.getGenericParameterTypes();
ParameterizedType paty = (ParameterizedType) type[0];//转为参数化类型
System.out.println(paty.getRawType());//表示声明此类型的类或接口
System.out.println(paty.getActualTypeArguments()[0]);//表示此类型实际类型参数的 Type 对象的数组
}
public static void applyVector(Vector<Date> v){
}
我们无法直接通过反射获取容器中的元素类型的,只能通过反射获取一个方法Method,然后通过Method相应的方法获取容器中的元素类型
2.类加载器
JVM的类加载是通过ClassLoader及其子类来完成的,类的层次关系和加载顺序可以由下图来描述:
1)Bootstrap ClassLoader
负责加载$JAVA_HOME中jre/lib/rt.jar里所有的class,由C++实现,不是ClassLoader子类
2)Extension ClassLoader
负责加载java平台中扩展功能的一些jar包,包括$JAVA_HOME中jre/lib/*.jar或-Djava.ext.dirs指定目录下的jar包
3)App ClassLoader
负责记载classpath中指定的jar包及目录中class
4)Custom ClassLoader
属于应用程序根据自身需要自定义的ClassLoader,如tomcat、jboss都会根据j2ee规范自行实现ClassLoader
加载过程中会先检查类是否被已加载,检查顺序是自底向上,从Custom ClassLoader到BootStrap ClassLoader逐层检查,只要某个classloader已加载就视为已加载此类,保证此类只所有ClassLoader加载一次。而加载的顺序是自顶向下,也就是由上层来逐层尝试加载此类。这个就是类加载器的委托机制。
自定义一个类加载器:
1.必须继承ClassLoader类
2.重写findClass方法,在其中调用defineClass方法
public class MyClassLoad extends ClassLoader{
public static void main(String[] args) throws Exception {
// TODO Auto-generated method stub
//通过反射技术利用自定义类加载器寻找Class
Class cl = new MyClassLoad("swustlib").loadClass("com.ClassLoad.ClassLoadAttch");
System.out.println(cl.newInstance().toString());//生成新对象
}
public static void cpy(InputStream ips,OutputStream ops) throws IOException{//Class文件加解密
int b = -1;
while((b=ips.read())!=-1){
ops.write(b^0xff);
}
}
private String classDir;
@Override
protected Class<?> findClass(String name) throws ClassNotFoundException {
// TODO Auto-generated method stub
String classFilename = classDir + "\\"+name.substring(name.lastIndexOf('.')+1)+".class";
try {
FileInputStream fis = new FileInputStream(classFilename);
ByteArrayOutputStream bos = new ByteArrayOutputStream();
cpy(fis, bos);
fis.close();
byte[] bytes = bos.toByteArray();//转为字节数组
System.out.println("success");
return defineClass(bytes, 0, bytes.length);//调用define方法
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}
public MyClassLoad(){
}
public MyClassLoad(String classDir){
this.classDir = classDir;
}
}