2017-01-09 187 views
0

假設我有幾類:從泛型類型獲取枚舉類?

Class ExceptionA{ 
    public ExceptionA(ExceptionA.ErrorCode errorCode){} 
    setters... 
    getters... 
    public static enum ErrorCode{ 
     EC_ABC,EC_XYZ,EC_123 
} 

Class ExceptionB{ 
    public ExceptionB(ExceptionB.ErrorCode errorCode){} 
    setters... 
    getters... 
    public static enum ErrorCode{ 
     EC_DEF,EC_LOL,EC_456 
} 

在一個循環的地方,用含ExceptionA,ExceptionB,ExceptionC對象的數組工作:我想使用它的構造而沒有明確說明ExceptionX.ErrorCode一般構造異常對象。

Class<? extends Exception> expectedException = exception.getClass().getConstructor(Enum.class).newInstance(someErrorCodeEnum); 

該問題發生在getConstructor()。構造函數對每個Exception類都存在,但它們採用SpecificException.ErrorCode類型。不只是一個通用的Enum.class。有沒有辦法像這樣工作?:

ExceptionA exceptionAobject = new ExceptionA(EC_ABC); 
exceptionAobject.getEnumClassFromString("ErrorCode"); // Should be of type ExceptionA.ErrorCode 
+0

可能有一些bean introspection API可能工作。否則,您需要使用'getConstructors()'獲取構造函數,循環遍歷它們以找到參數類型是Enum的子類型的構造函數,然後使用該構造函數。 –

+0

是否使用不同的錯誤代碼在你的異常類之間引入* only *區別,或者也可能存在其他差異? –

+0

我還沒有注意到,但是可能有其他的區別。我只想說明這些可能性。 –

回答

1

這取決於具體情況。如果您確定只會有一個構造函數,您可以直接調用,例如ExceptionA.class.getConstructors()[0]獲得唯一的構造函數。您甚至可以在構造函數對象上調用getParameterTypes()[0]以獲取實際的ErrorCode類型。

否則,如果你知道應該有一個名爲ErrorCode內部類,你必須使用內部類的Binary name,即

Class<? extends Exception> exceptionType = exception.getClass(); 
Class<?> errorCodeType = exceptionType.getClassLoader() 
         .loadClass(exceptionType.getName()+"$ErrorCode"); 
assert errorCodeType.getDeclaringClass() == exceptionType; 

然後,您可以查找使用

Constructor<? extends Exception> con = exceptionType.getConstructor(errorCodeType); 
構造

但也許你在想太複雜。如果你已經擁有你想要傳遞給構造你的someErrorCodeEnum對象,你可以簡單地使用這個對象來確定參數類型:

Constructor<? extends Exception> con = exception.getClass() 
    .getConstructor(((Enum<?>)someErrorCodeEnum).getDeclaringClass()); 

注意事項使用Enum.getDeclaringClass()的重要性,而不是Object.getClass()在這裏,作爲一個特定的enum常數可以是延伸正式enum類型的匿名內部類。 getDeclaringClass()將返回正確的類型。

+0

謝謝!我快到了。 '構造函數ctor = exception.getClass()。getConstructor(((Enum )errorCode).getDeclaringClass()); WhatClassType expectedException = ctor.newInstance(errorCode);' 此構造函數可能返回的類型可能是ExceptionA或ExceptionB等。我如何一般地指定返回類型? –

+0

這不是您的異常類的常見超類進入的地方嗎?正如我在底部所提到的(否則不重要)回答。 –

+0

那麼,如果沒有其他常見的基類比'Exception',使用'Constructor <?擴展Exception>'就像我的答案中所示的那樣,只要它不是一個類型參數,就足以將'newInstance'的結果賦值給'Exception'類型的變量或與'exception'變量相同的類型。如果'exception'的類型是一個類型參數,那麼沒有類型安全的方式來表示反射操作的結果將是相同的類型。它將代替類型變量的擦除。這是Java泛型的一個已知限制。 – Holger

0

我不太清楚我是否有你的要求。我想這應該是沒有反射可行的,所以這裏是我的想法:

public class ExceptionA extends Exception { 

    public ExceptionA(ExceptionA.ErrorCode errorCode) { 
    } 

    public static enum ErrorCode implements ExceptionErrorCode { 
     EC_ABC, EC_XYZ, EC_123; 

     @Override 
     public Exception toException() { 
      return new ExceptionA(this); 
     } 
    } 
} 

我使用這個小接口:

public interface ExceptionErrorCode { 
    Exception toException(); 
} 

這將使類似:

ExceptionErrorCode someErrorCodeEnum = ExceptionA.ErrorCode.EC_XYZ; 
    Exception expectedException = someErrorCodeEnum.toException(); 

這會滿足您的要求嗎?

我想你可能要爲大家介紹的通用超爲您的異常類模型的緣故,所以你不必申報toException()expectedException只是Exception - 這是一個模糊的類型對我的口味。即使您沒有立即看到需求,超類型可能會派上用場。

+0

雖然有幾個異常類。 MyRuntimeException,MyCheckedException等等,這些都擴展了基類的Exception類。 –

+0

我預計。是的,你將不得不在每個類的枚舉中複製'toException()'的重寫。 –