JDK1.5的新特性 04

来源:互联网 发布:手机无法安装软件 编辑:程序博客网 时间:2024/06/03 09:33
摘要:
 
一,泛型
       
      A.泛型的由来:强转的麻烦,非法类型的输入,运行后再修改的费事;
     
      B.泛型的原理:a.编译时期,编译器按照泛型限定的类型对程序员输入的元素类型进行鉴定,
                      类型超出限定的范围就报;
                    b.如何证明泛型只作用于编译器?通过反射得到的集合,可以装入任意对象;
                   
      C.需求的扩展:限定范围多元化
                    a.单种类型:<String>
                    b.多种类型:<? extends Person> <? super Student> <? extends Person && super Student>
                    C.任意类型:<?><E><T>
                   
      D.泛型的应用:自定义泛型
                    a.自定义方法泛型
                    b.自定义类泛型
          

二,类加载器

      A.默认加载方法:委托加载机制
      B.委托加载机制的意义:越基础的类(系统类),越不能被覆盖,所以rt.jar优先,ext.jar其次,相对路径最后;
      C.自定义加载器的创建:
      D.加载器、I/O流、位运算的综合运用:class文件加密和解密;
      E.自定义加载器的典例:
               a.Tomcat服务器
               b.MyServlet.class文件
               c.WebappClassLoader加载器
      F.自定义加载器的应用问题:必须把父类class文件与子类class文件放到同一目录下;

 

 笔记:

36,入门泛型的基本应用

    需求:
        1,在向集合添加元素时,加人了非目的对象,却没人提醒,到运行后出错了才发现问题!
        然后回来把不符合条件的对象删除,事后处理,麻烦又耗时,影响工作效率,能不能给集合做些注释,
        让编译器帮忙监督,以确保添加的元素都符合要求?
        2,在定义比较器时,类型转换好麻烦,有没有更好的办法?
       
        技术:泛型-指定类型:在定义集合时,给集合进行元素类型限定即可,同理,在定义类,定义方法时,都可以限定类型;
    让类型转换好麻烦! int i = (Integer)collection1.get(1);
          有问题:执行的时候抛异常!1角标上的集合元素类型不是Integer!!

37,泛型的内部原理及更深应用
    原理和应用
    提问:如何证明泛型是给编译器看的,而不是给虚拟机看的?
          编译时期有作用,运行时期没作用,反射可以直接获取字节码文件,不经过编译,可以向结合添加任意对象;
    总结:
    定义泛型是给编译器看的,通过反射,可以添加元素,也可以获取元素,不受类型限制。
   
    泛型参数,不考虑继承关系,声明和事例要一致;
    思考:
    Vector v1 = new Vector<String>();//对吗?对的
    Vector<Object> v2 = v1;//对吗?对的 编译是对的,运行是错的。
   
38,泛型的通配符扩展应用
    需求扩展:
    1,某种类型:没有通配符  <String>
    2,多种类型:不是只允许String类,而且允许其子类!<?extends Person> / <? super Person> /
                如:HashMap(Map<? extends k,? extends v> m)
    3,区间类型:是某个类的子类,但又是某个类的父类 <? extends XXX & super YYY >
    4,所有类型:<?> <T>
   
   
39,泛型集合的综合应用案例
    需求:如何对其元素进行迭代?
    分析:与List和Set不同,Map集合是成对存储的,所以迭代器不适用,要对元素进行获取,
        需要对外提供键和值的获取方法方法(键作为映射,不需要修改;);
    思路:既然Map没有继承Iterable接口,那么就应该建立一个内部接口继承Iterable接口
    办法:Map子类的内部类Entry:Map.Entry
   
    对自己的能力要有明确要求:1,通过API了解新技术,应用新技术;
                              2,通过eclipse验证、应用、学习新技术;
                              3,通过eclipse方便高效地编写程序;

40,自定义泛型方法及其应用
    用别人的,做自己的出来给别人用。
    <T extends 接口&接口>
   
41,自定义泛型的练习与类型推断总结
    需求:方法需要参数,参数需要类型指定和声明

42,自定义泛型类的应用
    需求:类也需要泛型指定
    对象:dao crud增添改成
    dao
43,通过反射活得泛型的实际类型参数
    需求:我想知道获得每个类的某个方法的泛型类型
    思路:通过字节码和方法名,获得方法对象, 
                   Method applyMethod = GenericTest.class.getMethod("applyVector",Vector.class);
          再通过方法对象获取泛型类型;
                   Type[] types = applyMethod.getGenericParameterTypes();
                  
     总结:代码的封装与组合;以函数、类、包为封装体,以嵌套链接为组合;

44,类加载器及其委托机制的深入分析

    需求:从硬盘到内存,从文件到字节码;如何将class文件加载到内存中?
    分析:不同的class文件,存在不同级别的目录中,不同的目录由不同的加载器负责加载。
    成果:1,BootStrap 爷爷优先加载的是最基础的类(如System类)的class文件——JRE/lib/rt.jar 
          2,ExtClassLoader父亲加载基本的类的class文件                  ——JRE/lib/ext/*.jar
          3,AppClassLoader儿子加载的是自定义类的class文件              ——classpath目录下的类文件
         
          BootStrap,Strap:带,绑定;虚拟机内核自带;
          Ext:abbr. 提取(extract);扩展(extension)
          AppClassLoader,App,应用的意思;也就是我们开发的类是应用层的类;
         
    ClassLoaderTest.java
    默认的三个加载器:己、父、爷
   
    委托加载机制,顶级优先管理模式;
    思考:为什么要不类放到不同目录的jar包中?
    回答:为了分等级,以确保类的优先级,避免重要的基础类被应用类替换(系统优先,扩展其次,自定义最后)

45,自定义类加载器的编写原理分析

    需求:处于安全考虑,对class文件进行加密处理,加载class文件时进行解密,可是默认加载方法(加载委托机制)是没有
          解密功能的,能否建立自定义的加载器?
   
    分析:为了满足个性化的需求,一定有默认加载方式和自定义加载方式,有个描述类加载器的类(ClassLoader),要建立自定义
          的功能,往往要继承类并复写对应方法;
   
    技术:模版方法设计模式
    ClassLoader
    loadClass()
    覆盖findClass 调用defineClass:
    public Class findClass(String name){
        //把字节码数据下载到数组中
        byte[] b = loadClassData(name);
        //把类名,数组,数组的0角标开始获取n个元素,n为数组长度。
        return defineClass(name,b,0,b.length);
    }
   
46,编写对class文件加密的工具类
   
    需求:对class文件加密
    分析:要产生一个加密的文件,必须用到IO流技术和异或运算;
    理解:异或技术,两次异或可以把数据还原;
            |0101 0001|
            |0001 1010| 异或:相同为假,不同为真;
           
            |0100 1011| 结果          
            |0001 1010| 再异或一次
            |0101 0001|
            现象:与0不变,与1必变;
            理论:0&0为0;1&0为1;
                  0&1为1;1&1为0;
            结论:数据变化在1对应位;
            口诀:与1必变,再与再变终还原;
   
     //加密功能
 public static void cypher(InputStream ips,OutputStream ops) throws Exception{
  int data = -1;
  while ((data=ips.read())!=-1) {
   ops.write(data^0xee);
  }
 }
           
47,编写和测试自己编写的解密类加载器
   
    分析:1,密码:class文件加密和解密,必须是同一个异或运算,所以把异或方法定义在加载器类中;
          2,加载:类的加载其实也是流的体现,自定义一个类加载器(MyClassLoader),加载时,调用异或方法(cypher()),
                对流中的数据进行解密;
    让加载器起作用: 删除父加载器对应的目录下的class文件,让虚拟机通过自定义加载器加载class文件,
                    然后重启虚拟机,(重启是必须的)
  
    排除问题的小技巧:window ——show view —— proplems
   
    //打破委托记载机制
 @Override
 protected Class<?> findClass(String name) throws ClassNotFoundException {
  // 获取class文件,需要路径,需要解码
  String classfilename = classDir + "\\"+name + ".class";
  try {
   //建立流,用相印的异或方法进行解密;
   FileInputStream fis = new FileInputStream(classfilename);
   ByteArrayOutputStream bos = new ByteArrayOutputStream();//数组输出流没有目的,只在内存;
   cypher(fis, bos);
   fis.close();
   byte[] bytes = bos.toByteArray();
   return defineClass(bytes,0, bytes.length);
  } catch (Exception e) {
   System.out.println(e);
  }
  return super.findClass(name);
 }
   
48,类加载器的一个高级问题的实验分析
   
    指引:有一个类,是用自己的类加载器加载的;那就是Tomcat服务器,MyServlet.class文件,WebappClassLoader;
    描述:public class MyServlet extends HttpServlet{}    即,MyServlet继承了HttpServlet;全部由WebappClassLoader加载;
  
    问题:当把MyServlet.class文件放到ext目录下后,报错。
  
    思考:一定是加载器找不到class文件,ExtClassLoader在ext下找到了MyServlet.class文件文件;掌握了加载器权,
          其必须亲子加载父类类文件,可惜在自己的管辖范围内找不到父类HttpServelet.class
    结论:1,规则:加载器一旦加载了一个类的类文件,及必须加载该类的父类类文件——负责到底!
          2,措施:把HttpServelet.class也放到ext目录下;——把父类和子类的lass文件放在同一目录下;