黑马程序员_java基础增强2

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

泛型也是 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()


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值