2016年12月14日 星期三

建構子、屬性 (反射二)

※取得全部建構子

package inheritate;
    
public abstract class Father implements GrandFather {
    Father(){}
    Father(String s){}
}
------------------------------
package inheritate;
    
public class Son extends Father {
    Son() {}
    
    public Son(String s) {}
    
    Son(int i, String s) {}
}

※GrandFather是介面,因介面是沒有建構子的,所以不貼出來

※測試

try {
    Class<?> clazz = Class.forName("inheritate.Son");
    
    System.out.println("Constructors:");
    for (Constructor<?> c : clazz.getConstructors()) {
        System.out.println(c);
    }
    
    System.out.println(System.getProperty("line.separator") + "DeclaredConstructors:");
    for (Constructor<?> c : clazz.getDeclaredConstructors()) {
        System.out.println(c);
    }
} catch (ClassNotFoundException e) {
    e.printStackTrace();
}

※getDeclaredConstructors,會叫出Class.forName裡面定義的建構子,不管修飾子是什麼

※getConstructors只會叫出修飾子是public的建構子
但要注意繼承的父類並不會出現,也就是Father抽象類別(沒抽象也是一樣)沒有作用



※建構子常用方法

package inheritate;
    
public class Son extends Father {
    private int i;
    private String s;
    
    // setter/getter...
    
    Son() {}
    
    private Son(String s) {}
    
    protected Son(int i, String s) {
        this.i = i;
        this.s = s;
    }
    
    public Son(String s, int i) {
        this.s = s;
        this.i = i;
    }
}
--------------------
package inheritate;
    
public class Father {
    public Father() {}
    
    Father(String s) {}
}


※測試

try {
    Class<?> clazz = Class.forName("inheritate.Son");
    
    System.out.println("幾個建構子:" + clazz.getDeclaredConstructors().length);
    System.out.println();
    for (Constructor<?> c : clazz.getDeclaredConstructors()) {
        System.out.println("c:" + c);
        System.out.println("修飾子(數字):" + c.getModifiers());
        System.out.println("修飾子(中文):" + Modifier.toString(c.getModifiers()));
        System.out.println("包.類名:" + c.getName());
        System.out.println("有幾個參數:" + c.getParameterCount());
        // System.out.println("有幾個參數:" + c.getParameterTypes().length);
    
        for (Class<?> p : c.getParameterTypes()) {
            System.out.println("參數名稱:" + p.getCanonicalName());
        }
        System.out.println();
    }
    
    // 塞值
    Constructor<?> c1 = clazz.getDeclaredConstructors()[0];
    try {
        Son s1 = (Son) c1.newInstance("xxx", 1);
        System.out.println(s1.getI());
        System.out.println(s1.getS());
    } catch (InstantiationException | IllegalAccessException | IllegalArgumentException
            | InvocationTargetException e) {
        e.printStackTrace();
    }
    
    // 有可能出現「Class reflection.Test can not access a member of class inheritate.Son with modifiers "protected"」,看測試類有沒有在同個package或者是否是Son的子類而定
    Constructor<?> c2 = clazz.getDeclaredConstructors()[1];
    try {
        Son s2 = (Son) c2.newInstance(2, "ooo");
        System.out.println(s2.getI());
        System.out.println(s2.getS());
    } catch (InstantiationException | IllegalAccessException | IllegalArgumentException
            | InvocationTargetException e) {
        e.printStackTrace();
    }
} catch (ClassNotFoundException e) {
    e.printStackTrace();
}

※getName、getCanonicalName很像,以下是差別


※getName、getCanonicalName差別

package inheritate;
    
public class Son {
    public static class Grandson {}
}
--------------------
package inheritate;
    
public interface GrandFather {
    public static String gf2(String p) {
        return "";
    }
    
    default String gf3(Integer p) {
        return "";
    }
}


※測試

// 內部類別
Class<?> sg = Son.Grandson.class;
System.out.println(sg.getName());//inheritate.Son$Grandson
System.out.println(sg.getCanonicalName());//inheritate.Son.Grandson
System.out.println();
    
// 陣列
Integer[] iArray1 = {};
int[] iArray2 = {};
System.out.println(iArray1.getClass().getName());//[Ljava.lang.Integer;
System.out.println(iArray1.getClass().getCanonicalName());//java.lang.Integer[]
System.out.println();
System.out.println(iArray2.getClass().getName());//[I
System.out.println(iArray2.getClass().getCanonicalName());//int[]
System.out.println();
    
// 介面、類別
System.out.println(new GrandFather(){}.getClass().getName());//Test$1
System.out.println(new GrandFather(){}.getClass().getCanonicalName());//null

※總之getCanonicalName比較好閱讀


※取得全部屬性

package inheritate;
    
public interface GrandFather {
    String gf1 = "";
    String gf2 = "";
}
------------------------------
package inheritate;
    
public abstract class Father implements GrandFather {
    public String f1 = "";
    String gf2 = "";
    public static String sf = "";
}
------------------------------
package inheritate;
    
public class Son extends Father {
    public String son = "";
    static String sson = "";
}


※測試

try {
    Class<?> clazz = Class.forName("inheritate.Son");
    
    System.out.println("Fields:");
    for (Field f : clazz.getFields()) {
        System.out.println(f);
    }
    
    System.out.println(System.getProperty("line.separator") + "DeclaredFields:");
    for (Field f : clazz.getDeclaredFields()) {
        System.out.println(f);
    }
} catch (ClassNotFoundException e) {
    e.printStackTrace();
}

※getDeclaredFields,只會叫出Class.forName裡面定義的屬性,不管修飾子是什麼

※getFields只會叫出修飾子是public的屬性
但要注意屬性的繼承是有作用的,不管是class、interface,只要是public都會印出來
介面的屬性不寫修飾子,預設就是public static final,所以一定是public,寫private、protected會編譯錯誤


※屬性常用方法

package inheritate;
    
public class Son extends Father {
    public String son = "";
    public static String sson = "";
}
------------------------------
package inheritate;
    
public abstract class Father implements GrandFather {
    public String f1 = "";
    String gf2 = "";
    public static String sf = "";
}
------------------------------
package inheritate;
    
public interface GrandFather {
    String gf1 = "";
    String gf2 = "";
}


※測試

try {
    Class<?> clazz = Class.forName("inheritate.Son");
    
    System.out.println(System.getProperty("line.separator") + "DeclaredFields:");
    for (Field f : clazz.getDeclaredFields()) {
        int modifiers = f.getModifiers();
        System.out.println("修飾子(數字):" + modifiers);
        System.out.println("修飾子(中文):" + Modifier.toString(modifiers));
    
        Class<?> type = f.getType();
        System.out.println("type:" + type);
        System.out.println("屬性類型:" + type.getCanonicalName());
        System.out.println("屬性名稱:" + f.getName());
        System.out.println("宣告的類別:" + f.getDeclaringClass());// Son
        System.out.println("欄位的類別:" + f.getClass());// Field
    }
} catch (ClassNotFoundException e) {
    e.printStackTrace();
}

沒有留言:

張貼留言