泛型:
泛型是提供给javac编译器使用的,可以限定集合中的输入类型,让编译器挡住源程序中的非法输入,编译器编译带类型说明的集合时会去除掉类型信息,使程序运行效率不受影响,对于参数化的泛型类型,getClass()方法的返回值和原始类型完全一样,由于编译生成的字节码会去掉泛型的类型信息,只要能跳过编译器,就可以往某个泛型集合中加入其它类型的数据,例如用反射得到集合,再调用其add方法即可。
ArrayList<Integer> collection3=newArrayList<Integer>();
collection3.getClass().getMethod("add",Object.class).invoke(collection3,"abc");
System.out.println(collection3.get(0));
Vector v1=newVector<String>();//原始类型引用参数化类型
Vector<Object>=v1;//参数化类型引用原始类型
这样是对的,编译器会一行一行编译。
限定通配符上边界
Vector<?extends Number> x=new Vector<Integer>();//正确
Vector<?extends Number> x=new Vector<String>();//错误
限定通配符下边界:
Vector<? super Integer>x=new Vector<Number>();//正确
Vector<? super Integer>x=new Vector<Byte>();//错误
限定通配符总是包括自己
泛型集合类:
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());
}
java中的泛型类型(或者泛型)类似于C++中的模板,但是这种相似性仅限于表面,java语言中泛型基本上完全是在编译器中实现,用于编译器执行类型检查和类型推断,然后生成普通的非泛型的字节码,这种实现技术称为擦除(erasure)(编译器使用泛型类型信息保证类型安全,然后在生成字节码之前将其清除)。这是因为扩展虚拟机指令集来支持泛型被认为是无法接受的,这会为java厂商升级其JVM造成难以逾越的障碍,所以,java的泛型采用了可以完全在编译器中实现的擦除方法。
add(3,5);//自动装箱为Integer
Numbern1=add(3.5,5);//返回必须是共有类型
Objecto1=add(3,"abc");//必须是共有类型
swap(newString[]{"abc","xyz","it"},1,2);
//swap(newint[]{1,3,4,5},1,3);//只有引用类型才能作为泛型方法的实际参数
privatestatic <T> T add(T x,T y){
returnnull;
}
privatestatic <T> void swap(T[] a,int i,int j){
Ttemp=a[i];
a[i]=a[j];
a[j]=temp;
}
编写一个泛型方法,自动将Object类型的对象转换成其他类型。
private static<T> T autoConvert(Object obj){
return (T)obj;
}
定义一个方法,可以将任意类型的数组中的所有元素填充为相应类型的某个对象。
private static <T> void fillArray(T[]a,T obj){
for(inti=0;i<a.length;i++){
a[i]=obj;
}
}
采用自定泛型方法的方式打印出任意参数化类型的集合中所有内容。
public static <T> void printCollection(Collection<T> collection){
for(Object obj:collection){
System.out.println(obj);
}
}
定义一个方法,把任意参数类型的集合中的数据安全地复制到相应类型的数组中或数组复制到数组中。
copy1(new Vector<String>(),new String[10]);
copy2(new Date[10],new String[10]);//可以它们共有类型为Object
//copy1(new Vector<Date>(),new String[10]);//错误,不能进行类型推断
public static <T> void copy1(Collection<T> dest,T[] src){
}
public static <T> void copy2(T[] dest,T[]src){
}
泛型类:
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 update(T obj){
}
public T findByUserName(String name){
return null;
}
public Set<T>findByConditions(String where){
return null;
}
}
通过反射获得泛型的实际参数类型:
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){
}
类加载器:
Java虚拟机中可以安装多个类加载器,系统默认三个主要类加载器,每个类负责加载特定位置的类:BootStrap,ExtClassLoader,AppClassLader
类加载器也是Java类,因为其他是java类的类加载器本身也要被类加载器加载,显然必须有第一个类加载器不是java类,这正是BootStrap。
java虚拟机中的所有类加载器采用具有父子关系的树形结构进行组织,在实例化每个类加载器对象时,需要为其指定一个父级类加载器对象或者默认采用系统类加载器为其父级类加载。
类加载器的委托机制:
面试题:能不能自己写个类叫java.lang.System?通常不可以,类加载采用委托机制,委托给父级,保证父级优先,总是使用父级能找到的类,总是在rt.jar包里找到java系统自己的提供的System。
代理类:
AOP面向方面的编程(Aspectoriented program):
安全,事物,日志等功能要贯穿到好多个模块中,所以它们就是交叉业务。
动态代理:
要为系统中的各种接口的类增加代理功能,将需要太多的代理类,全部采用静态代理方式,将是一件非常麻烦的事。
JVM可以在运行期动态生成出类的字节码,这种动态生成的类往往被用作代理类,即动态代理类。
JVM生成的动态类必须实现一个或多个接口,所以JVM生成的动态类只能用作具有相同接口的目标类的代理。
CGLIB库可以动态生成一个类的子类,一个类的子类也可以用作该类的代理,所以如果要为一个没有实现接口的类生成动态代理类,那么可以使用CGLIB库。
小细节:单线程用StringBuilder,多线程用StringBuffer。
创建动态类并查看其方法列表信息:
package cn.itcast.day1;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.Collection;
public class ProxyTest {
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generatedmethod stub
Class clazzProxy1=Proxy.getProxyClass(Collection.class.getClassLoader(),Collection.class);
System.out.println(clazzProxy1.getName());
System.out.println("----beginconstructors 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("----beginMethods 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());
}
}
}
分析InvocationHandler对象的运行原理:
package cn.itcast.day1;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
public class ProxyTest {
/**
* @param args
* @throwsNoSuchMethodException
* @throws SecurityException
*/
public static void main(String[] args) throws Exception {
// TODO Auto-generatedmethod stub
Class clazzProxy1=Proxy.getProxyClass(Collection.class.getClassLoader(),Collection.class);
System.out.println(clazzProxy1.getName());
//获取动态类的构造方法
System.out.println("----beginconstructors 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("----beginMethods 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());
}
//创建动态类实例对象
System.out.println("----begincreate instance----");
//第一种方式
Constructor constructor=clazzProxy1.getConstructor(InvocationHandler.class);
classMyInvocationHander1 implements InvocationHandler{
@Override
public Object invoke(Object proxy, Method method, Object[]args)
throws Throwable {
return null;
}
}
Collectionproxy1=(Collection)constructor.newInstance(new MyInvocationHander1());
System.out.println(proxy1);
proxy1.clear();
//第二种方式
Collection proxy2=(Collection)constructor.newInstance(newInvocationHandler(){
@Override
public Object invoke(Object proxy, Method method, Object[]args)
throws Throwable {
// TODO Auto-generatedmethod stub
return null;
}
});
//第三种方式
Collectionproxy3=(Collection)Proxy.newProxyInstance(
Collection.class.getClassLoader(),
new Class[]{Collection.class},
new InvocationHandler() {
ArrayList target=new ArrayList();//add使用同一个
@Override
//每次add都用invoke方法
public Object invoke(Object proxy, Method method, Object[]args)
throws Throwable {
//ArrayListtarget=new ArrayList();//每次add创建新的一个
long beginTime =System.currentTimeMillis();
Object retVal=method.invoke(target, args);
long endTime=System.currentTimeMillis();
System.out.println(method.getName()+"--running time--"+(endTime-beginTime));
return retVal;
}
});
proxy3.add("zxx");
proxy3.add("lhm");
proxy3.add("bxd");
System.out.println(proxy3.size());
}
}
客户端调用一个方法,会调用代理类的有参InvocationHandler构造方法,然后调用参数handler的invoke方法,invoke方法再去使用目标的该方法。从而实现代理。
编写可生成代理和插入通告的通用方法:(以上代码改进版)
package cn.itcast.day1;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
public class ProxyTest {
/**
* @param args
* @throwsNoSuchMethodException
* @throwsSecurityException
*/
public static void main(String[] args) throws Exception {
// TODO Auto-generatedmethod stub
Class clazzProxy1=Proxy.getProxyClass(Collection.class.getClassLoader(),Collection.class);
System.out.println(clazzProxy1.getName());
//获取动态类的构造方法
System.out.println("----beginconstructors 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("----beginMethods 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());
}
//创建动态类实例对象
System.out.println("----begincreate instance----");
//第一种方式
Constructor constructor=clazzProxy1.getConstructor(InvocationHandler.class);
classMyInvocationHander1 implements InvocationHandler{
@Override
public Object invoke(Object proxy, Method method, Object[]args)
throws Throwable {
return null;
}
}
Collectionproxy1=(Collection)constructor.newInstance(new MyInvocationHander1());
System.out.println(proxy1);
proxy1.clear();
//第二种方式
Collection proxy2=(Collection)constructor.newInstance(newInvocationHandler(){
@Override
public Object invoke(Object proxy, Method method, Object[]args)
throws Throwable {
// TODO Auto-generatedmethod stub
return null;
}
});
//第三种方式
final ArrayListtarget=new ArrayList();
Collectionproxy3 = (Collection)getProxy(target,new MyAdvice());
proxy3.add("zxx");
proxy3.add("lhm");
proxy3.add("bxd");
System.out.println(proxy3.size());
}
private static Object getProxy(final Object target,final Advice advice){
Object proxy3=Proxy.newProxyInstance(
target.getClass().getClassLoader(),
//Collection.class.getClassLoader(),
//newClass[]{Collection.class},
target.getClass().getInterfaces(),
new InvocationHandler() {
@Override
//每次add都用invoke方法
public Object invoke(Object proxy, Method method, Object[]args)
throws Throwable {
//ArrayListtarget=new ArrayList();//每次add创建新的一个
/*long beginTime=System.currentTimeMillis();
Object retVal=method.invoke(target, args);
long endTime=System.currentTimeMillis();
System.out.println(method.getName()+"--runningtime--"+(endTime-beginTime));
return retVal;*/
advice.beforeMethod(method);
Object retVal=method.invoke(target, args);
advice.afterMethod(method);
return retVal;
}
});
return proxy3;
}
}
package cn.itcast.day1;
import java.lang.reflect.Method;
public interface Advice {
void beforeMethod(Method method);
void afterMethod(Method method);
}
package cn.itcast.day1;
import java.lang.reflect.Method;
public class MyAdvice implements Advice {
long beginTime=0;
@Override
public void beforeMethod(Method method) {
// TODO Auto-generatedmethod stub
System.out.println("开始学习");
beginTime =System.currentTimeMillis();
}
@Override
public void afterMethod(Method method) {
// TODO Auto-generatedmethod stub
System.out.println("学习完");
long endTime=System.currentTimeMillis();
System.out.println(method.getName()+"--running time--"+(endTime-beginTime));
}
}
实现类似spring的可配置的AOP框架:
package cn.itcast.day1.aopframework;
import java.io.InputStream;
public class AopFrameworkTest {
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generatedmethod stub
InputStream ips=AopFrameworkTest.class.getResourceAsStream("config.properties");
Object bean=new BeanFactory(ips).getBean("xxx");
System.out.println(bean.getClass().getName());
}
}
package cn.itcast.day1.aopframework;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import cn.itcast.day1.Advice;
public class ProxyFactoryBean {
private Advice advice;
public Advice getAdvice() {
return advice;
}
public void setAdvice(Advice advice) {
this.advice = advice;
}
public Object getTarget() {
return target;
}
public void setTarget(Object target) {
this.target = target;
}
private Object target;
public Object getProxy(){
Object proxy3=Proxy.newProxyInstance(
target.getClass().getClassLoader(),
//Collection.class.getClassLoader(),
//newClass[]{Collection.class},
target.getClass().getInterfaces(),
new InvocationHandler() {
@Override
//每次add都用invoke方法
public Object invoke(Object proxy, Method method, Object[]args)
throws Throwable {
//ArrayListtarget=new ArrayList();//每次add创建新的一个
/*long beginTime=System.currentTimeMillis();
Object retVal=method.invoke(target, args);
long endTime=System.currentTimeMillis();
System.out.println(method.getName()+"--runningtime--"+(endTime-beginTime));
return retVal;*/
advice.beforeMethod(method);
Object retVal=method.invoke(target, args);
advice.afterMethod(method);
return retVal;
}
});
return proxy3;
}
}
package cn.itcast.day1.aopframework;
import java.io.InputStream;
import java.util.Properties;
import cn.itcast.day1.Advice;
public class BeanFactory {
Properties props=new Properties();
public BeanFactory(InputStream ips){
try {
props.load(ips);
} catch (Exception e) {
// TODO: handleexception
e.printStackTrace();
}
}
public ObjectgetBean(String name){
String className=props.getProperty(name);
Objectbean=null;
Class clazz;
try {
clazz = Class.forName(className);
bean=clazz.newInstance();
} catch (Exception e) {
// TODO Auto-generatedcatch block
e.printStackTrace();
}
if(bean instanceof ProxyFactoryBean){
Objectproxy=null;
ProxyFactoryBean proxyFactoryBean=(ProxyFactoryBean)bean;
try {
Advice advice=(Advice)Class.forName(props.getProperty(name+".advice")).newInstance();
Objecttarget=Class.forName(props.getProperty(name+".advice")).newInstance();
proxyFactoryBean.setAdvice(advice);
proxyFactoryBean.setTarget(target);
proxy=proxyFactoryBean.getProxy();
} catch (Exception e) {
// TODO Auto-generatedcatch block
e.printStackTrace();
}
return proxy;
}
return bean;
}
}
config.properties:
xxx=java.util.ArrayList
#xxx=cn.itcast.day1.aopframework.ProxyFactoryBean
xxx.advice=cn.itcast.day1.MyAdvice
xxx.target=java.util.ArrayList
总结:代理这部分内容是重点,但是真得比较难,真得需要多看几遍多练。。。