2

来源:互联网 发布:淘宝红线绿线流量图 编辑:程序博客网 时间:2024/05/02 07:28
//这个是代理类public class TimeForTank implements Moveable { public TimeForTank(Moveable m){       super();this.m = m;}private Moveable m ;@Overridepublic void move() {System.out.println("The tank start!");long startTime = System.currentTimeMillis();m.move();System.out.println("The tank stop!");long endTime = System.currentTimeMillis();System.out.println("Times : "+ (endTime - startTime));}}
//客户端Moveable a = new Tank();TimeForTank target = new TimeForTank(a);target.move();
public class Proxy{    public static Object newProxyInstance(Class infce){        1、反射 传入的接口infce接口的方法        2、定义一个字符串,该字符串包含了代理类的所有内容。        3、将字符串写入.java文件中        4、.java-->.class-->内存        5、通过反射获取内存中代理类的构造方法并向其传参数        6、Proxy返回的是 实现传入的接口的代理类对象,这样就可以调用自己的move()方法                String str ="";        //编译//1、获取编译器对象JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();//2、创建FileManager 用来管理动态生成的文件,该文件包含了一个代理类的全部内容。StandardJavaFileManager fileMgr = compiler.getStandardFileManager(null, null, null);Iterable units = fileMgr.getJavaFileObjects(fileName);//3、根据FileManager和要编译的内容units生成CompilationTaskCompilationTask compilationTask = compiler.getTask(null, fileMgr, null, null, null, units);//4、执行编译compilationTask.call();//5、关闭fileMgr.close();URL[] urls = new URL[]{new URL("file:/" + System.getProperty("user.dir") + "/src")};URLClassLoader url = new URLClassLoader(urls);Class c = url.loadClass("ProxyEdition2.TankTimeProxy");-----到这里,TankTimeProxy代理类已经加载到内存了,//getConstructor(Class<?>...parameterType)//获取的是 TankTimeProxy 代理类的构造方法//TankTimeProxy 是调用者 不要理解错了(Moveable.class)是参数来的,而不是调用Moveable的构造函数。。。Constructor constructor = c.getConstructor(Moveable.class);//给代理类传入参数Object obj = constructor.newInstance(new Tank());return obj;
public class  TankTimeProxy implements Moveable {public TankTimeProxy(Moveable m) {  //这里传入的就一个被代理的对象 new Tank()super();this.m = m;}private Moveable m ;@Override public void move() {System.out.println("The tank start!");long startTime = System.currentTimeMillis();m.move();System.out.println("The tank stop!");long endTime = System.currentTimeMillis();System.out.println("Times : " + (endTime - startTime));}}
//其实步骤差不多,但是解耦了处理方式,多了InvocationHandlerpublic interface InvocationHandler {void invoke(Object obj,Method m); // 调用的对象,该对象的方法}class TimeHandler implements InvocationHandler {private Object target;public TimeHandler(Object target) {super();this.target = target;}@Override//这个Obj传入的是代理类的对象,public void invoke(Object obj, Method m) {long startTime = System.currentTimeMillis();System.out.println("Working");try {//invoke(Object,args) 对带有指定参数的指定对象调用由此Method对象表示的底层方法。//obj:从中调用底层方法的对象,args用于方法调用的参数,与自身的invoke()方法区分。m.invoke(target);} catch (IllegalAccessException | IllegalArgumentException| InvocationTargetException e) {e.printStackTrace();}System.out.println("Stop!");long endTime = System.currentTimeMillis();System.out.println("Time:" + (endTime - startTime));}}
public static Object newProxyInstance(Class<?> infce,InvocationHandler h) throws Exception{    //获取构造方法,对应的是代理类TankTimeProxyConstructor constructor = c.getConstructor(InvocationHandler.class);//产生一个对象System.out.println(constructor);Object obj = constructor.newInstance(h);return obj;}
public class TankTimeProxy implements ProxyEdition3.Moveable{private InvocationHandler h ;public TankTimeProxy(InvocationHandler h) {super();this.h = h;}@Override public void move(){try{Method method = ProxyEdition3.Moveable.class.getMethod("move");//这个this 是指本身TankTimeProxy        h.invoke(this,method); }catch(Exception e){e.printStackTrace();};}}
public class $Proxy1 implements ProxyEdition3.Factory{private InvocationHandler h ;public $Proxy1(InvocationHandler h) {super();this.h = h;}@Override public void sell(){try{Method method = ProxyEdition3.Factory.class.getMethod("sell");        h.invoke(this,method);  //这句代码很经典  调用的是}catch(Exception e){e.printStackTrace();};}@Override public void produce(){try{Method method = ProxyEdition3.Factory.class.getMethod("produce");h.invoke(this,method);}catch(Exception e){e.printStackTrace();};}}
public interface Factory {void produce();void sell();}
public class NikeFactory implements Factory {@Overridepublic void produce() {System.out.println("Make in Nike");}@Overridepublic void sell() {System.out.println("sell by Nike");}}
public class SellObjectHandler implements InvocationHandler {Object target ;Factory nike = new NikeFactory();public SellObjectHandler(Object target){this.target = target;}@Override//这里的这个obj其实就是代理类对象public void invoke(Object obj, Method m) {if(target instanceof Student){try {m.invoke(nike);//System.out.println(obj);  //ProxyEdition3.$Proxy1@13a5fe33} catch (IllegalAccessException | IllegalArgumentException| InvocationTargetException e) {e.printStackTrace();}}else{System.out.println("No Sell");}}}
//这个是代理类public class TimeForTank implements Moveable {       public TimeForTank(Moveable m){       super();        this.m = m;    }    private Moveable m ;        @Override    public void move() {        System.out.println("The tank start!");        long startTime = System.currentTimeMillis();        m.move();        System.out.println("The tank stop!");        long endTime = System.currentTimeMillis();        System.out.println("Times : "+ (endTime - startTime));    }}//客户端Moveable a = new Tank();TimeForTank target = new TimeForTank(a);target.move();public class Proxy{    public static Object newProxyInstance(Class infce){        1、反射 传入的接口infce接口的方法        2、定义一个字符串,该字符串包含了代理类的所有内容。        3、将字符串写入.java文件中        4、.java-->.class-->内存        5、通过反射获取内存中代理类的构造方法并向其传参数        6、Proxy返回的是 实现传入的接口的代理类对象,这样就可以调用自己的move()方法                String str ="";        //编译        //1、获取编译器对象        JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();        //2、创建FileManager 用来管理动态生成的文件,该文件包含了一个代理类的全部内容。        StandardJavaFileManager fileMgr = compiler.getStandardFileManager(null, null, null);        Iterable units = fileMgr.getJavaFileObjects(fileName);        //3、根据FileManager和要编译的内容units生成CompilationTask        CompilationTask compilationTask = compiler.getTask(null, fileMgr, null, null, null, units);        //4、执行编译        compilationTask.call();        //5、关闭        fileMgr.close();                URL[] urls = new URL[]{new URL("file:/" + System.getProperty("user.dir") + "/src")};        URLClassLoader url = new URLClassLoader(urls);        Class c = url.loadClass("ProxyEdition2.TankTimeProxy");        -----到这里,TankTimeProxy代理类已经加载到内存了,        //getConstructor(Class<?>...parameterType)//获取的是 TankTimeProxy 代理类的构造方法//TankTimeProxy 是调用者 不要理解错了(Moveable.class)是参数来的,而不是调用Moveable的构造函数。。。        Constructor constructor = c.getConstructor(Moveable.class);        //给代理类传入参数        Object obj = constructor.newInstance(new Tank());        return obj;public class  TankTimeProxy implements Moveable {    public TankTimeProxy(Moveable m) {  //这里传入的就一个被代理的对象 new Tank()        super();        this.m = m;    }    private Moveable m ;    @Override     public void move() {        System.out.println("The tank start!");        long startTime = System.currentTimeMillis();        m.move();        System.out.println("The tank stop!");        long endTime = System.currentTimeMillis();        System.out.println("Times : " + (endTime - startTime));    }}//其实步骤差不多,但是解耦了处理方式,多了InvocationHandlerpublic interface InvocationHandler {        void invoke(Object obj,Method m); // 调用的对象,该对象的方法}class TimeHandler implements InvocationHandler {    private Object target;    public TimeHandler(Object target) {        super();        this.target = target;    }            @Override    //这个Obj传入的是代理类的对象,    public void invoke(Object obj, Method m) {        long startTime = System.currentTimeMillis();        System.out.println("Working");        try {            //invoke(Object,args) 对带有指定参数的指定对象调用由此Method对象表示的底层方法。//obj:从中调用底层方法的对象,args用于方法调用的参数,与自身的invoke()方法区分。            m.invoke(target);        } catch (IllegalAccessException | IllegalArgumentException                | InvocationTargetException e) {            e.printStackTrace();        }        System.out.println("Stop!");        long endTime = System.currentTimeMillis();        System.out.println("Time:" + (endTime - startTime));    }}public static Object newProxyInstance(Class<?> infce,InvocationHandler h) throws Exception{    //获取构造方法,对应的是代理类TankTimeProxy        Constructor constructor = c.getConstructor(InvocationHandler.class);        //产生一个对象        System.out.println(constructor);        Object obj = constructor.newInstance(h);            return obj;}public class TankTimeProxy implements ProxyEdition3.Moveable{private InvocationHandler h ;    public TankTimeProxy(InvocationHandler h) {        super();        this.h = h;    }@Override public void move(){    try{        Method method = ProxyEdition3.Moveable.class.getMethod("move");        //这个this 是指本身TankTimeProxy        h.invoke(this,method);     }catch(Exception e){e.printStackTrace();};    }}public class $Proxy1 implements ProxyEdition3.Factory{private InvocationHandler h ;    public $Proxy1(InvocationHandler h) {        super();        this.h = h;    }@Override public void sell(){    try{        Method method = ProxyEdition3.Factory.class.getMethod("sell");                h.invoke(this,method);  //这句代码很经典  调用的是    }catch(Exception e){e.printStackTrace();};    }@Override public void produce(){    try{        Method method = ProxyEdition3.Factory.class.getMethod("produce");        h.invoke(this,method);    }catch(Exception e){e.printStackTrace();};    }}public interface Factory {    void produce();    void sell();}public class NikeFactory implements Factory {        @Override    public void produce() {        System.out.println("Make in Nike");    }    @Override    public void sell() {        System.out.println("sell by Nike");    }}public class SellObjectHandler implements InvocationHandler {    Object target ;    Factory nike = new NikeFactory();    public SellObjectHandler(Object target){        this.target = target;    }    @Override    //这里的这个obj其实就是代理类对象    public void invoke(Object obj, Method m) {        if(target instanceof Student){                        try {                m.invoke(nike);                //System.out.println(obj);  //ProxyEdition3.$Proxy1@13a5fe33            } catch (IllegalAccessException | IllegalArgumentException                    | InvocationTargetException e) {                e.printStackTrace();            }        }else{                        System.out.println("No Sell");        }    }}
Integer i = 100; //Autoboxing
int totalprim = i;
javap -c StringTest
public static Integer valueOf(int i) {
    //先判断i的大小, 如果 i < -128 或 >= 128 就创建一个Integer对象,否则执行 SMALL_VALUES[i + 128]    return  i >= 128 || i < -128 ? new Integer(i) : SMALL_VALUES[i + 128];}
//这是一个静态的Integer数组对象,也就是说最终valueOf返回的都是一个Integer对象
private static final Integer[] SMALL_VALUES = new Integer[256];
//IntegerCache.low = -128;
public static Integer valueOf(int i) {        if (i >= IntegerCache.low && i <= IntegerCache.high)            return IntegerCache.cache[i + (-IntegerCache.low)];        return new Integer(i);    }
/*相关问题:
1、i >= 128 || i <-128 =====> new Integer(i) 2、i <128 && i>= -128 =====> SMALL_VALUES[i + 128]
SMALL_VALUES 本来已经被创建好,也就是说
在 i >= 128 || i <-128 是会创建不同的对象,
在 i < 128 && i>= -128 会根据 i 的值返回已经创建好的指定的对象。
*/

Integer i1 = 100;Integer i2 = 100;Integer i3 = 200;Integer i4 = 200;System.out.println(i1==i2);  //trueSystem.out.println(i3==i4);  //false
/*1、i1 和 i2 会进行自动装箱,执行了 valueOf 函数,它们的值在 (-128,128] 这个范围内,它们会拿到 SMALL_VALUES 数组里面的同一个对象 SMALL_VALUES[228],它们引用到了同一个 Integer 对象,所以它们肯定是相等的。2、i3 和 i4 也会进行自动装箱,执行了 valueOf 函数,它们的值大于 128,所以会执行 new Integer(200),也就是说它们会分别创建两个不同的对象,所以它们肯定不等。*/

Double i1 = 100.0;Double i2 = 100.0;Double i3 = 200.0;Double i4 = 200.0;System.out.println(i1==i2); //falseSystem.out.println(i3==i4); //false
/*看看上面的执行结果,跟 Integer 不一样,这样也不必奇怪,因为它们的 valueOf 实现不一样,结果肯定不一样,那为什么它们不统一一下呢? 这个很好理解,因为对于 Integer,在 (-128,128] 之间只有固定的 256 个值,所以为了避免多次创建对象,我们事先就创建好一个大小为 256 的 Integer 数组 SMALL_VALUES,所以如果值在这个范围内,就可以直接返回我们事先创建好的对象就可以了。但是对于 Double 类型来说,我们就不能这样做,因为它在这个范围内个数是无限的。 总结一句就是:在某个范围内的整型数值的个数是有限的,而浮点数却不是。所以在 Double 里面的做法很直接,就是直接创建一个对象,所以每次创建的对象都不一样。*/

/*Integer 派别:Integer、Short、Byte、Character、Long 这几个类的 valueOf 方法的实现是类似的。 Double 派别:Double、Float 的 valueOf 方法的实现是类似的。每次都返回不同的对象。*/

        Boolean i1 = false;        Boolean i2 = false;        Boolean i3 = true;        Boolean i4 = true;        System.out.println(i1==i2);//true        System.out.println(i3==i4);//true

/*因为在已经提前创建好了两个对象*/
public static final Boolean TRUE = new Boolean(true);public static final Boolean FALSE = new Boolean(false);


//情况
Integer num1 = 400;  int num2 = 400;  System.out.println(num1 == num2); //true

//说明 num==num2进行了拆箱操作
Integer num1 = 100;  int num2 = 100;  System.out.println(num1.equals(num2));  //true

@Overridepublic boolean equals(Object o) {    return (o instanceof Integer) && (((Integer) o).value == value);}
//我们指定 equal 比较的是内容本身,并且我们也可以看到 equal 的参数是一个 Object 对象,我们传入的是一个 int 类型,所以首先会进行装箱,然后比较,之所以返回 true,是由于它比较的是对象里面的 value 值。

Integer num1 = 100;  int num2 = 100;  Long num3 = 200l;  System.out.println(num1 + num2);  //200System.out.println(num3 == (num1 + num2));  //trueSystem.out.println(num3.equals(num1 + num2));  //false

/*1、当一个基础数据类型与封装类进行 ==、+、-、*、/ 运算时,会将封装类进行拆箱,对基础数据类型进行运算。 2、对于 num3.equals(num1 + num2) 为 false 的原因很简单,我们还是根据代码实现来说明:*/
@Overridepublic boolean equals(Object o) {    return (o instanceof Long) && (((Long) o).value == value);}


/*它必须满足两个条件才为 true: 1、类型相同 2、内容相同 上面返回 false 的原因就是类型不同。*/
Integer num1 = 100;Ingeger num2 = 200;Long num3 = 300l;System.out.println(num3 == (num1 + num2)); //true
/*我们来对基础类型进行一个测试*/
int num1 = 100;int num2 = 200;long mum3 = 300;System.out.println(num3 == (num1 + num2)); //true

所以,当 “==” 运算符的两个操作数都是 包装器类型的引用,则是比较指向的是否是同一个对象,而如果其中有一个操作数是表达式(即包含算术运算)则比较的是数值(即会触发自动拆箱的过程)。/*通过上面的分析我们需要知道两点: 1、什么时候会引发装箱和拆箱 2、装箱操作会创建对象,频繁的装箱操作会消耗许多内存,影响性能,所以可以避免装箱的时候应该尽量避免。*/







原创粉丝点击