【问题标题】:How do I restrict a generic type to specific types in java?java - 如何将泛型类型限制为Java中的特定类型?
【发布时间】:2012-02-11 23:08:43
【问题描述】:

我有一个带有泛型变量的类。我想将该变量限制为一组 类型(如 Car、Bike、...)如下所示:

class Garage{
   Class<K> ownerStaff;

   public Garage(Car c){
      this.ownerStaff = c;
   }
   public Garage(Bike b){
      this.ownerStaff = b;
   }
   ...
}

所以“genericVariable”只能是汽车、自行车或我想要的任何其他类型,但不是任何东西。我该怎么做?

注意: 我想我可以创建一个父类“Vehicle”,然后这样写(如果我错了,请纠正我)

class Garage<K extends Vehicle>{
   Class<K> ownerStaff;

   public Garage(Class<K> c){
      this.ownerStaff = c;
   }
}

但我不想要一个父类并使我所有的类都扩展“Vehicle”,并且可能我不想输入例如Garage&lt;Car&gt; 当我实例化一个“车库”时。

谢谢

【问题讨论】:

  • 为什么它必须是通用的?它可以只输入Vehicle。如果您的类型不共享公共代码,请将 Vehicle 设为接口而不是类。
  • 另外,我认为您的意思是 K 不是 Class&lt;K&gt;Class&lt;K&gt; 主要用于反射。
  • 是的,我可能是说 K。没关系...如果我制作界面 Vehicle 然后我编写第二段代码对吗?我的意思是...车库

标签: java generics types


【解决方案1】:

你的对象最终必须有某种共同的行为,否则将它们放在同一个Garage 中是没有意义的。因此,正如@perelman 建议的那样,只需在接口中声明这种常见行为并使用它(无泛型):

public interface Vehicle {
    // common behavior declared, if any
}

public class Car implements Vehicle {
    // Implementation
}

public class Bike implements Vehicle {
    // Implementation
}

public class Garage {
    Vehicle vehicle;

    public Garage(Vehicle v) {
       vehicle = v;
    }
}

【讨论】:

    【解决方案2】:

    重读您的问题,我认为您想要的只是将ownerStaff 字段的类型设为Class&lt;?&gt;。这允许您使用任何 Class 实例来填充它,而不管其类型如何。

    这里的旧答案:限制泛型类型的唯一方法是使用&lt;K extends Vehicle&gt;,正如您已经说过的。这还有一个额外的好处,就是能够在你的类中调用 K 实例上的所有 Vehicle 方法。

    你当然可以对值类型进行instanceof检查,例如,在你的构造函数中,添加if (!(Car.class.isAssignableFrom(c) or Bike.class.isAssignableFrom(c))) throw new IllegalArgumentException("we only accept cars and bikes")。不过,这将是一项非常严格的检查,并且会阻止该类的用户发明自己的车辆类型。

    【讨论】:

    • 我认为您对 Class> 的看法是正确的,但 this.ownerStuff = c; 不起作用(Class> 和 Car 类型不兼容)。
    【解决方案3】:

    由于 Java 没有代数数据类型——即你不能说“类型 A 或类型 B”,只能说“类型 A 和 B”,通过常见的超类型——这不是你自然可以做的事情。

    解决此问题的一种方法是将Garage 的构造函数设为私有,并且只为特定类型提供静态工厂方法:

    class Garage<K> {
        private Garage<K>(K thing) { this.thing = thing; } // hidden
        private K thing;
        public Garage<Car> newCarGarage(Car c) {
            return new Garage<Car>(c);
        }
        //... similarly for other types you want to be allowed
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-09-13
      • 1970-01-01
      • 1970-01-01
      • 2021-08-10
      • 1970-01-01
      • 1970-01-01
      • 2021-12-01
      相关资源
      最近更新 更多