2013-10-14 51 views
6

我創造了用戶偏好的店,並且有用戶可設置的值偏好的固定數量。首選項(設置)的名稱被存儲爲一個枚舉:關聯泛型類型與枚舉在Java中

public enum UserSettingName { 

    FOO, 
    BAR, 
    ETC 

} 

我想做什麼就能做的是存儲與名稱的值類型,這樣的服務將用戶的價值存儲與正確的Java類型。例如,FOO可能是Long,而BAR可能是String。直到現在,我們將所有值存儲爲String s,然後手動將值轉換爲適當的Java類型。這導致無處不在的try/catch塊,當在服務中只有一個try/catch時更有意義。據我所知,枚舉不能有泛型類型,所以我一直在玩弄:

public enum UserSettingName { 

    FOO(Long.class), 
    BAR(String.class), 
    ETC(Baz.class) 

    private Class type; 

    private UserSettingName(Class type) { 
     this.type = type; 
    } 

    public Class getType() { 
     return this.type; 
    } 
} 

我有了public T getSettingValue()public void setSettingValue(T value)方法應該返回,並設置正確類型值的通用UserSetting對象。我的問題來自於努力,當我創建指定泛型類型T或檢索設置,因爲我不能做這樣的事情:

new UserSetting<UserSettingName.FOO.getType()>(UserSettingName.FOO, 123L) 

很抱歉,如果這是不完全清楚,我可以嘗試澄清,如果它是不明白。

謝謝!

UPDATE

兩個設置名稱和值從Spring MVC的REST調用進來:

public ResponseEntity<String> save(@PathVariable Long userId, @PathVariable UserSettingName settingName, @RequestBody String settingValue) 

所以我用枚舉,因爲春節自動轉換傳入的數據。

+1

如何重要的是它爲你使用'enum'?如果你可以使用'static final'字段,那麼有一個相當簡單的答案。 – StriplingWarrior

+0

@StriplingWarrior並不重要,但它會減少代碼,因爲Spring MVC會自動轉換爲Enum。我將在我的問題中添加代碼 –

回答

2

看看它由網狀怎麼做:

http://grepcode.com/file/repo1.maven.org/maven2/io.netty/netty-all/4.0.0.Beta1/io/netty/channel/ChannelOption.java#ChannelOption

編輯:

public interface ChannelConfig { 
    ... 
    <T> boolean setOption(ChannelOption<T> option, T value); 
    ... 
} 

public class ChannelOption<T> ... 
    public static final ChannelOption<Integer> SO_TIMEOUT = 
     new ChannelOption<Integer>("SO_TIMEOUT"); 
    ... 
} 

EDIT2:

http://netty.io/wiki/new-and-noteworthy.html#type-safe-channeloption

他們利用類型的常量完成它,你可以將其轉換爲:

class Baz {} 

class UserSettingName<T> { 
    public static final UserSettingName<Baz> ETC = new UserSettingName<Baz>(); 
} 

class UserSetting { 
    public <T> UserSetting(UserSettingName<T> name, T param) { 

    } 
} 

public class Test { 
    public static void main(String[] args) { 
     new UserSetting(UserSettingName.ETC, new Baz()); 
    } 
} 
+1

我看不到您的鏈接如何回答問題。你能解釋一下嗎? – tom

+1

@tom:如果可以使用靜態最終字段而不是枚舉,那麼每個值都可以有一個與它關聯的泛型聲明類型,遵循您在他提供的鏈接的「ChannelOption」類中看到的模式。 – StriplingWarrior

+0

你能爲這個答案添加一個相關的代碼示例嗎?因爲它幾乎只有幾個鏈接 – Krease

3

首先,你必須退後一步,思考你想達到的目標,並使用標準模式或語言結構來實現它。

這不是完全清楚你要去這裏經過的話,但您的方法幾乎可以肯定看起來像你重塑的東西可能在Java中的一個更直接的方式來完成。例如,如果您確實需要了解並使用對象的運行時類,請考慮使用反射API。

在一個更實際的層面 - 你想在這裏做什麼是不可能的仿製藥。泛型是一種編譯時語言功能 - 它們有助於避免從Object中明確地轉換所有內容,並在編譯時給予類型檢查。您無法以這種方式使用泛型,即將T設置爲僅在運行時才知道的值UserSettingName.Foo.getType()

+5

我完全同意這一點,並進一步補充說,通常不應該像使用OP那樣使用枚舉。基本上,枚舉是一組用戶定義的抽象(不是編碼意義上的)類型,應該用來區分不同的場景。例如,如果你要編程你的生活,你可以使用一個枚舉,其中包含星期'MONDAY'到'SUNDAY',然後可以用來判斷你是否可以隨意休息。一個更好的例子是使用枚舉爲簡單的自制(UDP)消息解析器指定消息類型。 – Izmaki

0

枚舉不是這裏的答案。如果你發現自己在任何地方重複代碼,你可以創建一個實用程序類並在那裏封裝所有的try/catch邏輯。這會減少代碼冗餘,但不會對當前代碼產生重大影響。

public class Util 
{ 
    public static MyObject getObjectFromString(String s) 
    { 
     try 
     { 
      return (MyObject)s; 
     } 
     catch(Exception e) 
     { 
      return null; 
     } 
    } 
} 

然後使用方法如下:

MyObject myObj = Util.getObjectFromString(string);