黑马程序员_java基础增强2
2013-05-01 13:27
134 查看
------- android培训java培训、期待与您交流! ----------
泛型也是 JDK1.5的新特性
用了泛型以后不用进行类型转换了,省去了强制类型转化
只要是对象,不管是什么类型的喜爱那个,够可以存储进同一个集合中,使用泛型集合可以将一个
集合中的元素限定为一个特定类型的,JDK1.5推荐使用泛型,不使用泛型会出现警告
泛型是提供给javac编译器使用的,可以限定集合中的输入类型
编译器编译类型说明的结合时会去掉"类型"信息
通过反射可以绕过编译器
ArrayList<Integer>>中的Integer称为实际类型参数或类型参数的实例
ArrayList称为原始类型
Collection<String> c = new Vector<String> ;这个可以通过编译
参数化类型不考虑类型参数的继承关系:
Vector<String> v = new Vector<Object>(); //错误 不写<Object>没错,写了就报错
Vector<Object> v = new Vector<String>(); //也错误
在创建数组实例时,数组的元素不能使用参数化的类型,例如:
Vector<Integer> vectorList[] = new Vector<Integer>[10]; //这个会报错
下面这个不报错很奇怪:
Vector v1 = new Vector<String>();
Vector<Object> v = v1;
如果把这两行代码放在一块就报错这很奇怪
泛型的通配符:
Vector<? extends Number> x = new Vector<Integer>();
限定通配符的下边界:
Vector<? super Integer> x = new Vector<Number>();
限定通配符总是包括自己
泛型中关于map的迭代
如何自己定义一个泛型?
private static <T> T add(T x,T y){
return x;
}
调用add(3,5);
如何定义一个对任意类型的数组里面的值的位置替换的方法?
private static <T> void swap(T [] a ,int i, int j){
T temp = a[i];
a[i] = a[j];
a[j] = temp;
}
}
swap(new String[] { "aa", "bb", "cc" }, 1, 2);
swap(new int[]{1,3,4}, 1, 2);///这行会报错 int基本数据类型不行
普通方法,构造方法和静态方法都可以使用泛型,编译器不允许创建类型变量的数组,即在创建数组实例时,数组
的元素不能使用参数化的类型
在定义泛型的类型是可以定义多个类型参数,在定义它们的时候用<k,v,m>用逗号分开
DAO: data access object--->crud
静态方法不能用泛型
可以以泛型的方法得到参数类型,没法得到泛型中的参数是什么,但是可以通过方法得到泛型中的参数
public static void applyVector(Vector<Date> v1){
}
通过反射获得方法中泛型的参数类型的代码:
Java虚拟机也是Java类,因为其他事java类的类加载器本身也要被类加载器加载
显然必须有第一个类加载器,这个就是BootStrap
java虚拟机默认三个主要类加载器,每个类负责加载特定位置的类:
BootStrap(爷爷),ExClassLoader(父亲),AppClassLoader(儿子)
运行结果为:
ExtClassLoader用来加载JRE/lib/ext/*.jar
AppClassLoader用来加载classpath指定的所有jar或目录的
写自己的类加载器的话都要继承ClassLoader
可以使用自己的类加载器加载自己的特定目录
模板方法设计模式:
父类---->loadClass/findClass/得到class文件的转换成字节码 为了保持loadClass的流程
子类1(自己干)
子类2(自己干)
程序中的代理:
要为已存在的多个具有相同接口的目标类的各个方法增加一些系统功能,
例如,异常处理、日志、计算方法的运行时间、事务管理等等。
代理类的每个方法调用目标类的方法,调用方法的同时加上一些功能
如果采用工厂模式和配置文件的方式进行管理,则不需要修改客户端程序,在配置文件中
配置是使用目标类还是代理类,这样以后很容易切换,譬如:想要日志功能时就配置代理
类否则配置目标类,这样,增加系统功能很容易,以后运行一段时间后,又想去掉系统功
能也很容易
AOP Aspect oriented program 面向切面的编程 系统中存在交叉业务,一个交叉业务就
是要切入到系统中的一个方面
AOP的目标就是要使交叉业务模块化,可以采用将切面代码移动到原始方法的周围,这也直接
在方法中棉鞋切面代码的运行效果是一样的
代理是实现AOP的一个很重要的技术点
要为系统中的各种接口的类增加dialing共鞥,那将需要太多的代理类,全部采用静态代理方式,将
是一件非常麻烦的事情,JVM可以往往用作代理类,在运行期动态生成类的字节码,这种动态生成的类即动态代理类
JVM生成的动态类必须具有一个或多个接口,所以,JVM生成的动态类只能用作具有相同接口的目标类的代理
CGLIB库可以动态生成一个类的子类,一个类的子类也可以用作该类的代理
所以,如果要为一个没有实现接口的类生成动态代理类,那么可以使用CGLIB库
分析JVM动态生成的类
打印一个类的所有的构造方法:
打印结果为:
泛型也是 JDK1.5的新特性
用了泛型以后不用进行类型转换了,省去了强制类型转化
只要是对象,不管是什么类型的喜爱那个,够可以存储进同一个集合中,使用泛型集合可以将一个
集合中的元素限定为一个特定类型的,JDK1.5推荐使用泛型,不使用泛型会出现警告
泛型是提供给javac编译器使用的,可以限定集合中的输入类型
编译器编译类型说明的结合时会去掉"类型"信息
ArrayList<Integer> collection = new ArrayList<Integer>(); collection.add("abc"); //编译会报错
通过反射可以绕过编译器
collection.getClass().getMethod("add",Object.class).invoke(collection,"abc"); System.out.println(collection.get(0));这个编译器不会报错
ArrayList<Integer>>中的Integer称为实际类型参数或类型参数的实例
ArrayList称为原始类型
Collection<String> c = new Vector<String> ;这个可以通过编译
参数化类型不考虑类型参数的继承关系:
Vector<String> v = new Vector<Object>(); //错误 不写<Object>没错,写了就报错
Vector<Object> v = new Vector<String>(); //也错误
在创建数组实例时,数组的元素不能使用参数化的类型,例如:
Vector<Integer> vectorList[] = new Vector<Integer>[10]; //这个会报错
下面这个不报错很奇怪:
Vector v1 = new Vector<String>();
Vector<Object> v = v1;
如果把这两行代码放在一块就报错这很奇怪
泛型的通配符:
public static void pringCollecton(Collection<?> collection){ // collection.add("abc"); //这行报错,因为和类型有关,使用了通配符了以后不能进行和类型有关的方法 collection.size(); } }限定通配符的上边界:
Vector<? extends Number> x = new Vector<Integer>();
限定通配符的下边界:
Vector<? super Integer> x = new Vector<Number>();
限定通配符总是包括自己
泛型中关于map的迭代
import java.util.Collection; import java.util.HashMap; import java.util.Map; import java.util.Set; public class Test { public static void main(String[] args) { HashMap<String, Integer> map = new HashMap<String, Integer>(); map.put("aaa", 111); map.put("bbb", 222); Set<Map.Entry<String, Integer>> entrySet = map.entrySet(); for(Map.Entry<String, Integer> entry : entrySet){ System.out.println(entry.getKey() + ":" + entry.getValue());; } }
如何自己定义一个泛型?
private static <T> T add(T x,T y){
return x;
}
调用add(3,5);
如何定义一个对任意类型的数组里面的值的位置替换的方法?
private static <T> void swap(T [] a ,int i, int j){
T temp = a[i];
a[i] = a[j];
a[j] = temp;
}
}
swap(new String[] { "aa", "bb", "cc" }, 1, 2);
swap(new int[]{1,3,4}, 1, 2);///这行会报错 int基本数据类型不行
普通方法,构造方法和静态方法都可以使用泛型,编译器不允许创建类型变量的数组,即在创建数组实例时,数组
的元素不能使用参数化的类型
在定义泛型的类型是可以定义多个类型参数,在定义它们的时候用<k,v,m>用逗号分开
DAO: data access object--->crud
静态方法不能用泛型
可以以泛型的方法得到参数类型,没法得到泛型中的参数是什么,但是可以通过方法得到泛型中的参数
public static void applyVector(Vector<Date> v1){
}
通过反射获得方法中泛型的参数类型的代码:
Method appleMethod = GenericTest.class.getMethod("applyVector", Vector.class); Type[] types = appleMethod.getGenericParameterTypes(); ParameterizedType pType = (ParameterizedType) types[0]; System.out.println(pType); System.out.println(pType.getActualTypeArguments()[0]);
Java虚拟机也是Java类,因为其他事java类的类加载器本身也要被类加载器加载
显然必须有第一个类加载器,这个就是BootStrap
public class ClassLoaderTest { public static void main(String[] args) { System.out.println(ClassLoaderTest.class.getClassLoader().getClass() .getName());; //结果为sun.misc.Launcher$AppClassLoader System.out.println(System.class.getClassLoader());//这个就是BootStrap加载的 //结果为null } }
java虚拟机默认三个主要类加载器,每个类负责加载特定位置的类:
BootStrap(爷爷),ExClassLoader(父亲),AppClassLoader(儿子)
public class ClassLoaderTest { public static void main(String[] args) { System.out.println(ClassLoaderTest.class.getClassLoader().getClass() .getName());; //结果为sun.misc.Launcher$AppClassLoader System.out.println(System.class.getClassLoader());//这个就是BootStrap加载的 //结果为null ClassLoader loader = ClassLoaderTest.class.getClassLoader(); while(loader!=null){ System.out.println(loader.getClass().getName()); loader = loader.getParent(); } System.out.println(loader); }
运行结果为:
sun.misc.Launcher$AppClassLoader null sun.misc.Launcher$AppClassLoader sun.misc.Launcher$ExtClassLoader null
ExtClassLoader用来加载JRE/lib/ext/*.jar
AppClassLoader用来加载classpath指定的所有jar或目录的
写自己的类加载器的话都要继承ClassLoader
可以使用自己的类加载器加载自己的特定目录
模板方法设计模式:
父类---->loadClass/findClass/得到class文件的转换成字节码 为了保持loadClass的流程
子类1(自己干)
子类2(自己干)
程序中的代理:
要为已存在的多个具有相同接口的目标类的各个方法增加一些系统功能,
例如,异常处理、日志、计算方法的运行时间、事务管理等等。
代理类的每个方法调用目标类的方法,调用方法的同时加上一些功能
如果采用工厂模式和配置文件的方式进行管理,则不需要修改客户端程序,在配置文件中
配置是使用目标类还是代理类,这样以后很容易切换,譬如:想要日志功能时就配置代理
类否则配置目标类,这样,增加系统功能很容易,以后运行一段时间后,又想去掉系统功
能也很容易
AOP Aspect oriented program 面向切面的编程 系统中存在交叉业务,一个交叉业务就
是要切入到系统中的一个方面
AOP的目标就是要使交叉业务模块化,可以采用将切面代码移动到原始方法的周围,这也直接
在方法中棉鞋切面代码的运行效果是一样的
代理是实现AOP的一个很重要的技术点
要为系统中的各种接口的类增加dialing共鞥,那将需要太多的代理类,全部采用静态代理方式,将
是一件非常麻烦的事情,JVM可以往往用作代理类,在运行期动态生成类的字节码,这种动态生成的类即动态代理类
JVM生成的动态类必须具有一个或多个接口,所以,JVM生成的动态类只能用作具有相同接口的目标类的代理
CGLIB库可以动态生成一个类的子类,一个类的子类也可以用作该类的代理
所以,如果要为一个没有实现接口的类生成动态代理类,那么可以使用CGLIB库
分析JVM动态生成的类
打印一个类的所有的构造方法:
import java.lang.reflect.Constructor; import java.lang.reflect.Method; import java.lang.reflect.Proxy; import java.util.Collection; public class ProxyTest { public static void main(String[] args) { Class clazzProxy1 = Proxy.getProxyClass(Collection.class.getClassLoader(), Collection.class); System.out.println(clazzProxy1.getName()); System.out.println("--------------------begin constructors list"); 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("--------------------begin methods list"); 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()); } } }
打印结果为:
$Proxy0 --------------------begin constructors list $Proxy0(java.lang.reflect.InvocationHandler) --------------------begin methods list add(java.lang.Object) hashCode() clear() equals(java.lang.Object) toString() contains(java.lang.Object) isEmpty() addAll(java.util.Collection) iterator() size() toArray([Ljava.lang.Object;) toArray() remove(java.lang.Object) containsAll(java.util.Collection) removeAll(java.util.Collection) retainAll(java.util.Collection) isProxyClass(java.lang.Class) getProxyClass(java.lang.ClassLoader,[Ljava.lang.Class;) getInvocationHandler(java.lang.Object) newProxyInstance(java.lang.ClassLoader,[Ljava.lang.Class;,java.lang.reflect.InvocationHandler) wait() wait(long,int) wait(long) getClass() notify() notifyAll()
相关文章推荐
- 黑马程序员-java基础增强_常用类
- 黑马程序员--JAVA基础加强之可变参数与增强for循环
- 黑马程序员----java基础增强下
- 黑马程序员:基础加强(可变参数、增强for、枚举、javabBean、BeanUtils、注解、泛型)
- 黑马程序员 Java基础增强for循环 很重要
- 黑马程序员_Java基础增强_jdk1.5新特性(2) 反射(1)
- 黑马程序员————java基础--------JDK1.5新特性之泛型、自动拆装箱、增强for、静态导入、可变参数
- 黑马程序员——Java基础---集合(泛型及增强for)
- 黑马程序员----java基础增强上
- 黑马程序员--Java基础加强(2)-- JDK1.5新特性之可变参数,增强for,自动拆装箱,枚举
- 黑马程序员_毕向东JAVA基础_集合(3)Map&Collections&Arrays&增强for循环
- 黑马程序员_java基础增强
- 黑马程序员——Java基础---集合(Collection接口、List接口及其子类、增强for)
- 黑马程序员---JAVA基础增强
- 黑马程序员-Java基础之Set接口及HashSet类
- java基础39 增强for循环(也叫foreach循环)
- 黑马程序员1---Java基础final修饰符
- Java基础学习笔记16——(List的子类,泛型类,增强for循环,静态导入,可变参数)
- 黑马程序员_java编程基础第3天函数 数组
- 黑马程序员_毕向东_Java基础_DAY19_字节流、转换流、小知识点