亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

從泛型返回異常

從泛型返回異常

Helenr 2021-08-04 16:16:08
我目前有多個類,即FacadeA... FacadeZ,其擴展FacadeBase. FacadeBase應該有(某種通用方法?),即checkFacade,它會拋出一個異常FacadeAException......FacadeZException它擴展了FacadeException.目前就我所知。我堅持使用通用部分(或任何可以解決我的問題的方法)。是的,我知道我不能像我的例子中寫的那樣實例化泛型。public abstract class FacadeBase {  public void checkFacade(final String facadeId) throws Facade<A...Z>Exception {    if (!isFacadeAvailable(facadeId)) {      throw new Facade<A...Z>Exception(facadeId);    }  }  ...}public class FacadeA extends FacadeBase {  public void doSomethingWithFacadeA(final String facadeId) throws FacadeAException {    checkFacade(facadeId));    ...  }}public class FacadeAException extends FacadeException {  private FacadeAException(final String message) {    super(message);  }}public abstract class FacadeException extends Exception {  private FacadeException(final String message) {    super(message);  }}
查看完整描述

3 回答

?
翻閱古今

TA貢獻1780條經驗 獲得超5個贊

您可以使用泛型,但這還不夠,因為您需要在運行時實例化特定類型。

從廣義上講,您有兩種方法:


反思方式

聲明方式

1)反射方式不簡單。Java 并沒有提供所有你需要做的事情。您可以啟發或使用庫作為 Spring 來做到這一點。

該org.springframework.core.GenericTypeResolver應特別是幫助你。

您可以使用以下static Class<?> resolveTypeArgument(Class<?> clazz, Class<?> genericIfc) 方法:


針對給定的目標類解析給定泛型接口的單個類型參數,該類假定實現泛型接口并可能為其類型變量聲明具體類型。


如 :


public abstract class FacadeBase<T extends FacadeException> {


    private final Class<T> genericClazz;

    public FacadeBase () {

        this.genericClazz = (Class<T>) GenericTypeResolver.resolveTypeArgument(getClass(), FacadeBase.class);    

    }

}

現在,您可以使用genericClazz.newInstance()或 better來實例化泛型的類Constructor.newInstance()。


2)聲明式方式更簡單,但需要一些樣板代碼。


使您的抽象類成為指定異常類型并提供存儲要拋出的異常的構造函數的泛型類。

例如 :


public abstract class FacadeBase<T extends FacadeException> {


    private Supplier<T> suppException;


    public FacadeBase(Supplier<T> suppException) {

        this.suppException = suppException;

    }


    public void checkFacadeAvailability(final String facadeId) throws T {

        if (!isFacadeAvailable(facadeId)) {

            throw suppException.get();

        }

    }

}

子類應該使用它們的供應商調用超級構造函數:


public class FacadeA extends FacadeBase<FacadeExceptionA>{


    public FacadeA(Supplier<FacadeExceptionA> suppException) {

        super(suppException);

    }   

}

作為替代方案,你可以更換Supplier一個Class參數,但總的想法是一樣的。


查看完整回答
反對 回復 2021-08-04
?
慕神8447489

TA貢獻1780條經驗 獲得超1個贊

停在 有兩個很好的理由throws FacadeException

  • FacadeBase.checkFacade無論如何,合同都會迫使客戶捕捉FacadeException(假設編程接口的良好做法)

  • 異常類不能是通用的。盡管您可以Exceptionthrows子句中使用類型參數,但這只是過度設計(除了違背最佳實踐)

所以子類應該throws  Facade<A...Z>Exception在適用的地方完全聲明或省略這個子句。但這對客戶端/調用者沒有影響(除非他們采取不鼓勵的聲明子類類型的方式)

如果您需要檢查調用方引發了哪個異常,那么無論如何您都必須知道具體的異常類,因為instanceof  T無論如何您都無法檢查。


查看完整回答
反對 回復 2021-08-04
?
達令說

TA貢獻1821條經驗 獲得超6個贊

據我了解,問題的核心是如何按照checkFacade()以下偽代碼示意性表示的方式聲明和實現一個方法:


public abstract class FacadeBase {

  public void checkFacade(final String facadeId) throws Facade<A...Z>Exception {

    if (!isFacadeAvailable(facadeId)) {

      throw new Facade<A...Z>Exception(facadeId);

    }

  }

  ...

}

我首先注意到,將特征異常與具體FacadeBase子類相關聯會破壞抽象。子類當然可能會拋出它們自己的特定異常,但是一旦其他類知道或特別關心那些異常,特別是為了能夠識別這些子類,抽象就會崩潰。


特別是,如果您的isFacadeAvailable(facadeId)方法與FacadeBase在 Java 類路徑中可用的子類有關,那么這似乎與該外觀實現的特征異??捎糜嘘P。在這種情況下,您不能期望能夠實例化FacadeQExceptionwhenFacadeQ不可用,并且當類路徑中不存在任何異常時,您可能會遇到類加載失敗。


其次,我觀察到因為所有的Facade[A-Z]Exceptions 都擴展了FacadeException,FacadeBase.checkFacade()所以可以簡單地聲明FacadeException而不是聲明所有單獨的異常。這不會阻止其他代碼捕獲特定異常,如果這些異常確實仍然被此方法拋出。


為了實際拋出個別例外,您需要先建立他們,并呼吁無論是大的switch塊,大if/ then/else語句,一個工廠方法,或適當的異常類的反射實例,或這些的某種組合. 請注意,異常是對象;它們可以分配給變量并從方法中返回。一個throw語句可以拋出任何 Throwable;它不需要是新實例化的。因此,您可以考慮以下方面的內容:


public void checkFacade(final String facadeId) throws FacadeException {

    if (!isFacadeAvailable(facadeId)) {

        throw createFacadeException(facadeId);

    }

}


private FacadeException createFacadeException(String facadeId) {

    if ("A".equals(facadeId)) {

        return new FacadeAException();

    } else // ...

}

但是,我敦促您考慮提供FacadeException一個成員來傳達不可用外觀的ID,而不是通過拋出特定于外觀的異常來實現。或者如果你不想把它放在FacadeException自己身上,那么定義一個FacadeUnavailableException攜帶它的子類:


public class FacadeUnavailableException extends FacadeException {

    private final String facadeId;


    private FacadeAException(String message, String facadeId) {

        super(message);

        this.facadeId = facadeId;

    }


    public String getFacadeId() {

        return facadeId;

    }

}

有了這個,你的問題就變得簡單多了:


public void checkFacade(final String facadeId) throws FacadeUnavailableException {

    if (!isFacadeAvailable(facadeId)) {

        throw new FacadeUnavailableException("unavailable", facadeId);

    }

}


查看完整回答
反對 回復 2021-08-04
  • 3 回答
  • 0 關注
  • 236 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號