Skip to content
Advertisement

Not able to create generic bounded class objects with interface

I am trying to use bounded types with generics to create generic objects of subclasses (these implement an interface). But I am getting type mismatch errors when initializing objects with the subclasses.

Here is the interface:

public interface ScannableEntity {
}

Here’s the class that implements this interface:

public final class Attachment implements ScannableEntity {
 .
 .
 .
}

Now I created 2 classes (SegmentPageScanResult and ItemProcessor) with the bounded generic type as:

@Builder
public class SegmentPageScanResult<TEntity extends ScannableEntity> {
  .
  .
  .
}

and

public class ItemProcessor<TEntity extends ScannableEntity> {

    void submitAndExecute(SegmentPageScanResult<TEntity> pageScanResult) {
          . . .
    }
}

When I am trying to initialize the SegmentPageScanResult and try calling submitAndExecute method of ItemProcessor from a Unit test as follows:

@ExtendWith(MockitoExtension.class)
public class ScanTest {

    @Mock
    private ItemProcessor<Attachment> itemProcessor;

    @Test
    public void testDoScan() {
        Attachment mockRecord = new Attachment();
        SegmentPageScanResult<Attachment> segmentPageScanResult = SegmentPageScanResult.builder()
        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
            .scannedItems(ImmutableList.of(mockRecord))
            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
            .isLastPage(true)
            ^^^^^^^^^^^^^^^^^
            .build();  
            ^^^^^^^^^      
        verify(itemProcessor).submitAndExecute(segmentPageScanResult);

    }
}

I get the error –

Required type: SegmentPageScanResult<Attachment>
Provided:SegmentPageScanResult<ScannableEntity>

Can someone please help me understand why I am not able to initialize the generic object with the class implementing the interface?

Advertisement

Answer

I think you might have done:

ItemProcessor<Attachment> itemProcessor = new ItemProcessor<>();

And you also have:

SegmentPageScanResult<ScannableEntity> segmentPageScanResult = ...

So when you call:

itemProcessor.submitAndExecute(segmentPageScanResult, TEST_SEGMENT_ID, TEST_SCAN_ID);

There is a mismatch between the type of the itemProcessor (Attachment) and SegmentPageScanResult (ScannableEntity). So you probably need to create the ItemProcessor and the SegmentPageScanResult with the same type parameter.

EDIT: It’s not completely clear what you are trying to achieve but maybe this can help:

public class ItemProcessor<T extends ScannableEntity> {

    private List<T> items;

    void submitAndExecute(SegmentPageScanResult pageScanResult) {
        pageScanResult.setScannedItems(items);
    }
}

public class SegmentPageScanResult {

    private final List<ScannableEntity> items = new ArrayList<>();

    public void setScannedItems(List<? extends ScannableEntity> items) {
        this.items.addAll(items);
    }
}

So the SegmentPageScanResult no longer has a type parameter because it only handles ScannableEntity instances. To allow setting different types from each ItemProcessor, the method parameter allows subtypes with List<? extends ScannableEntity>

User contributions licensed under: CC BY-SA
10 People found this is helpful
Advertisement