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

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

如何從靜態工廠方法綁定靜態嵌套類的泛型類型?

如何從靜態工廠方法綁定靜態嵌套類的泛型類型?

弒天下 2023-08-23 11:40:45
我正在使用《Effective Java》中概述的 Builder 模式的變體,但我對 Java 泛型的行為感到困惑??紤]下面的類:public class Result<T extends Resource> {    //final members    final boolean success;    final T resource;    //private constructor    private Result(Builder<T> builder) {        success = builder.success;        resource = builder.resource;    }    //getters    public boolean isSuccess() {        return success;    }    public T getResource() {        return resource;    }    //static factory method to get a builder    public static <T2 extends Resource> Builder<T2> builder(Class<T2> clazz) {        return new Builder<T2>();    }    //nested Builder class    public static class Builder<T extends Resource> {        boolean success;        T resource;        private Builder() { }        public Builder<T> success(boolean success) {            this.success = success;            return this;        }        public Builder<T> resource(T resource) {            this.resource = resource;            return this;        }        public Result<T> build() {            return new Result<T>(this);        }    }}當我有一個 Resource 的具體子類時,這似乎很有效:Result<Device> result = Result.builder(Device.class).build();但是,當我從另一個定義具有 Resource 通用子類的方法的類中使用它時,它甚至無法編譯:public <T extends Resource> Result<T> createResult(T resource) {    return Result.builder(resource.getClass()).build();}編譯錯誤是:類型不匹配:無法從 Result<capture#1-of 轉換?將 Resource> 擴展為 Result<T>既然 T 和 T2 都擴展了 Resource,為什么它不能弄清楚 Result.Builder.build() 應該返回泛型類型 T 的 Result 呢?我發現的一種解決方法是放棄 static builder() 方法并使用類似這樣的方法:public <T extends Resource> Result<T> createResult(T resource) {     return new Result.Builder<T>().build(); }似乎應該有一種方法可以使用靜態工廠方法和隱藏構造函數來做到這一點......我錯過了什么嗎?
查看完整描述

1 回答

?
慕妹3146593

TA貢獻1820條經驗 獲得超9個贊

編譯錯誤的原因是由于Object.getClass()方法。根據java文檔:

返回此對象的運行時類。返回的 Class 對象是由所表示的類的靜態同步方法鎖定的對象。

實際結果類型是 Class where |X|?是調用 getClass 的表達式的靜態類型的擦除。例如,此代碼片段中不需要強制轉換:

數字 n = 0;
類 c = n.getClass();


打電話時return Result.builder(resource.getClass()).build();

  1. resource.getClass()Class<? extends Resource>將像Resource擦除一樣返回T

  2. Result.builder(resource.getClass())方法將返回Builder<? extends Resource>。

  3. Result.builder(resource.getClass()).build()會回來的Result<? extends Resource>

的類型信息T在步驟 1 中丟失。因此,編譯錯誤顯示為返回類型不兼容??梢赃M行以下更改來解決該錯誤。

  1. 更改構建器方法以接受T實例而不是Class<T>評論中的狀態。

  2. 將調用者更改為傳遞Class<T>而不是Class<? extends Resource>方法builder。

更改的代碼片段:

? // Caller

? // Solution 1

? public <T extends Resource> Result<T> createResult(T resource) {

? ? return Result.builder(resource).build();

? }


? // Solution 2

? public <T extends Resource> Result<T> createResult(Class<T> resourceClass) {

? ? return Result.builder(resourceClass).build();

? }



public class Result<T extends Resource> {


? ...

? //Solution 1

? public static <T2 extends Resource> Builder<T2> builder(T2 instance) {

? ? return new Builder<T2>();

? }


? // static factory method to get a builder

? // Solution 2

? public static <T2 extends Resource> Builder<T2> builder(Class<T2> clazz) {

? ? return new Builder<T2>();

? }

? ...

查看完整回答
反對 回復 2023-08-23
  • 1 回答
  • 0 關注
  • 190 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

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

幫助反饋 APP下載

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

公眾號

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