Chthonic Project
Chthonic Project

Reputation: 8346

Guava Function with generic types

I am trying to code up a few Functions that I will be using quite often in the rest of my code. Some of these are things like, say, summing up all the numbers of an Iterable. Instead of implementing different functions for Double, Integer, etc. I want a single Function that sums up all the elements of a given Iterable as long as each element is a number. In order to do this, I attempted the following:

<T> Function<List<T extends Number>, T> sum = new Function<List<T extends Number>, T>() {
    public T apply(List<T> tlist) {
        // the main code
    }
};

But I get a compiler error saying "Unexpected token". I have coded my own Java methods with generics before, but I don't understand why the same thing isn't working here. Am I missing something ridiculously obvious, or is it that guava Functions don't allow generics?

Upvotes: 1

Views: 950

Answers (2)

ColinD
ColinD

Reputation: 110046

A couple things:

  1. If you're going to define bounds for a generic type (e.g. T extends Number) you have to do it where the type is declared (e.g. not <T> Function... but <T extends Number> Function...). I see Louis has already covered this.
  2. I'm not sure it's really possible to implement a single function that can sum any type of Number, though you could come reasonably close I suppose. You'd have to take into consideration the possibility of numbers that are larger than any of the built in primitive types can represent (BigInteger, BigDecimal, and even possibly custom Number subclasses).
  3. Your method doesn't really need to a type parameter at all if your function returns Double.

It can just be:

Function<List<? extends Number>, Double> sum = new Function<List<? extends Number, Double>() {
  public Double apply(List<? extends Number> numbers) {
    // the main code
  }
}

Upvotes: 2

Louis Wasserman
Louis Wasserman

Reputation: 198033

You can't define a polymorphic variable like this, and you can also only put bounds like extends Number inside the initial declaration of the T type variable. I suspect that the closest thing to what you mean that would actually work is something like

<T extends Number> Function<List<T>, T> sum() {
  return new Function<List<T>, T>() {
    public Double apply(List<T> doubles) {
        // the main code
    }
  };
}

...except that you're also going to have issues returning a Double instead of a T.

Upvotes: 1

Related Questions