Java instead of 用法,在此示例中了解Java泛型的最佳用法

Let's say I have a manufacturing scheduling system, which is made up of four parts:

There are factories that can manufacture a certain type of product and know if they are busy:

interface Factory {

void buildProduct(ProductType product);

boolean isBusy();

}

There is a set of different products, which (among other things) know in which factory they are built:

interface Product> {

Factory getFactory();

}

Then there is an ordering system that can generate requests for products to be built:

interface OrderSystem {

Product> getNextProduct();

}

Finally, there's a dispatcher that grabs the orders and maintains a work-queue for each factory:

class Dispatcher {

Map, Queue>> workQueues

= new HashMap, Queue>>();

public void addNextOrder(OrderSystem orderSystem) {

Product> nextProduct = orderSystem.getNextProduct();

workQueues.get(nextProduct.getFactory()).add(nextProduct);

}

public void assignWork() {

for (Factory> factory: workQueues.keySet())

if (!factory.isBusy())

factory.buildProduct(workQueues.get(factory).poll());

}

}

Disclaimer: This code is merely an example and has several bugs (check if factory exists as a key in workQueues missing, ...) and is highly non-optimal (could iterate over entryset instead of keyset, ...)

Now the question:

The last line in the Dispatcher (factory.buildProduct(workqueues.get(factory).poll());) throws this compile-error:

The method buildProduct(capture#5-of ?) in the type Factory is not applicable for the arguments (Product)

I've been racking my brain over how to fix this in a type-safe way, but my Generics-skills have failed me here...

Changing it to the following, for example, doesn't help either:

public void assignWork() {

for (Factory> factory: workQueues.keySet())

if (!factory.isBusy()) {

Product> product = workQueues.get(factory).poll();

product.getFactory().buildProduct(product);

}

}

Even though in this case it should be clear that this is ok...

I guess I could add a "buildMe()" function to every Product that calls factory.buildProduct(this), but I have a hard time believing that this should be my most elegant solution.

Any ideas?

EDIT:

A quick example for an implementation of Product and Factory:

class Widget implements Product {

public String color;

@Override

public Factory getFactory() {

return WidgetFactory.INSTANCE;

}

}

class WidgetFactory implements Factory {

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

}

}

解决方案

Got it! Thanks to meriton who answered this version of the question:

I need to baby-step the compiler through the product.getFactory().buildProduct(product)-part by doing this in a separate generic function. Here are the changes that I needed to make to the code to get it to work (what a mess):

Be more specific about the OrderSystem:

interface OrderSystem {

> ProductType getNextProduct();

}

Define my own, more strongly typed queue to hold the products:

@SuppressWarnings("serial")

class MyQueue> extends LinkedList {};

And finally, changing the Dispatcher to this beast:

class Dispatcher {

Map, MyQueue>> workQueues = new HashMap, MyQueue>>();

@SuppressWarnings("unchecked")

public > void addNextOrder(OrderSystem orderSystem) {

ProductType nextProduct = orderSystem.getNextProduct();

MyQueue myQueue = (MyQueue) workQueues.get(nextProduct.getFactory());

myQueue.add(nextProduct);

}

public void assignWork() {

for (Factory> factory: workQueues.keySet())

if (!factory.isBusy())

buildProduct(workQueues.get(factory).poll());

}

public > void buildProduct(ProductType product) {

product.getFactory().buildProduct(product);

}

}

Notice all the generic functions, especially the last one. Also notice, that I can NOT inline this function back into my for loop as I did in the original question.

Also note, that the @SuppressWarnings("unchecked") annotation on the addNextOrder() function is needed for the typecast of the queue, not some Product object. Since I only call "add" on this queue, which, after compilation and type-erasure, stores all elements simply as objects, this should not result in any run-time casting exceptions, ever. (Please do correct me if this is wrong!)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值