1

I am trying to add a method to an existing class BinaryTree<T> to simple add the values of all the elements in the tree. The problem is that being the class a generic one, not all the types that can be send at the time of creating a tree can be added. I mean, for example It wouldn't make any sense to try to add the values of a class people.

So my question is, how do I make a method public T addAllElements() that only allows T to be an specific kind of type, in this case, only the types that is possible to add it's value, like Integer, Float, Long, etc? I guess there have to be some kind of numerical interface or maybe some kind of declaration provided by the language to do something like that.

By the way, it seems to be a solution without having to create a child class, in case that it could help in anything, because I was asked to solve a similar problem and the instructions says that the method have to be in the same class.

Trying to be more clear, I'll ask another question , because I think that both of them have the same answer.

I found that the method sort() in java.util.Arrays class can be used by a class if the class implements the interface Comparable<T>. So if I hava a class, lets say

public class People {
    implements Comparable<People>
    private String name;
    public int compareTo(People o) {
        ...
    }
    ...
}

This class can be sorted with the sort() method from the Arrays class, but if the class dind't implement the Comparable<T> interface it couldn't. So what is making this restriction in the Arrays class definition? Is it what I need to solve the first problem I asked?

sir psycho sexy
  • 780
  • 7
  • 19
  • 1
    Also see [*Bounded Type Parameters*](https://docs.oracle.com/javase/tutorial/java/generics/bounded.html). But, as a side note, `Arrays.sort` does not use a type bound (for historical reasons, I'm sure). `Arrays.sort` just blindly casts to `Comparable` and throws an exception during execution. It's probably not an example we should typically follow. ;p – Radiodef May 15 '15 at 00:42

2 Answers2

2

So my question is, how do I make a method publicTaddAllElements() that only allows T to be an specific kind of type, in this case, only the types that is possible to add it's value, like int, float, long, etc? I guess there have to be some kind of numerical interface or maybe some kind of declaration provided by the language to do something like that.

You're looking for Number.

So your declaration would look something like this, if the class is generic:

public BinaryTree<T extends Number> {
  // ...
}

or if you want to make just the method generic:

public <T extends Number> T addAllElements() {
  // ...
}

That said, for better or for worse Number does not define arithmetic operations in terms of methods. To my knowledge there is no such built-in type which does.

Do note that the types you listed are all primitives, which mean they're not compatible with generics at all. Subtypes of Number (and types that can be used with generics) will all be wrapper types: Integer, Float, Long, etc.

Matt Ball
  • 354,903
  • 100
  • 647
  • 710
  • Reformulated the question for being clear: It Seems that this class `number` and all of his childs classes are allowed by java to being added without making the compiler giving error messages. So for the second part of the question, does `Arrays` class is a class or extends from a class that have this kind of permissions (in this case to be ordered, not added) from java being this something that is coded in a library that is a really deep part of the language? or is there any way to code this specific "permission" without extending from a class that is already allowed to do that? – sir psycho sexy May 15 '15 at 01:01
  • No, two `Number`s _can't_ be added together. Try it. [The compiler won't let you.](http://stackoverflow.com/q/2721390/139010) There are compiler-specific "hacks" for auto(un)boxing when working with specific subtypes of `Number` (`Integer`, `Float`, and so on). – Matt Ball May 15 '15 at 02:01
2

Your examples are related, but they're not the same.

To address the latter concern first, the reason that Arrays.sort with a specific signature requires that things be Comparable is because it needs to sort them based on that natural ordering. There is another signature that you could provide to the method which allows you to pass a custom Comparator to it, to sort on whatever other property of the class you liked.

To your main concern, you need to have an upper-bound generic, specifically one of type T extends Number. The reason for this is that Number is the parent class to all of the numeric wrapper classes, as well as BigDecimal and BigInteger.

There's two things you'd want to be sure of before you did this:

  • Your generic type was bound at the class level. Since we're dealing with a tree, it makes no sense to have non-homogeneous data throughout.
  • You did a math operation according to a specific data type (int, long, or double).

You would then declare your method(s) as such:

public int addAsInteger() {}
public double addAsDouble() {}
public long addAsLong() {}

You'd make use of Number's methods: intValue, longValue and doubleValue for your respective methods.

You wouldn't be able to simply return T since you can't guarantee what kind of Number you're getting back, or what T is specifically bound to (it can't be Number since it's an abstract class, so it is a non-inclusive upper bound).

Makoto
  • 104,088
  • 27
  • 192
  • 230
  • Nit: `T` can definitely be bound to `Number`. Generics aren't limited to concrete types at runtime. Not sure what a "non-inclusive upper bound" means here. Any type `T` is considered to be a subtype of itself. – Matt Ball May 15 '15 at 00:46
  • If you could share a type-safe example that demonstrates this, that'd be amazing (and I'd be duly impressed). In working with `Number`, I know that there's no properties attached to the abstract class to describe what kind of number representation lies under the covers. Since we're only working with `Number` at the method level, how could we possibly determine which one to return? – Makoto May 15 '15 at 00:49
  • I stated "non-inclusive upper bound" because you can't instantiate a `Number`. You also can't use any information about where that `Number` came from without running into unchecked casts and potentially corrupting the original class that it originated from. – Makoto May 15 '15 at 00:52