2016年12月17日 星期六

方法、介面、父類 (反射三)

※取得全部方法

package inheritate;
    
public interface GrandFather {
    void gf1();
    
    static String gf2(String p) {
        return "";
    }
    
    default String gf3(Integer p) {
        return "";
    }
}
------------------------------
package inheritate;
    
public abstract class Father implements GrandFather {
    public abstract void f1();
    
    public static String f2(String p) {
        return "";
    }
    
    public String f3(Integer p) {
        return "";
    }
}
------------------------------
package inheritate;
    
public class Son extends Father {
    @Override
    public void gf1() {
        System.out.println("");
    }
    
    static String s1(String p) {
        return "";
    }
    
    @Override
    public void f1() {}
}


※測試

try {
    Class<?> clazz = Class.forName("inheritate.Son");
    
    System.out.println("Methods:");
    for (Method m : clazz.getMethods()) {
        System.out.println(m);
    }
    
    System.out.println(System.getProperty("line.separator") + "DeclaredMethods:");
    for (Method m : clazz.getDeclaredMethods()) {
        System.out.println(m);
    }
} catch (ClassNotFoundException e) {
    e.printStackTrace();
}

※getDeclaredMethods,只會叫出Class.forName裡面定義的方法,不管修飾子是什麼

※getMethods只會叫出修飾子是public的方法
但要注意屬性的繼承是有作用的,抽象方法並不會印出來
介面不寫修飾子,預設是public abstract,所以一定是public,寫private還會編譯錯誤

※注意介面的static不會印出來(default可以),有可能是java8的bug,因為java8才可以寫static方法在裡面,又或者本來就是這樣的設計

※方法常用方法

package inheritate;
    
public class Son extends Father {
    private String a;
    private int b;
    
    public String getA() {
        return a;
    }
    
    public void setA(String a) {
        this.a = a;
    }
    
    public int getB() throws RuntimeException {
        return b;
    }
    
    public void setB(int b) {
        this.b = b;
    }
    
    @Override
    public void gf1() {
        System.out.println("");
    }
    
    static String s1(String p) {
        return "";
    }
    
    @Override
    public void f1() {}
}


※測試

try {
    Class<?> clazz = Class.forName("inheritate.Son");
    
    for (Method m : clazz.getDeclaredMethods()) {
        System.out.println("m:" + m);
        System.out.println("修飾子(數字):" + m.getModifiers());
        System.out.println("修飾子(中文):" + Modifier.toString(m.getModifiers()));
        System.out.println("包.方法名:" + m.getName());
        System.out.println("有幾個參數:" + m.getParameterCount());
        // System.out.println("有幾個參數:" + m.getParameterTypes().length);
        System.out.println("回傳型態:" + m.getReturnType());
        System.out.println("宣告的類別:" + m.getDeclaringClass());// Son
        System.out.println("方法的類別:" + m.getClass());// Method
    
        for(Class<?> exc:m.getExceptionTypes()){
            System.out.println("例外:" + exc);
        }
    
        for (Class<?> p : m.getParameterTypes()) {
            System.out.println("參數名稱:" + p.getCanonicalName());
        }
        System.out.println();
    }
} catch (ClassNotFoundException e) {
    e.printStackTrace();
}




※取得全部介面

public interface GrandFather {}
public interface Dad {}
public class Son implements Dad, GrandFather {}
--------------------
try {
    Class<?> clazz = Class.forName("inheritate.Son");
    
    System.out.println(clazz.getInterfaces().length);
    for (Class<?> cz : clazz.getInterfaces()) {
        System.out.println(cz.toGenericString());
        System.out.println(cz.toString());
        System.out.println(cz.getPackage());
        System.out.println(cz.getCanonicalName());
        System.out.println(cz.getName());
        System.out.println(cz.getSimpleName());
        System.out.println();
        cz.getFields();
        cz.getMethods();
    }
} catch (ClassNotFoundException e) {
    e.printStackTrace();
}

※如果Son有繼承父類是取不到的,只能取得介面,且是Son的直接介面
假設Son只有實作Dad,而Dad繼承GrandFather,只會取得Dad而已


※取得父類

public abstract class Father {}
public class Son extends Father {}
--------------------
try {
    Class<?> clazz = Class.forName("inheritate.Son");
    Class<?> cz = clazz.getSuperclass();
    System.out.println(cz.toGenericString());
    System.out.println(cz.toString());
    System.out.println(cz.getPackage());
    System.out.println(cz.getCanonicalName());
    System.out.println(cz.getName());
    System.out.println(cz.getSimpleName());
    System.out.println();
} catch (ClassNotFoundException e) {
    e.printStackTrace();
}

※如果Son有實作介面是取不到的,只能取得父類,且是Son的直接父類,沒有就是Object
假設Father還有繼承父類或實作類別都取不到

※getSuperclass並沒有length方法,因為父類只有一個,至少有Object,如繼承了,則Object就取不到了

沒有留言:

張貼留言