2

Java 8 here. I have the following POJOs:

public interface HasPartNumber {
  String getPartNumber();
}

@Getter
@Setter
public class InventoryItem implements HasPartNumber {
  private String modelNumber;
  private String description;
  // lots of other fields here

  @Override
  public String getPartNumber() {
    return this.modelNumber;
  }
}

public class Inventory extends ArrayList<InventoryItem> {
  // Inventory is just an alias of a list of InventoryItem
}

@Getter
@Setter
public class PriceItem implements HasPartNumber {
  private String equipmentNumber;
  // lots of other fields here

  @Override
  public String getPartNumber() {
    return this.equipmentNumber;
  }
}

public class PriceRoster extends ArrayList<PriceItem> {
  // PriceRoster is just an alias of a list of PriceItem
}

I understand some of you may have an aversion to how I'm modeling Inventory and PriceRoster, but using the is-a and has-a golden rule, it is correct. An "inventory" is no more and no less than just a list of InventoryItems. Ditto for PriceRoster. And, the Domain-Driven Design community would probably agree that these are valid data models if it makes sense to a developer reading the code.

However, I am not married to this design. And so while my druthers would be to keep this data model above, if it truly is impossible to accomplish what I describe below without changing the data model, I'll be flexible.


I am trying to write a generic PartProcessor class that will iterate through lists of HasPartNumber impls and perform processing on them. My best attempt:

public class PartProcessor<PART_CONTAINER extends List<HasPartNumber>> {

  public void process(PART_CONTAINER partContainer) {

    partContainer.stream().forEach(part -> {

      // Do something here

    });

  }

}

produces compilation errors when I go to instantiate the PartProcessor:

PartProcessor<Inventory> inventory = new PartProcessor<Inventory>();

The compiler errors I'm seeing are:

"Type parameter 'com.example.myapp.Inventory' is not within its bound; should implement 'java.util.List<com.example.myapp.HasPartNumber>'"

Any ideas what I can do to get my PartProcessor working generically on any list of HasPartNumbers impl, including Inventory and PriceRoster?

Naman
  • 27,789
  • 26
  • 218
  • 353
hotmeatballsoup
  • 385
  • 6
  • 58
  • 136

1 Answers1

2

bounded types makes the type covariant:

 public class PartProcessor<PART_CONTAINER extends List<? extends HasPartNumber>> {... 

For a broader read see this answer also.

Eugene
  • 117,005
  • 15
  • 201
  • 306
  • Thanks @Eugene (+1) but can I place `PartProcessor` in its own source file (`PartProcessor.java`)? Doing so produces the compiler error: "_Modifier 'static' not allowed here_"... – hotmeatballsoup Nov 19 '19 at 18:41
  • @hotmeatballsoup of course you can, I can't guess though what exactly is not working for you. – Eugene Nov 19 '19 at 18:44
  • According to [this](https://stackoverflow.com/a/11831828/5235665) you can't have a top-level static class – hotmeatballsoup Nov 19 '19 at 18:45
  • @hotmeatballsoup ah! right, a _top level_ class - no; but you don't need it as such, right? – Eugene Nov 19 '19 at 18:46
  • I mean, I'd *prefer* to make it a top level class...where else would I put it?! Its generic to all lists of `HasPartNumbers`. So to me it doesn't make sense to put it inside of `Inventory.java` or `PriceRoster.java`. And `HasPartNumber` is just a one-method interface...so putting it inside of there seems weird to me as well! – hotmeatballsoup Nov 19 '19 at 18:48
  • @hotmeatballsoup that is correct, it does not make sense, so put it as a top level class? – Eugene Nov 19 '19 at 18:49
  • Haha I'm getting *really* confused now. Maybe I don't understand what is meant by a top-level class. To me, that means the outermost and only `class` defined inside a JAVA (.java) source file. If I'm wrong about that, please correct me. If I'm correct, then I'm not sure what you're telling me to do. Your solution (it seems) cannot be used for top-level classes. – hotmeatballsoup Nov 19 '19 at 18:51
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/202670/discussion-between-eugene-and-hotmeatballsoup). – Eugene Nov 19 '19 at 18:52