6

In Java it is tiring to have to write:

Pair<String, String> pair = new Pair<String, String>("one", "two");

It would be nice if the types were inferred for you so you could at least do this:

Pair<String, String> pair = new Pair("one", "two");

And skip the generic params again.

You can make a static method that can cheat around it like so:

public static <T, S> Pair<T, S> new_(T one, S two) {
    return new Pair<T, S>(one, two);
}

And then use it like: Pair.new_("one", "two").

Is it possible to build the type inferencing into the constructor so that hack can be avoided?

I was thinking of something like:

public <S,T> Pair(S one, T two) {
    this.one = one;
    this.two = two;
}

But then you run into generic type collisions. Does anyone have any thoughts?

jjnguy
  • 136,852
  • 53
  • 295
  • 323
  • That default behavior was actually proposed for JDK 1.7, but I don't think it got included. – JustinKSU Jun 13 '11 at 16:26
  • @Justin, that would have been a nice feature to have. – jjnguy Jun 13 '11 at 16:27
  • Does your IDE not auto-complete that for you? – Yaneeve Jun 13 '11 at 16:27
  • @Yaneeve, could you please elaborate on that question? I don't know what you mean. – jjnguy Jun 13 '11 at 16:29
  • 7
    @JustinKSU It was included in the form of [diamond operator](http://stackoverflow.com/questions/4166966/what-is-the-point-of-the-diamond-operator-in-java-7) – axtavt Jun 13 '11 at 16:31
  • @jjnguy, I meant that when I declare a class such as Pair, and then when I wish to write a new statement, my IDE (intellij, currently, but I remember eclipse doing the same) can complete the statement (after writing the new keyword) with Pair(), after which I just add "one" then "two"... – Yaneeve Jun 13 '11 at 16:38
  • 1
    @Yaneeve, good point. My IDE does auto-complete that. However, it is also more clutter to read. Esp. if you have things like `Map>`. I guess I'd like it better for readability and maintainability in the future. – jjnguy Jun 13 '11 at 16:45
  • Hmm, where did they hide the language specification? http://java.sun.com/docs/books/jls/ does not work anymore, as well as the web site feedback link there. :-/ – Paŭlo Ebermann Jun 13 '11 at 17:03
  • Incidentally, [beware of failure to infer wildcards](http://stackoverflow.com/q/1294227/1968) in this code. – Konrad Rudolph Jun 13 '11 at 17:57
  • On a completely off-topic note, is [this](http://stackoverflow.com/questions/3389264/how-to-get-the-separate-digits-of-an-int-number/4924618#4924618) really you? – Michael Myers Nov 09 '11 at 21:33
  • @Michael, I'm not sure. I never use `toCharArray` in my code...so I'm not sure why I would suggest that. I don't remember writing that, or answering a question I already had the top answer on with a completely different answer. I'm a bit spooked. – jjnguy Nov 09 '11 at 22:54
  • Oh, waffles must have merged the users before you saw it. The user there was called NotJustin and had the same gravatar and a remarkably similar email. The weird thing is that according to your user history, you weren't even going by Justin on February 7. – Michael Myers Nov 09 '11 at 23:00
  • Hmmm, odd. Were there any other answers by that user? – jjnguy Nov 09 '11 at 23:34
  • No, just the one. Doesn't matter now, I guess. Just curious. – Michael Myers Nov 10 '11 at 00:08

5 Answers5

8

It s common to have a helper method which will imply the types for you.

Pair<String, String> pair = Pair.of("one", "two");

then it doesn't seem like such a hack.

It would also be nice if Java had a built in Pair class. ;)

Peter Lawrey
  • 525,659
  • 79
  • 751
  • 1,130
6

In Java 7 you can use the "diamond" operator:

List<String> strings = new ArrayList<>();

Map<String, Int> map = new HashMap<>();

Map<String, List<String>> lolmap = new HashMap<>();
DigitalZebra
  • 39,494
  • 39
  • 114
  • 146
1

The problem is that the declaration of a variable of a particular type, and the instantiation of an object to be referenced by that variable, are two different operations. Strings are generally hard to mistake, but let's say you were setting up pairs of numbers (maybe X-Y coordinates):

Pair<float,float> myCoords = new Pair(3,4);

This brings up a quandary; you're declaring a Pair<float, float>, but assigning an object that would probably be inferred as Pair<int,int>, unless the compiler were given enough intelligence to take the type of the variable being set into account when inferring the instantiated object's generic types (highly unlikely). Java generics, AFAIK, are not covariant, and even if they were, int does not inherit from float. I don't know of a non-duck-typed language that would handle a situation like this correctly.

KeithS
  • 70,210
  • 21
  • 112
  • 164
1

I know it's tiring but that way you ensure type safety of your code. This code is a legal Java code (despite of the warning from the compiler):

import java.util.*;

public class Main {
  public static void main(String[] args) {
    ArrayList a = new ArrayList();
    a.add(1);
    ArrayList<String> b = a;
    System.out.println(b.get(0));
  }
}

But the compiler cannot infer the type now, yet a is assignment compatible with b. Try running it, and a runtime error would occur.

LeleDumbo
  • 9,192
  • 4
  • 24
  • 38
0

I prefer things to be explicit. When things are inferred, they can be inferred incorrectly, or the method can be used incorrectly without any notice because the system infers how to handle the incorrect arguments.

Larry Watanabe
  • 10,126
  • 9
  • 43
  • 46