你需要注意的Java小細節(一)

happyfish發表於2015-10-12
  1. 呼叫靜態常量不會引起初始化(呼叫初始化程式碼塊)。但是要呼叫類的靜態方法當然會初始化類了

class Test{
    static{
                  System.out.println("初始化");
     }
        public  final static  String  str="ddd";
}
public class Main {
public static void main(String[] args) {
System.out.println(Test.str);
}
}

輸出ddd。

2.關於靜態代理與動態代理

public class ProxyTest {

    public static void main(String[] args){

            Class clazz = Proxy.getProxyClass(Person.class.getClassLoader(), Person.class);
           System.out.println(clazz);
           System.out.println(Person.class);
    }

}
public interface Person {
    public   void  sayHello();
}

輸出:

class com.sun.proxy.$Proxy0
interface main.Person

為什麼需要一個classloader,就是因為class是動態生成的。這個class就是代理物件。(也就是被擴充套件了的Person物件。Person是一個介面)
Java中的代理與OC中的委託基本類似。但是區別不同的是,JAVA中的代理物件包裹著被代理的物件(得到的是被擴充套件的Person物件)
。而OC中代理物件是作為被代理物件的一個屬性。(個人覺得,OC中的代理更能體現物件導向程式設計,尤其是對多型的理解。)

也就是說,java中的代理最終獲得的是代理物件(雖然是Person介面,但是不是我們自己處理邏輯的的那個實現物件),而在OC中獲得的是原物件。

Class proxyClass= Proxy.getProxyClass(Person.class.getClassLoader(), Person.class);
         InvocationHandler handler = new MyInvocationHandler();
         Person f = (Person) proxyClass.getConstructor(InvocationHandler.class).newInstance(handler);
         System.out.println(f);

proxyClass的getConstructor得到的是代理類的構造器物件,而不是person的構造器物件。

使用代理可以根據介面動態的生成物件,所謂的動態代理就是根據介面動態生成代理物件而已。

public class ProxyTest {

    public static void main(String[] args) throws InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchMethodException, SecurityException{

            Class proxyClass= Proxy.getProxyClass(Person.class.getClassLoader(), Person.class);
         InvocationHandler handler = new MyInvocationHandler();
       Person  person= (Person) proxyClass.getConstructor(InvocationHandler.class).newInstance(handler);
      person.sayHello();  
    }
}
public class MyInvocationHandler  implements  InvocationHandler {
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
      System.out.println("我被呼叫了!");
        return null;
    }
}

呼叫這個動態生成物件(擴充套件了的Person物件)的任何方法都將呼叫invoke方法。
動態代理:

    public static void main(String[] args) throws InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchMethodException, SecurityException{
             Class proxyClass= Proxy.getProxyClass(Person.class.getClassLoader(), Person.class);
             MyInvocationHandler handler = new MyInvocationHandler();
             //person是一個介面。我們自己的處理邏輯還需要實現:
             handler.setTarget(new PersonImpl());
//person是加入了InvocationHandler的person:
             Person  person= (Person )proxyClass.getConstructor(InvocationHandler.class).newInstance(handler);
             person.sayHello("Jetty"); 
    }
public class MyInvocationHandler implements InvocationHandler {
    private Person person;
    public void setTarget(Person target) {
        this.person = target;
    }
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        new Before().before();
         method.invoke(person, args[0]);//自己的邏輯呼叫。成員變數person
        return null;
    }
}
public class Before {
    public    void    before(){
        System.out.println("before");
    }
}

可以看出,java中的動態代理體現了java中最重要的一點:面向介面程式設計。這樣生成的代理類也是一個Person物件。

相關文章