疯狂java


您现在的位置: 疯狂软件 >> 新闻资讯 >> 正文

java高级技术总结 3


 

 自定义泛型
   
    用于放置泛型的类型参数的尖括号应出现在方法的其他所有修饰符之后和在方法的返回类型之前,也就是紧邻返回值之前。按照惯例,类型参数通常用单个大写字母表示。
   
    l交换数组中的两个元素的位置的泛型方法语法定义如下:
   
    static <E> void swap(E[] a, int i, int j) {
   
    E t = a[i];
   
    a[i] = a[j];
   
    a[j] = t;
   
    }//或用一个面试题讲:把一个数组中的元素的顺序颠倒一下
   
    只有引用类型才能作为泛型方法的实际参数,swap(new int[3],3,5);语句会报告编译错误。
   
    除了在应用泛型时可以使用extends限定符,在定义泛型时也可以使用extends限定符,例如,Class.getAnnotation()方法的定义。并且可以用&来指定多个边界,如<V extends Serializable & cloneable> void method(){}
   
    l普通方法、构造方法和静态方法中都可以使用泛型。
   
    l也可以用类型变量表示异常,称为参数化的异常,可以用于方法的throws列表中,但是不能用于catch子句中。
   
    l在泛型中可以同时有多个类型参数,在定义它们的尖括号中用逗号分,例如:public static <K,V> V getValue(K key) { return map.get(key);}
   
    类加载器  Java虚拟机中可以安装多个类加载器,系统默认三个主要类加载器,每个类负责加载特定位置的类:BootStrap,ExtClassLoader,AppClassLoader
   
    类加载器也是Java类,因为其他是java类的类加载器本身也要被类加载器加载,显然必须有第一个类加载器是java类,这正是BootStrap.
   
    lJava虚拟机中的所有类装载器采用具有父子关系的树形结构进行组织,在实例化每个类装载器对象时,需要为其指定一个父级类装载器对象或者默认采用系统类装载器为其父级类加载。

 
    
    加载机制:
   
    当Java虚拟机要加载一个类时,到底派出哪个类加载器去加载呢?
   
    首先当前线程的类加载器去加载线程中的第一个类。

 

如果类A中引用了类B,Java虚拟机将使用加载类A的类装载器来加载类B.
   
    还可以直接调用ClassLoader.loadClass()方法来指定某个类加载器去加载某个类。
   
    每个类加载器加载类时,又先委托给其上级类加载器。
   
    当所有祖宗类加载器没有加载到类,回到发起者类加载器,还加载不了,则抛ClassNotFoundException,不是再去找发起者类加载器的儿子,因为没有getChild方法,即使有,那有多个儿子,找哪一个呢?
   
    对着类加载器的层次结构图和委托加载原理,解释先前将ClassLoaderTest输出成jre/lib/ext目录下的itcast.jar包中后,运行结果为ExtClassLoader的原因。
   
    编写自己的类加载器
   
    编程步骤:
   
    编写了一个自己的类装载器,可实现对类进行装载。
   
    编写一个程序调用类加载器加载类,在源程序中不能用该类名定义引用变量,因为编译器无法识别这个类。程序中可以除了使用ClassLoader.load方法之外,还可以使用设置线程的上下文类加载器或者系统类加载器,然后再使用Class.forName.
   
    代理

 

 
    
    编写一个与目标类具有相同接口的代理类,代理类的每个方法调用目标类的相同方法,并在调用方法时加上系统功能的代码如果采用工厂模式和配置文件的方式进行管理,则不需要修改客户端程序,在配置文件中配置是使用目标类、还是代理类,这样以后很容易切换,譬如,想要日志功能时就配置代理类,否则配置目标类,这样,增加系统功能很容易,以后运行一段时间后,又想去掉系统功能也很容易。
   
    动态代理技术

 
    
    代理类的各个方法中通常除了要调用目标的相应方法和对外返回目标返回的结果外,还可以在代理方法中的如下四个位置加上系统功能代码:
   
    1.在调用目标方法之前
   
    2.在调用目标方法之后
   
    3.在调用目标方法前后
   
    4.在处理目标方法异常的catch块中