现在的位置: 首页 > 综合 > 正文

(黑马程序员—日记8)代理及其他——胜利的曙光就在前方

2013年08月27日 ⁄ 综合 ⁄ 共 4342字 ⁄ 字号 评论关闭

------- android培训java培训、期待与您交流! ----------

        独自,继续前行,路还很长。渐渐地,基础的视频已然是被我啃完了,今天新闻联播的主要内容有...(嘿嘿,给自己来点冷幽默),今天主要学习了代理技术,还有一些其他的知识点,比如注解,泛型,类加载器等等。似乎,胜利的曙光就在前方了。

 

    注解:
java提供几个基本的注解:
   @SuppressWarnings         //表示禁止警告
      通过System.runFinalizersOnExit(true);的编译警告引出@SuppressWarnings("deprecation")
   @Deprecated                       //表示该方法已经过时,在MyEclipse里,调用被注解过的方法会出现一条横线
      直接在刚才的类中增加一个方法,并加上@Deprecated标注,在另外一个类中调用这个方法。
   @Override                            //表示覆写方法
      public boolean equals(Reflect other)方法与HashSet结合讲解

        总结:解相当于一种标记,在程序中加了注解就等于为程序打上了某种标记。标记可以加在包,类,字段,方法,方法的参数以及局部变量上。

     
       元注解

       加在注解上的注解,即对注解进行描述
1、@Retention(RetentionPolicy.RUNTIME|SOURCE|CLASS)
其中的三个属性分别代表代码的三个阶段:java源程序-->class文件-->内存中的字节码
如果不对注解进行@Retention处理的话,默认值是在class文件阶段

2、@Target(ElementType.TYPE...)//用来说明注解可以放在程序的哪个位置,是方法上呢,还是类型上,还是变量上...

        自定义注解:

public @interface MyAnnotation {}

为注解添加高级属性:

       数组类型的属性
   int [] arrayAttr() default {1,2,3};//在注解类中定义,加了default表明默认为{1,2,3}

   @MyAnnotation(arrayAttr={2,3,4})  //在使用注解的时候可以为该数组类型的属性赋值
   如果数组属性中只有一个元素,这时候属性值部分可以省略大括

       枚举类型的属性
   EnumTest.TrafficLamp lamp() ;//该处的枚举是定义好的EnumTest.TrafficLamp,即EnumTest中的内部枚举类型

   @MyAnnotation(lamp=EnumTest.TrafficLamp.GREEN)//使用的时候必须赋值

      注解类型的属性:
   MetaAnnotation annotationAttr() default @MetaAnnotation("xxxx");//注解中的属性还是一个注解

   @MyAnnotation(annotationAttr=@MetaAnnotation(“yyy”) )

 

     泛型:

         泛型是提供给javac编译器使用的,可以限定集合中的输入类型,让编译器挡住源程序中的非法输入,编译器编译带类型说明的集合时会去除掉“类型”信息,使程序运行效率不受影响,对于参数化的泛型类型,getClass()方法的返回值和原始类型完全一样。由于编译生成的字节码会去掉泛型的类型信息,只要能跳过编译器,就可以往某个泛型集合中加入其它类型的数据,例如,用反射得到集合,再调用其add方法即可。

        简单的泛型应用: List<String> list = new ArrayList;   //该List集合中只允许存储String类型的数据

        参数化类型不考虑类型参数的继承关系:
Vector<String> v = new Vector<Object>(); //错误!///不写<Object>没错,写了就是明知故犯
Vector<Object> v = new Vector<String>(); //也错误!

       注意:编译器不允许创建泛型变量的数组。即在创建数组实例时,数组的元素不能使用参数化的类型。

       例如:Vector<Integer> vectorList[] = new Vector<Integer>[8]; //这是错误的

      泛型的集合方式:

  HashMap<String,Integer> hm = new HashMap<String,Integer>();
  hm.put("zxx",19);
  hm.put("lis",18);
 
  Set<Map.Entry<String,Integer>> mes= hm.entrySet();
  for(Map.Entry<String,Integer> me : mes) {
   System.out.println(me.getKey() + ":" + me.getValue());
  }

       总结:
       使用?通配符可以引用其他各种参数化的类型,?通配符定义的变量主要用作引用,可以调用与参数化无关的方法,不能调用与参数化有关的方法

      限定通配符的上边界:
正确:Vector<? extends Number> x = new Vector<Integer>();

     限定通配符的下边界:
正确:Vector<? super Integer> x = new Vector<Number>();
注意:1.限定通配符总是包括自己。2.?只能用作引用,不能用它去给其他变量赋值

       自定义泛型方法:

  public static <T> T[] fill(T[] a, T v) {
      for(int i = 0; i < a.length; i++) a[i] = v;
      return a;  
}

 

     类加载器:
1.Java虚拟机中可以安装多个类加载器,系统默认三个主要类加载器,每个类负责加载特定位置的类:BootStrap,ExtClassLoader,AppClassLoader

2.类加载器也是Java类,因为其他是java类的类加载器本身也要被类加载器加载,显然必须有第一个类加载器不是不是java类,这正是BootStrap。

3.Java虚拟机中的所有类装载器采用具有父子关系的树形结构进行组织,在实例化每个类装载器对象时,需要为其指定一个父级类装载器对象或者默认采用系统类装载器为其父级类加载

       自定义一个类加载器
1、自定义的类加载器必须继承ClassLoader
2、注意loadClass方法和findClass方法的使用
       loadClass已经在父类中定义了找父类的功能,所以不需要复写,自定义类加载器需要做的就是复写findClass方法,这种模式可以称作模版方法设计模式
3、defineClass方法是把Class文件编程字节数组,加载进内存

     代理:
        动态代理技术:
1.JVM可以在运行期动态生成出类的字节码,这种动态生成的类往往被用作代理类,即动态代理类。
2.JVM生成的动态类必须实现一个或多个接口,所以,JVM生成的动态类只能用作具有相同接口的目标类的代理。

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

 

       用以下的代码理解代理的知识:

  ArrayList target = new ArrayList();   //创建目标实例对象
  Advice advice = new MyAdvice();     //创建添加的系统功能实例对象,在这之前先创建接口Advice和期实现子类MyAdvice
  Collection proxy = (Collection)getProxy(target,advice); //通过自定义的方法得到代理对象
  proxy.add("mxl");   
  proxy.add("lsj");
  proxy.add("xjh");
  System.out.println(proxy.size());//使用代理
  

private static Object getProxy(final Object target,final Advice advice) {  //这是抽取出来的方法
  Object proxy = Proxy.newProxyInstance(   //Proxy类中为了使用方便,有一个直接创建代理的方法,而不需要通过Proxy.getProxyClass先得到代理的Class对象,再创建对象

    target.getClass().getClassLoader(), //传入目标类的类加载器

    target.getClass().getInterfaces(),   //传入目标类的实现接口

    new InvocationHandler(){   //创建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;     //返回代理
 }

       小总结:张老师在视频里说注解是很有用的一个知识,但是我到目前为止还没有发现注解的用处有多大,可能在以后的学习过程中会慢慢体会到吧。关于泛型,之前在老毕的视频里已经学到过了,但是张老师的视频里更加深入,总结里面还有一块类型推断的知识没写上去,但是已经做了笔记了。最难的就是代理技术了,看了两遍还是挺模糊的,还得继续学。

抱歉!评论已关闭.