Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Ambiguous constructor (java 7)... the only way around this is a Builder pattern, right?

Tags:

java

This code compiles fine under Java 6, but when switching to Java 7 results in a compile time error "reference to Foo is ambiguous, both constructor <I,C>Foo(C) in com.company.Foo and constructor <I>Foo(I) in com.company.Foo match"

/**
 * Constructor A - acts on a Collection of Iterables
 */
public <I extends Iterable<T>, C extends Collection<I>> Foo(C intervalSeries) {
    initialize(intervalSeries);
}

/**
 * Constructor B - convenience constructor for callers who only have 1 Iterable
 */
public <I extends Iterable<T>> Foo(I intervals) {
    List<I> intervalSeries = newArrayList(1);
    intervalSeries.add(intervals);
    initialize(intervalSeries);
}

I can see why (Collections are Iterables). I'm planning on writing a Builder helper class than differentiates the two construction options by providing a differently-named builder method to get around this, but before I do I thought I'd ask: There's no magic wildcard or super incantation that's going to get me out of this, right?

like image 684
user311121 Avatar asked Feb 14 '23 23:02

user311121


1 Answers

You're overusing generics.

You can simply take a Collection<I>, and any subclass of that will be implicitly convertible to that interface.

In fact, you don't need type parameters at all; you can write

public Foo(Collection<? extends Iterable<T>> intervalSeries)
public Foo(Iterable<T> intervals)

You may also want to change T to ? extends T.

like image 162
SLaks Avatar answered Apr 28 '23 10:04

SLaks