簡體   English   中英

Java中的泛型:如何定義具有多個不同類型的函數

[英]Generic Type in java: How to define a function with multiple different type returned

@Service
public class Animal {
   public String name;
}
@Service
public class Dog extends Animal {
   public String name;
}

@Service
public class Cat extends Animal {
   public String name;
}

在spring boot項目中,我想使用spring框架提供的ApplicationContext獲得一個特定的bean,這是我寫來說明的一個簡單示例:

@Component
public class AnimalLocator implements ApplicationContextAware {
   private static ApplicationContext applicationContext;
   @Override
   public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
      if (PayServiceLocator.applicationContext == null) {
         PayServiceLocator.applicationContext = applicationContext;
      }
   }

   public <T extends Animal> T getService(String name) {
      if("Cat".equals(name) {
        applicationContext.getBean(name, Cat.class);
      }
      if("Dog".equals(name) {
        applicationContext.getBean(name, Dog.class);
      }
   }
}

但是,編譯器提示了異常:

在此處輸入圖片說明

馬賽克部分應該是狗或貓。 我認為它應該起作用,因為T已經擴展了Animal類,但是它沒有,那么有人對此有任何想法嗎? 謝謝!

由於您正在使用bean類訪問bean實例,因此直接將class作為參數傳遞是很簡單的:

public <T extends Animal> T getPayService(String name, Class<T> payClass) {
   return applicationContext.getBean(name, payClass);
}

當然, getPayService T將擴展Animal 這意味着用另一種類型調用它的代碼將無法編譯:

Fruit fruit = animalLocator.getPayService("Banana")

為了說明您當前的問題 ,請查看以下內容:

Cat cat = animalLocator.getPayService("Dog");

在這種情況下, TCat ,但是您的代碼將返回Dog

為了避免編譯器錯誤,可以添加類型強制轉換:

return (T) applicationContext.getBean(...

但這仍然是不安全的,因為編譯器仍然無法保證實際的返回類型將是運行時調用方上下文中T值,並且調用方將具有類強制轉換異常。

如果我們可以假設getBean是一個安全的調用,那么您應該將方法更改為以下實現:

public <T extends Animal> T getPayService(String name, Class<T> cls) {
   return applicationContext.getBean(name, cls);
}

從調用者的角度來看,這並沒有太大變化,而是取決於applicationContext.getBean(name, cls);的事實(或假設applicationContext.getBean(name, cls); 將返回類型T的對象。 這意味着您的代碼與getBean一樣具有類型安全性,但是編譯器對此感到滿意。

您可以將所有Animal實例自動綁定到Map中,而無需編寫if / else:

@Service("Animal")
public class Animal {
    public String name;
}
@Service("Dog")
    public class Dog extends Animal {
}
@Service("Cat")
    public class Cat extends Animal {
}

在您的AnimalLocator中:

@Component
public class AnimalLocator {

   @Autowired
   private Map<String,Animal> animals;

   public <T extends Animal> T getService(String name) {
      return this.animals.get(name);
   }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM