首页 > 代码库 > 黑马程序员_Java基础加强(下)

黑马程序员_Java基础加强(下)

 

8、注解类

注解相当于一种标记,加了注解就等于打上了某种标记,没加就等于没打特殊标记,开发工具和其他程序可以用反射来了解你的类及各种元素上有无何种标记,看你有什么标记就去干什么事,标记可以加在包、类、字段、方法,方法的参数以及局部变量上。

注解的应用结构图:

为注解增加属性

定义基本类型的属性和应用属性

在注解类中增加String color();

@MyAnnotation(color = "red")

用反射方式获得注解对应的实例对象后,再通过该对象调用属性对应的方法

MyAnnotation a =(MyAnnotation)AnnotationTest.class.getAnnotation(MyAnnotation.class);

System.out.println(a.color);

可以认为上面这个@MyAnnotation是MyAnnotation类的一个实例对象。

为属性指定缺省值

String color() default"yellow";

value属性

String value() default "xyz"

为注解增加高级属性

数组类型的属性

int[] arrayAttr() default {1,2,3}

@MyAnnotation(arrayAttr={2,3,4})

如果数组属性中只有一个元素,这时候属性值部分可以省略大括号

枚举类型的属性

EnumTest.TrafficLamp lamp();

MateAnnotation annotationAttr() default @MateAnnotation("xxxxx")

@MyAnnotation(annotationAttr = @MateAnnotation("yyy"))

可以认为上面这个@MyAnnotation是MyAnnotation类的一个实例对象,同样道理可以认为上面这个@MateAnnotation是MateAnnotation类的一个实例对象调用代码如下:

MateAnnotation ma=myAnnotation.annotationAttr();

System.out.println(ma.value());

例:

package cn.itcast.day2;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

import javax.lang.model.element.Element;

import cn.itcast.day1.EnumTest;

@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD,ElementType.TYPE})
public @interface ItcastAnnotation { //创建注解类
    String color() default "blue";
    String value();
    int[] arrayAtt() default {3,4,5};
    EnumTest.TrafficLamp lamp() default EnumTest.TrafficLamp.RED;
    MetaAnnotation annotationAttr() default @MetaAnnotation("lhm");
}
package cn.itcast.day2;

@ItcastAnnotation(annotationAttr = @MetaAnnotation("flx"), color = "red",value = "http://www.mamicode.com/abc",arrayAtt = {1,2,3})
public class AnnotationTest {

    @SuppressWarnings("deprecation")
    @ItcastAnnotation("xyz")
    public static void main(String[] args){
        
        System.runFinalizersOnExit(true);
        
        if(AnnotationTest.class.isAnnotationPresent(ItcastAnnotation.class)){
            
            ItcastAnnotation annotation = (ItcastAnnotation)AnnotationTest.class.getAnnotation(ItcastAnnotation.class);
            System.out.println(annotation.color());
            System.out.println(annotation.value());
            System.out.println(annotation.arrayAtt().length);
            System.out.println(annotation.lamp().nextLamp().name());
            System.out.println(annotation.annotationAttr().value());
        }
    }
    
    @Deprecated
    public static void sayHello(){
        System.out.println("hi,传智播客");
    }
}
public @interface MetaAnnotation {

    String value();
}

9、泛型

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

例:

import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import java.util.Vector;

import cn.itcast.day1.ReflectPoint;

public class GenericTest {

    public static void main(String[] args) throws Exception{
        // TODO Auto-generated method stub
        ArrayList connection1 = new ArrayList();
        connection1.add(1);
        connection1.add(1L);
        connection1.add("abc");
        //int i = (Integer)connection1.get(1);

        ArrayList<String> connection2 = new ArrayList<String>();
        //connection2.add(1);
        //connection2.add(1L);
        connection2.add("abc");
        String element = connection2.get(0);
        
        
        Constructor<String> constructor1 = String.class.getConstructor(StringBuffer.class);
        String str2 = constructor1.newInstance(new StringBuffer("abc"));
        System.out.println(str2.charAt(2));
        
        ArrayList<Integer> connection3 = new ArrayList<Integer>();
        System.out.println(connection3.getClass() == connection2.getClass());
        
        connection3.getClass().getMethod("add", Object.class).invoke(connection3, "abc");
        System.out.println(connection3.get(0));
        
        printCollection(connection3);
        
        //Class<Number> x = String.class.asSubclass(Number.class);
        Class<?> y;
        Class<String> x;
        
        HashMap<String,Integer> maps = new HashMap<String,Integer>();
        maps.put("zxx", 20);
        maps.put("lhm", 30);
        maps.put("flx", 35);
        
        Set<Map.Entry<String,Integer>> entrySet = maps.entrySet();
        for(Map.Entry<String,Integer> entry : entrySet){
            System.out.println(entry.getKey()+":"+entry.getValue());
        }
        
        add(3,5);
        add(3.5,3);
        add(3,"abc");
    
        swap(new String[]{"abc","xyz","123"},1,2);
        
        Object obj = "abc";
        String x3 = autoConvert(obj);
        
        copy1(new Vector<String>(),new String[10]);
        copy2(new Date[10],new String[10]);
        //copy1(new Vector<Date>(),new String[10]);
    
        GenericDao<ReflectPoint> dao = new GenericDao<ReflectPoint>();
        dao.add(new ReflectPoint(3,3));
        //String s = dao.findById(0);
        
        //Vector<Date> v1 = new Vector<Date>();
        Method applyMethod = GenericTest.class.getMethod("applyVector", Vector.class);
        Type[] types = applyMethod.getGenericParameterTypes();
        ParameterizedType pType = (ParameterizedType)types[0];
        System.out.println(pType.getRawType());
        System.out.println(pType.getActualTypeArguments()[0]);
    }
    public static void applyVector(Vector<Date> v1){
        
    }
    private static <T> void fillArray(T[] a,T obj){
        for(int i=0;i<a.length;i++){
            a[i] = obj;
        }
    }
    private static <T> T autoConvert(Object obj){
        return (T)obj;
    }
    
    private static <T> void swap(T[] a,int i,int j){
        T tmp = a[i];
        a[i] = a[j];
        a[j] = tmp;
        
    }
    private static <T> T add(T x , T y){
        
        return null;
    }
    public static void printCollection(Collection<?> collection){
        
        System.out.println(collection.size());
        for(Object obj : collection){
            System.out.println(obj);
        }
    }
    public static <T> void printCollection2(Collection<T> collection,T obj2){
        
        System.out.println(collection.size());
        for(Object obj : collection){
            System.out.println(obj);
        }
        collection.add(obj2);
    }
    public static <T> void copy1(Collection <T> dest,T[] src){
        
    }
    public static <T> void copy2(T[]
            dest,T[] src){
        
    }
}
import java.util.Set;

public class GenericDao <T> {

    public void add(T X){
        
    }
    public T findById(int id){
        
        return null;
    }
    public void delete(T obj){
        
    }
    public void delete(int id){
        
    }
    public void updata(T obj){
        
    }
    public static <T> void updata2(T obj){
        
    }
    public T findByUserName(String name){
        return null;
    }
    public Set<T> findByConditions(String where){
        
        return null;
    }
}

10、类加载器

类加载器也是Java类因为其他Java类的类加载器本身也要被类加载器加载,显然必须有第一个类加载器不是Java类,这正是BootStrap(c++提供的类)

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

类加载器之间的父子关系和管辖范围图

类加载器的委托加载机制

当Java虚拟机要加载一个类时到底派出哪个类加载器加载呢?

首先当前现成的类加载器去加载线程中的第一个类

如果A中引用了类B,Java虚拟机将使用加载类A的类加载器来加载类B

还可以直接调用ClassLoader.loadClass()方法来指定某个类加载器去加载某个类

11、代理类

程序中的代理是指要为已存在的多个具有相同接口的目标类的各个方法增加一些系统功能,例如:异常处理、日志、计算方法的运行时间、事务管理等等

代理架构图:

例:

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.Collection;

public class ProxyTest {

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        Class clazzProxy1 = Proxy.getProxyClass(Collection.class.getClassLoader(),Collection.class);
        System.out.println(clazzProxy1.getName());

        System.out.println("");
        /*$Proxy0();
         $Proxy0(InvocationHandler,int);*/
        Constructor[] constructors = clazzProxy1.getConstructors();
        for(Constructor constructor :constructors){
            String name = constructor.getName();
            StringBuilder sBuilder = new StringBuilder(name);
            sBuilder.append(‘(‘);
            Class[] clazzParams = constructor.getParameterTypes();
            for(Class clazzParam : clazzParams){
                sBuilder.append(clazzParam.getName()).append(‘,‘);
            }
            if(clazzParams!=null && clazzParams.length!=0){
                sBuilder.deleteCharAt(sBuilder.length()-1);
            }
            sBuilder.append(‘)‘);
            System.out.println(sBuilder.toString());
        }
        System.out.println("");
        /*$Proxy0();
         $Proxy0(InvocationHandler,int);*/
        Method[] methods = clazzProxy1.getMethods();
        for(Method method :methods){
            String name = method.getName();
            StringBuilder sBuilder = new StringBuilder(name);
            sBuilder.append(‘(‘);
            Class[] clazzParams = method.getParameterTypes();
            for(Class clazzParam : clazzParams){
                sBuilder.append(clazzParam.getName()).append(‘,‘);
            }
            if(clazzParams!=null && clazzParams.length!=0){
                sBuilder.deleteCharAt(sBuilder.length()-1);
            }
            sBuilder.append(‘)‘);
            System.out.println(sBuilder.toString());
        }
        
    }

}