Java parse int method without exception - java

I am searching for a method to check if it is possible to convert a string to int.
The following link says that it is not possible but since new Java version are available I would like to check.

You may wish to consider the NumberUtils.isDigits method from Apache Commons. It gives a boolean answer to the question and is null safe.
For a broader range of numbers that could include decimal points such as float or double, use NumberUtils.isParsable.

It is not a good idea to use exceptions to control flow - they should only be used as exceptions.
This is a classic problem with a regex solution:
class ValidNumber {
// Various simple regexes.
// Signed decimal.
public static final String Numeric = "-?\\d*(.\\d+)?";
// Signed integer.
public static final String Integer = "-?\\d*";
// Unsigned integer.
public static final String PositiveInteger = "\\d*";
// The valid pattern.
final Pattern valid;
public ValidNumber(String validRegex) {
this.valid = Pattern.compile(validRegex);
}
public boolean isValid(String str) {
return valid.matcher(str).matches();
}
}

Java 8 does not change anything by the type parsing. So you still have write your own typeParser like this:
public Integer tryParse(String str) {
Integer retVal;
try {
retVal = Integer.parseInt(str);
} catch (NumberFormatException nfe) {
retVal = 0; // or null if that is your preference
}
return retVal;
}

Related

Way to parseInt without try-catch in Java 8?

Is there a better way to try to convert to int a string that can be or not an integer?
Integer.parseInt(String value) will work well with "25" or "019" but not with "hello" or "8A".
In Java 8, we have optional values, for example:
public static void main(String[] args) {
Optional<Integer> optionalResult = functionThatReturnsOptionalInteger();
Integer finalValue = optionalResult.orElse(0);
System.out.println(finalValue);
}
public static Optional<Integer> functionThatReturnsOptionalInteger() {
Integer[] ints = new Integer[0];
return Stream.of(ints).findAny();
}
You do not need to check nulls, because the Optional wrapper expose useful methods to deal with this kind of situations.
But if you want to parseInt a string, that can be null, or does not contains a valid integer, the solution is the same as always:
public static Integer parseIntOrDefault(String toParse, int defaultValue) {
try {
return Integer.parseInt(toParse);
} catch (NumberFormatException e) {
return defaultValue;
}
}
How can improve this with Java 8 features, why Integer.parseInt() has not been overloaded to return an Optional in case of bad argument? (Or just add a new method Integer.parseIntOptional() to Integer wrapper)
There doesn't exist anything like this in the standard library afaik, but you can write a method that parses a String into an Optional<Integer> like this:
public static Optional<Integer> parseInt(String toParse) {
try {
return Optional.of(Integer.parseInt(toParse));
} catch (NumberFormatException e) {
return Optional.empty();
}
}
Unlike other answers that are now deleted, I don't think this really has to do with Java being backwards-compatible.
Because an empty Optional represents a value that is absent, it would mean that the method actually worked but no results are returned.
However, parsing hello as an integer will not work and has to throw an exception, because it is an error rather than an empty result. Keep in mind that NumberFormatException extends IllegalArgumentException.
More generally speaking, Optional was made for dealing with possibly absent values (instead of using null for that), and not for error handling. Also, Optional doesn't provide any way to know what is the error and why there is one.
I don’t want to speculate why such method does not exist, but if you like neither, perform a pre-test nor catch an exception, you need a re-implementation, e.g.
public static OptionalInt parseInt(String s) {
if(s.isEmpty()) return OptionalInt.empty();
final int len = s.length(), limit;
final boolean negative;
int i = 0;
switch(s.charAt(0)) {
case '-':
i=1;
if(len==1) return OptionalInt.empty();
negative = true;
limit = Integer.MIN_VALUE;
break;
case '+':
i=1;
if(len==1) return OptionalInt.empty();
// fall-through
default:
negative = false;
limit = -Integer.MAX_VALUE;
}
final int limitBeforeMul = limit / 10;
int result = 0;
for(; i < len; i++) {
int digit = Character.digit(s.charAt(i), 10);
if(digit < 0 || result < limitBeforeMul || (result *= 10) < limit + digit)
return OptionalInt.empty();
result -= digit;
}
return OptionalInt.of(negative? result: -result);
}
This basically does the same as Integer.parseInt, but returns an empty OptionalInt for invalid strings instead of throwing an exception…
As you might notice, the hardest part is to handle numbers close to Integer.MIN_VALUE resp. Integer.MAX_VALUE correctly.
Without a try-catch and still returning an Optional - you could do
Optional<Integer> result = Optional.ofNullable(input)
.filter(str -> str.matches("-?\\d+"))
.map(Integer::parseInt);
EDIT: Regex updated to support negative numbers
WARNING: As pointed out in the comments, will still throw a RuntimeException if the parsed String turns out to be outside the range of Integer.MIN_VALUE and Integer.MAX_VALUE
Google's Guava library provides a helper method to do this: Ints.tryParse(String).It runs null when the string is not parsable. You can checkout the documentation.
Using Mutiny it can be written like this.
If you just want to do something with the result you could do it in a single expression
Uni.createFrom()
.item(() -> Integer.parseInt(toParse))
.onFailure().recoverWithItem(defaultValue)
.subscribe().with(i -> System.out.println(i));
Or create a method like the one intended
public static Integer parseIntOrDefault(String toParse, int defaultValue) {
Integer[] toReturn = new Integer[]{null};
Uni.createFrom()
.item(() -> Integer.parseInt(toParse))
.onFailure().recoverWithItem(defaultValue)
.subscribe().with(i -> toReturn[0] = i);
return toReturn[0];
}
This solution adds a library, but the lib is not specific to handle this problem. It uses reactive programing, futures, callbacks and a fluent API and proves to be flexible enough to solve this problem.

Java: Method that returns either String or int

A part of a small program I am coding:
String maxs = "";
int maxi = 0;
At this part I defined two variables as int and String.
public Class(String max){
try {
this.maxi = Integer.parseInt(max);
}catch (Exception e){
this.maxs = max;
}
}
I think this way I will get to define one of both variables, if the String does not parse to int it will be saved as normal String.
Now I need to check what I need to return:
private TypeOfReturn getMax(){
if(this.maxi == 0){
// return maxs (return String)
} else if (this.maxs.equals("")) {
// return maxi (return int)
} else return null;
}
The quastion is, how do I fill the missing parts of the method getMax()?
Is it even possiable in Java?
Use Object instead of TypeOfReturn
You can change the TypeoOfReturn to Object and then return the respective types.
Another way to find out fast if a string is a number or not, which is the main part of your program, is to use the lambda expressions in java 8 like this:
String max = "123";
boolean isNumber = max.chars().allMatch(Character::isDigit);
System.out.println(isNumber);
Which will give you the output
true
Make your TypeOfReturn as String object type and convert the maxi as String and return that String in your else if condition.
Note: you cannot return both the int and String in the Same method.

Reflection improvements to access field secret, when field type is unknown

I am learning about Security and looking at storing secrets in the clear.
When I retrieve the contents of a private field, it returns an Object. My mal code correctly assumes and casts the Object as an int, however if I change/parse the field type from int secretInt = 42; to String secretInt = (new Integer(42).intValue()).tostring the Mal code fails miserably.
EDIT: The unusual wrapping (new Integer(42).intValue()).tostring is created by a automated parser, it is not written by a programmer.
how can I add robustness to Mal code so the assumption of the returned type is removed. Is this possible? I need to use this value as int param.
EDIT: 'String' is one example but the parser may choose a data-structure as suitably-inappropriate as byte[], char[].
This is my non-compliant code.
public final class SecretInClear implements Check4SecretsInClear {
//Non-Compliant: Secret int stored in Clear.
private final int secretInt = 42;
#Override
public boolean isSecretInt(int check) {
return (check == secretInt);
}
}
This is my mal code.
public class ReadClearSecret implements Tester {
//Example of running
public static void main(String[] args) {
String testResult = new ReadClearSecret().test(new SecretInClear());
System.out.println(testResult);
}
private Object readPrivateField(Object o, String fieldName) {
try {
Field field = o.getClass().getDeclaredField(fieldName);
field.setAccessible(true);
return field.get(o);
} catch(Exception e) {
throw new IllegalArgumentExecption(e);
}
#Override
public String test(final Object secretChecks) {
final Check4SecretsInClear check4SecretsInClear = (Check4SecretsInClear)secretChecks;
StringBuilder stringBuilder = new StringBuilder();
stringBuilder.append("class:").
append(check4SecretsInClear.getClass().getSimpleName());
boolean bSecretInt = false;
String s = "";
try {
int secretInt = (Integer)readPrivateField(check4SecretsInClear,"secretInt"); //<<< HERE! It's cast as an integer!!!
bSecretInt = check4SecretsInClear.isSecretInt(secretInt); //<<< HERE! Param must be an int.
} catch (ClassCastException e) {
s = "," + e.getClass().getSimpleName();
} finally {
stringBuilder.append(" int:").append(bSecretInt).append(s);
s = "";
}
return stringBuilder.toString();
}
}
EDIT:
Instead of casting (int) from readPrivateField(). Instead I extract the string value String.valueOf(Object) or Object.toString(). I can then pass that string as a int param with new Integer(stringValue).
HOWEVER: If the parser chooses to represent secretInt as type byte[] the string value will be nuts and the mal code will be pwned. Any suggest to produce robustness against this?
The return type of Field.get() is an Object. If you need to know its class you can call Field.getType() but usually you don't need to know the type, only the information contained.
You could just do
String secret = "42";
or
#Override
public boolean isSecretInt(int check) {
return check / 6.0 == 7;
}
Don't use Integer to compare values, as this compare objects, not their values.
A shorter implementation
private Object readPrivateField(Object o, String fieldName) {
try {
Field field = o.getClass().getDeclaredField(fieldName);
field.setAccessible(true);
return field.get(o);
} catch(Exception e) {
throw new IllegalArgumentExecption(e);
}
}
BTW: "What do you get if you multiply 6 by 9", for those who have read the Hitchhiker's Guide to the Galaxy.
System.out.println(Integer.toString(6 * 9, 13));
prints
42
;)
You can always use:
String value = String.valueOf(field.get(o));
To avoid caring what the type is and always give you a String.
CREDIT: Peter Lawrey
If it is suitably inappropriate you know the answer, it can't be don't generically in code. You need to read the byte code of isSecretInt to see how it is done, and for that a human is the simplest solution ;) –

Is there a way to achieve implicit type cast or conversion in java

I wanted to create a method that takes an enum and uses it directly in an computation
private static int getEntries(List<Integer> vector, Sign sign)
{
//assert isPrimitiveTypeCompliant(vector) : "Vector has null components!";
int entries = 0;
for (Integer entry : vector)
if (entry * sign > 0) // does not compile
entries++;
return entries;
}
I thought sth. like that was possible, since I assumed System.out.println(Object) does implicit type conversion, too. Which it doesn't, it uses following approach:
public void println(Object x) {
String s = String.valueOf(x);
synchronized (this) {
print(s);
newLine();
}
}
public static String valueOf(Object obj) {
return (obj == null) ? "null" : obj.toString();
}
Question
So is it possible to achieve this in java? Or is this reserved to C++ and overloading of operators? What are the common workarounds? Utility/Adapter classes that do the work?
Btw, I eventually ended up with this approach
private enum Sign
{
POSITIVE(+1), NEGATIVE(-1);
private int sign;
private Sign(int sign)
{
this.sign = sign;
}
public int process(int n)
{
if (n * sign > 0)
{
return n;
}
return 0;
}
}
private static int getEntries(List<Integer> vector, Sign sign)
{
//assert isPrimitiveTypeCompliant(vector) : "Vector has null components";
int entries = 0;
for (Integer entry : vector)
entries += sign.process(entry);
return entries;
}
Yes, it is possible to achieve it. In fact, you did in the second piece of code.
Java doesn't have operator overloading or implicit conversions (beyond numerical conversions and "widening" type casts). So, there is no way of allowing syntax like entry * sign (except the one you used).
What do you mean workarounds? This is not a problem. It is a language design decision. And you already arrived successfully to the appropriate Java idiom.
why not just use the int value of the sign
if (entry * sign.value > 0)
enum Sign
public final int value;
I think for this case it would work better for you to use final static variables.
public final class Sign {
public final static int POSITIVE = 1;
public final static int NEGATIVE = -1;
private Sign() {
}
}
Then you can use Sign.POSITIVE and Sign.NEGATIVE for the operations you want.

Convert string to integer- what should I return if string is invalid

If I want to write a function that takes a string and converts it into an integer and I don't trust my input at all, what should I return if the string is invalid. I want to return 0 but would that be confusing since the number might actually be 0? Assume this is for an interview question and you need to check all edge cases.
In Java, it would be conventional to throw an Exception. This is what Integer.parseInt() does, which is the official Java implementation of this functionality.
what should I return if the string is invalid
Throw a RunTimeException. API already does that for you.If your try to parse an invalid string using Integer.parseInt(str) it would throw NumberFormatException at run time.
One possible option is to return default value if string can't be converted to integer. For example:
public int convert(String input, int defaultValue) {
try {
return Integer.parseInt(input);
} catch (Exception e) {
return defaultValue;
}
}

Categories

Resources