泛型用的好,下班走得早

泛型方法和類允許程序員編寫高級化的單個方法或類,以用於不同的類型。

泛型方法和類允許程序員編寫高級化的單個方法或類,以用於不同的類型。

我們每天都在使用它們,例如List ,Stream ,Map …

泛型類是普通類,其類名後跟一個類型參數部分。這些類稱爲參數化類或參數化類型,因爲它們接受一個或多個參數。

特徵:

  • 類型安全:泛型中只能容納一種類型的對象。
  • 不需要類型轉換:無需類型轉換對象。
  • 編譯時檢查:在編譯時進行檢查,因此在運行時不會發生此問題。好的編程策略表明,在編譯時處理問題比運行時要好得多。

類型參數命名約定:

  • T type
  • E element
  • K Key
  • N Number
  • V value

泛型通配符:

我們知道 ? 是通配符,它表示任何類型。如果我們寫<? extends Number>,我們接受Number的任何子類,例如Integer,Float和double。

我們可以使用通配符作爲參數,字段,返回類型或局部變量的類型。但是,不允許將通配符用作泛型方法調用,泛型類實例創建或超類型的類型參數。

通用類示例:

public class Response<T> {
 private List<T> data;
 private Integer page;
 private Integer elements;
}

在第一個簡單示例中,我們創建了一個通用類Response,將用於返回分頁的結果。我們不需要做魔術,也不必創建其他類。

如何寫更少的代碼?

儘管泛型在庫中使用非常廣泛,但是我看到很少有程序員使用泛型來泛化代碼,例如,您有多少次看到控制器,服務和存儲庫幾乎在做同樣的事情?

在介紹完之後,我希望您展示一個簡單的示例,說明如何編寫一次性代碼並在多個類中使用它。

一個簡單的項目

在此示例中,我想向您展示如何定義BaseService和GeneralRepository來處理Java服務中的常見操作。

BaseEntity.java

@Data
@AllArgsConstructor
@NoArgsConstructor
public class BaseEntity {
    @Id
    protected String id;
    protected String tenantId;
    protected Date creationDate;
    protected Date updateDate;
}

我們正在創建一個簡單的類,該類在我們的類中包含commons屬性,下一個代碼段將很有必要。

BaseRepository

@Repository
public interface GenericRepository<E extends BaseEntity> extends ReactiveCrudRepository<E, String> {
    Mono<Void> deleteByIdAndTenantId(String id, String tenantId);
    Mono<E> findFirstByIdAndTenantId(String id, String tenantId);
}

這是基本存儲庫,其中包含對我們的BaseEntity類的子類的常見查詢。

BaseService

@Service
@Slf4j
public class BaseService<E extends BaseEntity> {

    @Autowired
    protected GenericRepository<E> generalRepo;

    public Mono<E> findEnitity(String entityId, String tenantId) {
        return generalRepo.findFirstByIdAndTenantId(entityId,tenantId);
    }

    public Mono<Void> delete(String entityId, String tenantId) {
        return findEnitity(entityId, tenantId)
                .switchIfEmpty(Mono.error(new NotFoundException(ITEM_NOT_FOUND)))
                .flatMap(e -> generalRepo.deleteByIdAndTenantId(e.getId(),e.getTenantId()));
    }
    
    public Mono<E> saveEntity(String tenantId, E entity) {
        entity.setTenantId(tenantId);
        return generalRepo.save(entity);
    }

    public Mono<E> updateEntity(String entityId, String tenantId,E entity) {
        return findEnitity(entityId,tenantId)
                .map(u -> saveEntity(tenantId,entity))
                .switchIfEmpty(Mono.error(new Exception(ITEM_NOT_FOUND)))
                .flatMap(m -> m);
    }
}

所有服務將繼承BaseService繼承繼承的保存,更新,查找和刪除方法,這些方法執行通用操作以將我們的數據持久保存在數據庫中。顯然,這段代碼非常簡單,您可以編寫一種處理分頁請求的方法,在執行插入/更新之前添加檢查。

BaseController

public class BaseController<E extends BaseEntity> {

    @Autowired
    private BaseService<E> baseService;

    @PostMapping("/save")
    public Mono<E> save(Authentication auth,
                        @RequestBody E entity) {
        return baseService.save(getTenant(auth),entity);
    }
    
}

讓我們以允許在多個控制器之間共享公共端點的BaseController結束該示例。

總結

因此,我們對泛型進行了一些小小的更新,並看到了如何編寫更少的代碼來使多個類之間的通用操作更加溫和。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章