code: package test;
  
  import java.util.ArrayList;
  
  
  
  // 1. A simple object and a collection class for it...
  class Item {
      int index;
  }
  
  class ItemGroup<ItemType extends Item> extends ArrayList<ItemType> {      
      
      // 2. The collection has a method that returns another collection
      //    with the same generic type, ItemType with an upper bound of Item.
      public ItemGroup<ItemType> getItems() {
          ItemGroup<ItemType> items = new ItemGroup<>();
          items.addAll(this);
          return items;
      }
      
      // 3. The collection has an abstract nested class, e.g. for processing elements...
      public abstract class Fork {
          public Fork() {}
          
          // 4. The nested class has an abstract method that takes
          //    the same generic type argument that the collection that instantiated
          //    this Fork consists of. The argument ItemType has an upper bound
          //    of Item by construct.
          public abstract void process(ItemType item); 
      }
  }
  
  
  // 5. A specific Item implementation with the corresponding specific collection implementation
  //    They can be completely bare...
  class MyItem extends Item {   
  }
  
  
  class MyGroup extends ItemGroup<MyItem> {
  }
  
  
  // 6. The test case that fails...
  public class AssertErrorTest {
      public static void main(String[] args) {
          // We instantiate a new specific Item group, and get a second collection of
          // the same type of items from it...
          ItemGroup<?> items = new MyGroup().getItems();
          
          // We then try to create a type-restricted nested class to process that
          // group of channels. But, this trips the compiler...
          items.new Fork() {
              @Override
              public void process(Item item) { System.err.println(item.index); }
          }.process(items.get(0));
      }
  }
  