1. 程式人生 > >java反射獲取聚合<List>屬性欄位

java反射獲取聚合<List>屬性欄位

java反射獲取聚合<List>屬性欄位

2016年09月30日 11:59:40 閱讀數:7997 標籤: javareflect 更多

個人分類: java

需要動態的傳入一個Class的型別,然後反射到啟動的List,根據List裡定義的泛型,知道其中List的具體物件的各種屬性。 

程式碼

 
  1. import java.lang.reflect.Field;

  2. import java.lang.reflect.ParameterizedType;

  3. import java.lang.reflect.Type;

  4. import java.util.ArrayList;

  5. import java.util.HashMap;

  6. import java.util.HashSet;

  7. import java.util.List;

  8. import java.util.Map;

  9. import java.util.Set;

  10.  
  11. import com.meyacom.ruleapp.dto.Ztree;

  12.  
  13. public class test {

  14.  
  15. public static void main(String[] args) throws ClassNotFoundException {

  16. Class<?> apply = Class.forName("com.chac.ruleapp.bom.ApplyTest");

  17. Field[] fields = apply.getFields();

  18. //獲取所有屬性

  19. List> allFieldList = getBomFields1(new ArrayList(), fields);

  20. for (List list : allFieldList) {

  21. System.out.println(list.toString());

  22. }

  23. }

  24.  
  25. protected static List> getBomFields(List chain, Field[] fields) {

  26. List> result = new ArrayList>();

  27. for (Field field : fields) {

  28. Class<?> fieldClass = field.getType();

  29. if (fieldClass.getName().startsWith("java")

  30. || fieldClass.getName().startsWith("javax")

  31. || fieldClass.getName().startsWith("com.sun")

  32. || fieldClass.getName().startsWith("boolean")

  33. || fieldClass.getName().startsWith("double")

  34. || fieldClass.getName().startsWith("int")) {

  35. List endChain = new ArrayList(chain);

  36. endChain.add(field);

  37. result.add(endChain);

  38. continue;

  39. } else {

  40. List thisChain = new ArrayList(chain);

  41. thisChain.add(field);

  42. result.addAll(getBomFields(new java.util.ArrayList(

  43. thisChain), fieldClass.getDeclaredFields()));

  44. }

  45. }

  46. return result;

  47. }

  48. public static List> getBomFields1(List chain,

  49. Field[] fields) {

  50. List> result = new ArrayList>();

  51. for (Field field : fields) {

  52. Class<?> fieldClass = field.getType();

  53. if (fieldClass.isPrimitive()

  54. || fieldClass.getName().startsWith("java.lang")

  55. || fieldClass.getName().startsWith("java.util.Date")

  56. || fieldClass.getName().startsWith("javax")

  57. || fieldClass.getName().startsWith("com.sun")

  58. || fieldClass.getName().startsWith("sun")

  59. || fieldClass.getName().startsWith("boolean")

  60. || fieldClass.getName().startsWith("double")

  61. || fieldClass.getName().startsWith("int")) {

  62. List endChain = new ArrayList(chain);

  63. endChain.add(field);

  64. result.add(endChain);

  65. continue;

  66. } else {

  67. if (fieldClass.isAssignableFrom(List.class)) // 【2】

  68. {

  69. Type fc = field.getGenericType(); // 關鍵的地方,如果是List型別,得到其Generic的型別

  70. if (fc instanceof ParameterizedType) // 【3】如果是泛型引數的型別

  71. {

  72. ParameterizedType pt = (ParameterizedType) fc;

  73. Class genericClazz = (Class) pt.getActualTypeArguments()[0]; // 【4】

  74. if ( genericClazz.getName().startsWith("java.lang") //設定list的終止型別

  75. || genericClazz.getName().startsWith("java.util.Date")

  76. || genericClazz.getName().startsWith("javax")

  77. || genericClazz.getName().startsWith("com.sun")

  78. || genericClazz.getName().startsWith("sun")

  79. || genericClazz.getName().startsWith("boolean")

  80. || genericClazz.getName().startsWith("double")

  81. || genericClazz.getName().startsWith("int")) {

  82. continue;

  83. }

  84. //System.out.println(genericClazz);

  85. // 得到泛型裡的class型別物件。

  86. List thisChain = new ArrayList(chain);

  87. // System.out.println(chain);

  88. thisChain.add(field); //!!

  89. result.addAll(getBomFields1(new ArrayList(thisChain), genericClazz.getDeclaredFields()));

  90. }

  91. } else {

  92. List thisChain = new ArrayList(chain);

  93. thisChain.add(field);

  94. result.addAll(getBomFields1(new ArrayList(thisChain),

  95. fieldClass.getDeclaredFields()));

  96. }

  97.  
  98. }

  99. }

  100. return result;

  101. }

其中針對List型別的單獨判斷參考一下別人的程式碼片段如下 

  1.  Field[] fs = clazz.getDeclaredFields(); // 得到所有的fields  
  2.   
  3. for(Field f : fs)   
  4. {   
  5.     Class fieldClazz = f.getType(); // 得到field的class及型別全路徑  
  6.   
  7.     if(fieldClazz.isPrimitive())  continue;  //【1】 //判斷是否為基本型別  
  8.   
  9.     if(fieldClazz.getName().startsWith("java.lang")) continue; //getName()返回field的型別全路徑;  
  10.   
  11.     if(fieldClazz.isAssignableFrom(List.class)) //【2】  
  12.     {   
  13.              Type fc = f.getGenericType(); // 關鍵的地方,如果是List型別,得到其Generic的型別  
  14.   
  15.              if(fc == null) continue;  
  16.   
  17.              if(fc instanceof ParameterizedType) // 【3】如果是泛型引數的型別   
  18.             {   
  19.                    ParameterizedType pt = (ParameterizedType) fc;  
  20.   
  21.                    Class genericClazz = (Class)pt.getActualTypeArguments()[0]; //【4】 得到泛型裡的class型別物件。  
  22.   
  23.                    m.put(f.getName(), genericClazz);  
  24.   
  25.                    Map<String, Class> m1 = prepareMap(genericClazz);  
  26.   
  27.                    m.putAll(m1);   
  28.              }   
  29.       }   
  30. }  




【解釋】: 
1、isPrimitive 

public boolean isPrimitive()判定指定的 Class 物件是否表示一個基本型別。 
有九種預定義的 Class 物件,表示八個基本型別和 void。這些類物件由 Java 虛擬機器建立,與其表示的基本型別同名,即 boolean、byte、char、short、int、long、float 和 double。 【注:像Integer,Boolean等包裝類不是基本型別!】 

這些物件僅能通過下列宣告為 public static final 的變數訪問,也是使此方法返回 true 的僅有的幾個 Class 物件。  

返回: 當且僅當該類表示一個基本型別時,才返回 true 
從以下版本開始:JDK1.1 

 

 

參考http://lorry1113.iteye.com/blog/973903

http://www.360doc.com/content/11/1231/14/1954236_176297236.shtml