2012-02-07 85 views
1

我有一個數據庫表,其中包含一個名爲type的列。對於數據庫列中的每一行,我必須根據類型創建一個對象。目前,我使用if else語句爲:根據類型創建不同的對象

if (type.equals("object1")){ 
    Object1 object1 = new Object1(); 
} 
else if (type.equals("object2")){ 
    Object2 object2 = new Object2(); 
} 

有些更好的辦法是使用一個枚舉,作爲類型的數量是有限的,但有沒有可能讓一個對象的創建依賴於價值的字符串?

我願意以另一種方式解決我的問題,而不是我試圖解決的問題。

回答

1

您可以使用

Object o = Class.forName(type).newInstance(); 

如果你有一個int和兩個字符串,因爲你需要的參數。

Object o = Class.forName(type) 
       .getConstructor(int.class, String.class, String.class) 
       .newInstance(intValue, string1, string2); 

另一種可能性是使用工廠方法

Object o = getClass().getMethod("create_" + type).invoke(null); 

static Object1 create_object1() { 
    return new Object1(/* with args */); 
} 

static Object2 create_object2() { 
    return new Object2(/* with other args */); 
} 

但最靈活的方法可能是使用一個開關

Object o; 
switch(type) { // in Java 7 
    case "object1": o = new Object1(); break; 
    case "object2": o = new Object2(); break; 

什麼是Java中8使用閉包更優雅。

http://cr.openjdk.java.net/~briangoetz/lambda/lambda-state-final.html

+1

我正在爲Android開發,因此switch語句不起作用 – 2012-02-07 10:22:23

+0

好點,關閉也一樣。第一個例子會工作。您可能需要在名稱的開頭添加一個包,並更改第一個字母的大小寫。 ;) – 2012-02-07 10:27:17

+0

我想對象o = Class.forName(type).newInstance();我認爲這將最適合我。然而,我堅持傳遞構造函數變量。我需要通過一個int和兩個字符串,這個問題解決這個問題,但我似乎無法弄清楚(或只是瞭解會發生什麼)http://stackoverflow.com/questions/234600/can-i-class-class -newinstance-with-constructor-arguments – 2012-02-07 10:48:13

3

您可以創建一個從StringClass的地圖並使用newInstance。然而,這依賴於無參數構造函數的存在。

import java.util.*; 

class Test { 
    public static void main(String[] args) throws Exception { 
     Map<String, Class<?>> classes = new HashMap<String, Class<?>>(); 
     classes.put("object1", Object1.class); 
     classes.put("object2", Object2.class); 

     String type = "object2"; 

     Object obj = classes.get(type).newInstance(); 

     //... 
    } 
} 

class Object1 { ... } 

class Object2 { ... } 
+0

或者所有具有相同參數的構造函數。例如'Object1(Object [] values)' – 2012-02-07 10:14:58

+0

啊,好點。 – aioobe 2012-02-07 10:17:08

+0

我確實想過使用Map,過去我也這樣做過。如果你有Java 7,交換機可能更優雅。 – 2012-02-07 10:18:20

0
package main; 

import java.util.ArrayList; 
import java.util.List; 

public class TempClass { 
    public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException { 
     List<Class> classes = new ArrayList<Class>() {{ 
      add(Class.forName("main.Object1")); 
      add(Class.forName("main.Object2")); 
     }}; 
     for (Class aClass : classes) { 
      Object o = aClass.newInstance(); 
     } 
    } 
} 


package main; 

public class Object1 { 
    public Object1() { 
     System.out.println("Object1"); 
    } 
} 


package main; 

public class Object2 { 
    public Object2() { 
     System.out.println("Object2"); 
    } 
} 
0

使用switchif聲明強制你硬編碼各種選項,所以你會得到一個不太靈活的解決方案,在我看來。

我總是比較喜歡編寫可擴展的代碼以用於未來的軟件開發。

所以我建議你使用Object o = Class.forName(type).newInstance();在你的數據庫中放入你要實例化的類的名字,如果你需要的話,還可以使用自定義標籤。

編輯

如果你有一些參數傳遞到你必須實例化類的構造函數,爲方便使用Constructor.newInstance()代替Class.newInstance();和使用Constructor對象實例化的類,例如:

Class myClass = Class.forName(type); 

// get the constructor you need specifying parameters type 
Constructor constructor = myClass.getConstructor(String.class); 

Object myObject = constructor.newInstance("constructor-arg"); 
0

如果有問題的類是繼承層次結構的一部分,你碰巧使用某種映射工具/像Hibernate或iBATIS的/ MyBatis的框架,它可能包括一個方法來配置這樣CAL帶領鑑賞家。

然後,您可以將您的「類型」列配置爲descriminator列,並將支持的值映射到您的類。當您從數據庫中檢索對象時,框架將爲您實例化適當的類。