TryParse uses an out parameter. Java doesn't have that. AFAIK, the JVM has no way to represent pointers in any such fashion.
It's sort of ironic that the JVM, with it's limited Java-only bytecode has attracted so many languages, while the CLR, which is designed to handle multiple languages in an efficient manner, has relatively few.
I started to reply that Microsoft could fix that by providing high-performance CLR implementations on all the platforms the JVM runs on.
But it occurred to me that even if they did so, a lot of people wouldn't trust them to continue to support the other platforms indefinitely. The only way around that would be for them to spin off the entire .NET division.
Microsoft being Microsoft, of course, they would never do any of this.
To me it's a huge deal how portable my software is. CLR is very much tied to Windows. I know that there are other implementations but they always lag behind.
As a Java programmer, i agree that the catch blocks around parsing are annoying, but i'm not sure a method that returns an error code is any better. Wasn't that tried back in the '80s?
The way Scala (and probably other functional languages, with which i am not familiar) handle this is with a little bit of polymorphism. Using Java syntax, parsing a string into integer would return a Validation<Integer, Exception>, an abstract type which could be either a Failure<Exception> or Success<Integer>. This then exposes methods like ifSuccess(Consumer<Integer>) (it's called something less obvious in Scala, because that's how Scala works) and ifFailure(Consumer<Exception>), and various other useful things.
This seems a bit weird at first glance, but it makes it quite easy to deal specifically with either success or failure, or both, or to defer dealing with them until later (you can put a load of Validation objects in a set and worry about whether they're successful or failed later on). It also makes it impossible to ignore failure - there is no error code to forget to check, and no unchecked exception to forget to write a catch block for.
Ah apparently I remembered it wrong. I thought it was
int res = int.TryParse(s, 0); // 0 as the default if parsing fails
Of course if there is no reasonable default you should bubble the thing up anyway or handle it on the spot. But very often for input parsing there is sane default you can choose.
if(Int.CanParse(s))
{
i = Int.Parse(s);
// OK things.
}
else
{
// Not ok.
}
but it also be weird in Java because Parse throws and exception, so you'd have to either write an empty catch block or declare the method with a throw clause, event though it actually doesn't throw anything.
That either is inefficient (you end up parsing each number twice) or requires the compiler to have deep knowledge of the standard library.
Similarly, C# has TryGet where in Java, you need a containsKey/get combo, or have to assume your collections do not store nulls.
I do think C# could do better, though. Neither C# nor Java have the equivalent of "insert ... on duplicate key ..." for collections. You now have to do:
items.TryGet( key, out value);
items[key] = value + 1;
Guava's Hints.tryParse is about as good as it can get in Java... Maybe it could return an Optional instead of a nullable boxed type, but the calling code wouldn't be much different.
I'm convinced everytime I have to manually write the try catch clause for parse a kitten dies somewhere!