黑马程序员——高新技术(二)

来源:互联网 发布:矩阵计算六讲 pdf 编辑:程序博客网 时间:2024/06/05 15:25

------- http://www.itheima.com" target="blank">android培训、http://www.itheima.com" target="blank">java培训、期待与您交流! ----------

一、注解 

  1、元注解

    即,对注解进行注解的注解。

    @Retention(RetentionPolicy.RUNTIME),表示保留这个注解一直到运行时。(注解的生命周期:源文件、class文件、内存中的字节码文件,默认是class文件)

    @Target({ElementType.METHOD,ElementType.TYPE})表示当前注解可以进行注解的元素类型:注解、类(接口、枚举)、方法、成员变量等,当需要指定多种元素类型时,用数组的形式表示。

  2、创建注解类

  @Retention(RetentionPolicy.RUNTIME)

  @Target({ElementType.METHOD,ElementType.TYPE})

  public @interface MyAnnotation {
     //注解的属性默认都是public、abstract的
     String color() default "blue"; //设置默认值
     String value(); //当一个注解只有value一个属性需要设置,可以只写值
     int[] arrayAttr(); //数组类型的属性,如果在设置时只有一个值,可以不写{},arrayAttr = 3
     MyEnum myEnum() default MyEnum.three; //枚举类型的属性
     MetaAnnotation metaAnno() default @MetaAnnotation("元注解"); //注解类型的属性
  }

  3、使用注解

    每次使用一个注解,就相当于创建一个注解对象,需要对属性进行赋值。

    判断一个类上是否使用的指定的注解:类名.class.isAnnotationPresent(注解类.class)

    获得某个类上的某个注解:类名.class.getAnnotation(注解类.class);

 

二、泛型

    泛型是提供给javac编译器使用的,可以限定集合中的输入类型,让编译器挡住源程序中的非法输入,编译器编译带类型说明的集合时会除掉“类型”信息,来保证成员运行效率,对于参数化的泛型类型,getCass()方法的返回值和原始类型完全一样。所以只要跳过编译器,就可以往某个泛型集合中加入其他类型的数据。

    获取某个成员方法中参数的泛型信息:

    public class Demo01 {
       public static void main(String[] args) throws SecurityException, NoSuchMethodException {  
          //1、通过反射获得这个方法的表示对象
          Method method = Demo01.class.getMethod("applyGeneric", List.class);
          //2、获取该方法中的参数化的参数类型数组(中 的第一个)
          Type t = method.getGenericParameterTypes()[0];
          System.out.println(t); //结果:java.util.List
          //3、如果该类型确实是参数化过的,可以转型。ParameterizedType是Type接口的子接口
          ParameterizedType pType = (ParameterizedType) t;
          //4、获取原始类型(不带泛型)
          System.out.println(pType.getRawType()); //interface java.util.List
          //5、获取该类型中泛型数组
          System.out.println(pType.getActualTypeArguments()[0]); //class java.util.Date
     }

     public void applyGeneric(List list){
  
     }
  }

 

三、类加载器

    jvm中有很多类加载器,不同的加载器负责加载不同的java类,系统默认3个主要的:
    1、BootStrap
      加载jre/lib/rt.jar中的class文件。
      类加载器也是一个java类,他也由类加载器加载,就是BootStrap加载器,这个加载器不是java类,他是一个用c++写的二进制字节码,内嵌在jvm中。被他加载的类在获取加载器的时候,返回null。

    2、ExtClassLoader
      加载jre/lib/ext/*.jar中的class文件
    3、AppClassLoader:
      用于加载classpath指定的所有jar或目录

    4、类加载器的委托机制
      当加载一个类的时候,当前类加载器会一层一层委托上级,从最顶层开始加载,如果加载不到,开始往下委托,直到之前的类加载器,如果再找不到,就不会往下委托了,会报异常。

 

四、动态代理

//创建一个代理类对象3个要素:Classloader、被代理类实现的接口、InvocationHandler对象。合而一:
private static Object getProxy(final Object target,final Advice advice) {
    Object proxy = Proxy.newProxyInstance(
        target.getClass().getClassLoader(),
        target.getClass().getInterfaces(),
        new InvocationHandler(){
          @Override
          public Object invoke(Object proxy, Method method, Object[] args)throws Throwable {
            advice.beforeMethod(method);
            Object retVal = method.invoke(target, args);
            advice.afterMethod(method);
            return retVal;
          }
       }
    );
  return proxy;
  //注:代理类只把从Object继承的hashCode、equals 或 toString 方法委托给了InvocationHandler,
  //  其他的(从Object继承的)方法,还由其自己处理。
}