呼叫靜態常量不會引起初始化(呼叫初始化程式碼塊)。但是要呼叫類的靜態方法當然會初始化類了
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物件。