了解本例中Java泛型的最佳使用

了解本例中Java泛型的最佳使用,java,generics,Java,Generics,假设我有一个生产调度系统,它由四部分组成: 有些工厂可以生产某种类型的产品,并知道他们是否忙碌: interface Factory<ProductType> { void buildProduct(ProductType product); boolean isBusy(); } 我一直在绞尽脑汁想如何以一种类型安全的方式解决这个问题,但是我的泛型技能让我在这里失败了 例如,将其更改为以下内容也无济于事: public void assignWork() {

假设我有一个生产调度系统,它由四部分组成:

  • 有些工厂可以生产某种类型的产品,并知道他们是否忙碌:

    interface Factory<ProductType> {
        void buildProduct(ProductType product);
        boolean isBusy();
    }
    
    我一直在绞尽脑汁想如何以一种类型安全的方式解决这个问题,但是我的泛型技能让我在这里失败了

    例如,将其更改为以下内容也无济于事:

    public void assignWork() {
        for (Factory<?> factory: workQueues.keySet())
            if (!factory.isBusy()) {
                Product<?> product = workQueues.get(factory).poll();
                product.getFactory().buildProduct(product);
            }
    }
    
    您的代码很奇怪。
    您的问题是您正在将一个
    产品
    传递给一个方法,该方法需要一个
    产品类型
    ,实际上是
    T

    我也不知道什么是
    产品
    ,因为您在OP中没有提到它的定义。
    您需要传递
    产品
    才能工作。我不知道您将从何处获得它,因为我无法理解您试图用代码做什么

    Map>>workQueues=newhashmap>>();
    
    Map<Factory<?>, Queue<Product<?>>> workQueues = new HashMap<Factory<?>, Queue<Product<?>>>();
    
    // factory has the type "Factory of ?"
    for (Factory<?> factory: workqueues.keySet())       
        // the queue is of type "Queue of Product of ?"
        Queue<Product<?>> q = workqueues.get(factory);
    
        // thus you put a "Product of ?" into a method that expects a "?"
        // the compiler can't do anything with that.
        factory.buildProduct(q.poll());
    }
    
    //工厂的类型是“工厂的?” 对于(工厂:workqueues.keySet()) //队列的类型为“产品的队列?”
    排队明白了!感谢meriton回答了这个问题:

    我需要在一个单独的泛型函数中完成
    product.getFactory().buildProduct(product)
    -部分的编译。以下是我需要对代码进行的更改,以使其正常工作(真是一团糟):

    • 请更具体地介绍OrderSystem:

      interface OrderSystem {
          <ProductType extends Product<ProductType>> ProductType getNextProduct();
      }
      
      接口命令系统{
      ProductType getNextProduct();
      }
      
    • 定义我自己的强类型队列以容纳产品:

      @SuppressWarnings("serial")
      class MyQueue<T extends Product<T>> extends LinkedList<T> {};
      
      @SuppressWarnings(“串行”)
      类MyQueue扩展了LinkedList{};
      
    • 最后,将调度程序更改为此beast:

      class Dispatcher {
          Map<Factory<?>, MyQueue<?>> workQueues = new HashMap<Factory<?>, MyQueue<?>>();
      
          @SuppressWarnings("unchecked")
          public <ProductType extends Product<ProductType>> void addNextOrder(OrderSystem orderSystem) {
              ProductType nextProduct = orderSystem.getNextProduct();
              MyQueue<ProductType> myQueue = (MyQueue<ProductType>) workQueues.get(nextProduct.getFactory());
              myQueue.add(nextProduct);
          }       
      
          public void assignWork() {
              for (Factory<?> factory: workQueues.keySet())
                  if (!factory.isBusy())
                      buildProduct(workQueues.get(factory).poll());
          }
      
          public <ProductType extends Product<ProductType>> void buildProduct(ProductType product) {
              product.getFactory().buildProduct(product);
          }
      }   
      
      类调度器{
      Map>workQueues=newhashmap>();
      @抑制警告(“未选中”)
      public void addNextOrder(OrderSystem OrderSystem){
      ProductType nextProduct=orderSystem.getNextProduct();
      MyQueue MyQueue=(MyQueue)workQueues.get(nextProduct.getFactory());
      添加(nextProduct);
      }       
      公共工程(){
      对于(工厂:workQueues.keySet())
      如果(!factory.isBusy())
      buildProduct(workQueues.get(factory.poll());
      }
      公共产品(产品类型产品){
      product.getFactory().buildProduct(产品);
      }
      }   
      
    注意所有的泛型函数,尤其是最后一个。另外请注意,我不能像在原始问题中那样将此函数内联回for循环


    还要注意的是,队列的类型转换需要
    @SuppressWarnings(“unchecked”)
    函数上的
    @SuppressWarnings(“unchecked”)
    注释,而不是某些产品对象。因为我只在这个队列上调用“add”,在编译和类型擦除之后,它将所有元素简单地存储为对象,所以这永远不会导致任何运行时强制转换异常。(如果这是错误的,请纠正我!)

    为什么
    Product
    需要泛型类型?@Andy可能不需要,但我想如果我在Product return a Factory中使用getFactory()方法,那么使这项工作正常的机会可能更小,因为那个时候,返回的工厂甚至不知道它应该生产哪种类型的产品。但也许我错了?通常你会有一个
    产品
    ,以及其他类型的子类(例如
    书籍
    汽车
    ),而不是“X的产品,它是X的产品的子类型”-这是可能的吗?同意。。。(这是可能的)。。。也许我不需要用更干净的方法。但通过这种方式,我能够更好地强制执行,我得到了正确的工厂回来。。。否?是有道理的,但是为什么我的第二个版本的代码不能工作,它使用了这个调用:
    product.getFactory().buildProduct(product)getFactory方法是否正确定义为仅返回可以将产品作为参数处理的工厂?
    
    class Widget implements Product<Widget> {
        public String color;
    
        @Override
            public Factory<Widget> getFactory() {
                return WidgetFactory.INSTANCE;
        }
    }
    
    class WidgetFactory implements Factory<Widget> {
        static final INSTANCE = new WidgetFactory();
    
        @Override
        public void buildProduct(Widget product) {
            // Build the widget of the given color (product.color)
        }
    
        @Override
        public boolean isBusy() {
            return false; // It's really quick to make this widget
        }
    }
    
    Map<Factory<?>, Queue<Product<?>>> workQueues = new HashMap<Factory<?>, Queue<Product<?>>>();
    
    // factory has the type "Factory of ?"
    for (Factory<?> factory: workqueues.keySet())       
        // the queue is of type "Queue of Product of ?"
        Queue<Product<?>> q = workqueues.get(factory);
    
        // thus you put a "Product of ?" into a method that expects a "?"
        // the compiler can't do anything with that.
        factory.buildProduct(q.poll());
    }
    
    interface OrderSystem {
        <ProductType extends Product<ProductType>> ProductType getNextProduct();
    }
    
    @SuppressWarnings("serial")
    class MyQueue<T extends Product<T>> extends LinkedList<T> {};
    
    class Dispatcher {
        Map<Factory<?>, MyQueue<?>> workQueues = new HashMap<Factory<?>, MyQueue<?>>();
    
        @SuppressWarnings("unchecked")
        public <ProductType extends Product<ProductType>> void addNextOrder(OrderSystem orderSystem) {
            ProductType nextProduct = orderSystem.getNextProduct();
            MyQueue<ProductType> myQueue = (MyQueue<ProductType>) workQueues.get(nextProduct.getFactory());
            myQueue.add(nextProduct);
        }       
    
        public void assignWork() {
            for (Factory<?> factory: workQueues.keySet())
                if (!factory.isBusy())
                    buildProduct(workQueues.get(factory).poll());
        }
    
        public <ProductType extends Product<ProductType>> void buildProduct(ProductType product) {
            product.getFactory().buildProduct(product);
        }
    }