Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/343.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 封装Integer.parseInt()的好方法_Java_Exception Handling_Encapsulation - Fatal编程技术网

Java 封装Integer.parseInt()的好方法

Java 封装Integer.parseInt()的好方法,java,exception-handling,encapsulation,Java,Exception Handling,Encapsulation,我有一个项目,其中我们经常使用Integer.parseInt()将字符串转换为int。当出现问题时(例如,字符串不是数字而是字母a,或者其他什么),此方法将引发异常。然而,如果我必须处理代码中所有地方的异常,这很快就会变得非常糟糕。我想把它放在一个方法中,但是,我不知道如何返回一个干净的值来显示转换出错 在C++中,我可以创建一个方法,它接受一个int的指针,并让方法本身返回true或false。然而,据我所知,这在Java中是不可能的。我还可以创建一个包含真/假变量和转换值的对象,但这似乎也

我有一个项目,其中我们经常使用
Integer.parseInt()
将字符串转换为int。当出现问题时(例如,
字符串
不是数字而是字母
a
,或者其他什么),此方法将引发异常。然而,如果我必须处理代码中所有地方的异常,这很快就会变得非常糟糕。我想把它放在一个方法中,但是,我不知道如何返回一个干净的值来显示转换出错

在C++中,我可以创建一个方法,它接受一个int的指针,并让方法本身返回true或false。然而,据我所知,这在Java中是不可能的。我还可以创建一个包含真/假变量和转换值的对象,但这似乎也不理想。全局值也是如此,这可能会给多线程带来一些麻烦


那么,有没有一个干净的方法可以做到这一点

您可以返回一个
整数,而不是
int
,在解析失败时返回
null

遗憾的是,Java没有提供一种在没有内部抛出异常的情况下实现这一点的方法——您可以隐藏异常(通过捕获异常并返回null),但是如果您正在解析数十万位用户提供的数据,那么这仍然可能是一个性能问题

编辑:此方法的代码:

public static Integer tryParse(String text) {
  try {
    return Integer.parseInt(text);
  } catch (NumberFormatException e) {
    return null;
  }
}
请注意,如果
text
为空,我不确定这会发生什么。您应该考虑,如果它代表一个bug(即,您的代码可能通过一个无效的值,但不应该传递null),那么抛出一个异常是合适的;如果它不代表bug,那么您可能应该像返回任何其他无效值一样返回null


最初,这个答案使用了
新整数(字符串)
构造函数;它现在使用
Integer.parseInt
和装箱操作;通过这种方式,小值最终会被装箱到缓存的
Integer
对象中,使其在这些情况下更高效。

我的Java有点过时,但让我看看是否可以为您指出正确的方向:

public class Converter {

    public static Integer parseInt(String str) {
        Integer n = null;

        try {
            n = new Integer(Integer.tryParse(str));
        } catch (NumberFormatException ex) {
            // leave n null, the string is invalid
        }

        return n;
    }

}

如果返回值为
null
,则值不正确。否则,您有一个有效的
整数

您可以像这样使用空对象:

public class Convert {

    @SuppressWarnings({"UnnecessaryBoxing"})
    public static final Integer NULL = new Integer(0);

    public static Integer convert(String integer) {

        try {
            return Integer.valueOf(integer);
        } catch (NumberFormatException e) {
            return NULL;
        }

    }

    public static void main(String[] args) {

        Integer a = convert("123");
        System.out.println("a.equals(123) = " + a.equals(123));
        System.out.println("a == NULL " + (a == NULL));

        Integer b = convert("onetwothree");
        System.out.println("b.equals(123) = " + b.equals(123));
        System.out.println("b == NULL " + (b == NULL));

        Integer c = convert("0");
        System.out.println("equals(0) = " + c.equals(0));
        System.out.println("c == NULL " + (c == NULL));

    }

}
本例中的main结果为:

a.equals(123) = true
a == NULL false
b.equals(123) = false
b == NULL true
c.equals(0) = true
c == NULL false

通过这种方式,您可以始终测试转换是否失败,但仍然可以将结果作为整数实例使用。您可能还需要调整NULL表示的数字(≠ 0)。

可能是您可以使用以下内容:

public class Test {
public interface Option<T> {
    T get();

    T getOrElse(T def);

    boolean hasValue();
}

final static class Some<T> implements Option<T> {

    private final T value;

    public Some(T value) {
        this.value = value;
    }

    @Override
    public T get() {
        return value;
    }

    @Override
    public T getOrElse(T def) {
        return value;
    }

    @Override
    public boolean hasValue() {
        return true;
    }
}

final static class None<T> implements Option<T> {

    @Override
    public T get() {
        throw new UnsupportedOperationException();
    }

    @Override
    public T getOrElse(T def) {
        return def;
    }

    @Override
    public boolean hasValue() {
        return false;
    }

}

public static Option<Integer> parseInt(String s) {
    Option<Integer> result = new None<Integer>();
    try {
        Integer value = Integer.parseInt(s);
        result = new Some<Integer>(value);
    } catch (NumberFormatException e) {
    }
    return result;
}

}
公共类测试{
公共接口选项{
T get();
T getOrElse(T def);
布尔值();
}
最后一个静态类是一些实现选项{
私人最终T值;
公共部分(T值){
这个值=值;
}
@凌驾
公共部门得不到{
返回值;
}
@凌驾
公共T getOrElse(T def){
返回值;
}
@凌驾
公共布尔值(){
返回true;
}
}
最后一个静态类None实现选项{
@凌驾
公共部门得不到{
抛出新的UnsupportedOperationException();
}
@凌驾
公共T getOrElse(T def){
返回def;
}
@凌驾
公共布尔值(){
返回false;
}
}
公共静态选项parseInt(字符串s){
选项结果=新无();
试一试{
整数值=整数.parseInt(s);
结果=新的一些(值);
}捕获(数字格式){
}
返回结果;
}
}

> p>您也可以复制非常简单的

C++行为。
public static boolean parseInt(String str, int[] byRef) {
    if(byRef==null) return false;
    try {
       byRef[0] = Integer.parseInt(prop);
       return true;
    } catch (NumberFormatException ex) {
       return false;
    }
}
您可以使用如下方法:

int[] byRef = new int[1];
boolean result = parseInt("123",byRef);
之后,变量
result
如果一切正常并且
byRef[0]
包含解析后的值,则为真


就个人而言,我会坚持捕捉异常。

在阅读了问题的答案后,我认为封装或包装parseInt方法是没有必要的,甚至可能不是一个好主意

您可以按照Jon的建议返回'null',但这或多或少会用null检查替换try/catch构造。如果您“忘记”错误处理,则在行为上只有一点不同:如果您没有捕获异常,则没有赋值,左侧变量将保留它的旧值。如果不测试null,可能会被JVM(NPE)击中

在我看来,yawn的建议更优雅,因为我不喜欢返回null来表示某些错误或异常状态。现在,您必须检查预定义对象的引用相等性,这表明存在问题。但是,正如其他人所说,如果您再次“忘记”检查,并且字符串不可解析,那么程序将继续使用“ERROR”或“NULL”对象中的包装int

Nikolay的解决方案更加面向对象,并且将与来自其他包装器类的parseXXX方法一起工作。但最后,他只是用OperationNotSupported异常替换了NumberFormatException——同样,您需要一个try/catch来处理不可解析的输入


因此,我的结论是不封装普通的parseInt方法。如果我还可以添加一些(依赖于应用程序的)错误处理,我将进行封装。

当它不是一个数字时,您希望它有什么行为

例如,如果在输入不是数字时经常使用默认值,那么这样的方法可能很有用:

public static int parseWithDefault(String number, int defaultVal) {
  try {
    return Integer.parseInt(number);
  } catch (NumberFormatException e) {
    return defaultVal;
  }
}

在输入无法解析的情况下,可以为不同的默认行为编写类似的方法。

< P>我建议您考虑一种类似

的方法。
 IntegerUtilities.isValidInteger(String s)
然后根据您的需要实施。如果希望返回结果(可能是因为您使用了Integer.parseInt()),可以使用数组技巧

 IntegerUtilities.isValidInteger(String s, int[] result)

将结果[0]设置为过程中找到的整数值。

这与Nikolay的解决方案有些相似:

 private static class Box<T> {
  T me;
  public Box() {}
  public T get() { return me; }
  public void set(T fromParse) { me = fromParse; }
 }

 private interface Parser<T> {
  public void setExclusion(String regex);
  public boolean isExcluded(String s);
  public T parse(String s);
 }

 public static <T> boolean parser(Box<T> ref, Parser<T> p, String toParse) {
  if (!p.isExcluded(toParse)) {
   ref.set(p.parse(toParse));
   return true;
  } else return false;
 }

 public static void main(String args[]) {
  Box<Integer> a = new Box<Integer>();
  Parser<Integer> intParser = new Parser<Integer>() {
   String myExclusion;
   public void setExclusion(String regex) {
    myExclusion = regex;
   }
   public boolean isExcluded(String s) {
    return s.matches(myExclusion);
   }
   public Integer parse(String s) {
    return new Integer(s);
   }
  };
  intParser.setExclusion("\\D+");
  if (parser(a,intParser,"123")) System.out.println(a.get());
  if (!parser(a,intParser,"abc")) System.out.println("didn't parse "+a.get());
 }
Character.isDigit()
私有静态c
public static boolean tryParse(String s, int[] result)
{
    NumberFormat format = NumberFormat.getIntegerInstance();
    ParsePosition position = new ParsePosition(0);
    Object parsedValue = format.parseObject(s, position);

    if (position.getErrorIndex() > -1)
    {
        return false;
    }

    if (position.getIndex() < s.length())
    {
        return false;
    }

    result[0] = ((Long) parsedValue).intValue();
    return true;
}
int[] i = new int[1];
Assert.assertTrue(IntUtils.tryParse("123", i));
Assert.assertEquals(123, i[0]);
//Checking for Regular expression that matches digits
if(value.matches("\\d+")) {
     Integer.parseInt(value);
}
int port = NumberUtils.toInt(properties.getProperty("port"), 8080);
private int numberValue(String value, boolean val) throws IOException {
    //prints the value passed by the code implementer
    System.out.println(value);
    //returns 0 is val is passed as false
    Object num = 0;
    while (val) {
        num = br.readLine();
        try {
            Integer numVal = Integer.parseInt((String) num);
            if (numVal instanceof Integer) {
                val = false;
                num = numVal;
            }
        } catch (Exception e) {
            System.out.println("Error. Please input a valid number :-");
        }
    }
    return ((Integer) num).intValue();
}
public class IntBoxSimple {
    // IntBoxSimple - Rudimentary class to implement a C#-like tryParse() method for int
    // A full blown IntBox class implementation can be found in my Github project
    // Copyright (c) 2016, Peter Sulzer, Fürth
    // Program is published under the GNU General Public License (GPL) Version 1 or newer

    protected int _n; // this "boxes" the int value

    // BEGIN The following statements are only executed at the
    // first instantiation of an IntBox (i. e. only once) or
    // already compiled into the code at compile time:
    public static final int MAX_INT_LEN =
            String.valueOf(Integer.MAX_VALUE).length();
    public static final int MIN_INT_LEN =
            String.valueOf(Integer.MIN_VALUE).length();
    public static final int MAX_INT_LASTDEC =
            Integer.parseInt(String.valueOf(Integer.MAX_VALUE).substring(1));
    public static final int MAX_INT_FIRSTDIGIT =
            Integer.parseInt(String.valueOf(Integer.MAX_VALUE).substring(0, 1));
    public static final int MIN_INT_LASTDEC =
            -Integer.parseInt(String.valueOf(Integer.MIN_VALUE).substring(2));
    public static final int MIN_INT_FIRSTDIGIT =
            Integer.parseInt(String.valueOf(Integer.MIN_VALUE).substring(1,2));
    // END The following statements...

    // ltrimZeroes() methods added 2016 08 16 (are required by tryParse() methods)
    public static String ltrimZeroes(String s) {
        if (s.charAt(0) == '-')
            return ltrimZeroesNegative(s);
        else
            return ltrimZeroesPositive(s);
    }
    protected static String ltrimZeroesNegative(String s) {
        int i=1;
        for ( ; s.charAt(i) == '0'; i++);
        return ("-"+s.substring(i));
    }
    protected static String ltrimZeroesPositive(String s) {
        int i=0;
        for ( ; s.charAt(i) == '0'; i++);
        return (s.substring(i));
    }

    public static boolean tryParse(String s,IntBoxSimple intBox) {
        if (intBox == null)
            // intBoxSimple=new IntBoxSimple(); // This doesn't work, as
            // intBoxSimple itself is passed by value and cannot changed
            // for the caller. I. e. "out"-arguments of C# cannot be simulated in Java.
            return false; // so we simply return false
        s=s.trim(); // leading and trailing whitespace is allowed for String s
        int len=s.length();
        int rslt=0, d, dfirst=0, i, j;
        char c=s.charAt(0);
        if (c == '-') {
            if (len > MIN_INT_LEN) { // corrected (added) 2016 08 17
                s = ltrimZeroesNegative(s);
                len = s.length();
            }
            if (len >= MIN_INT_LEN) {
                c = s.charAt(1);
                if (!Character.isDigit(c))
                    return false;
                dfirst = c-'0';
                if (len > MIN_INT_LEN || dfirst > MIN_INT_FIRSTDIGIT)
                    return false;
            }
            for (i = len - 1, j = 1; i >= 2; --i, j *= 10) {
                c = s.charAt(i);
                if (!Character.isDigit(c))
                    return false;
                rslt -= (c-'0')*j;
            }
            if (len < MIN_INT_LEN) {
                c = s.charAt(i);
                if (!Character.isDigit(c))
                    return false;
                rslt -= (c-'0')*j;
            } else {
                if (dfirst >= MIN_INT_FIRSTDIGIT && rslt < MIN_INT_LASTDEC)
                    return false;
                rslt -= dfirst * j;
            }
        } else {
            if (len > MAX_INT_LEN) { // corrected (added) 2016 08 16
                s = ltrimZeroesPositive(s);
                len=s.length();
            }
            if (len >= MAX_INT_LEN) {
                c = s.charAt(0);
                if (!Character.isDigit(c))
                    return false;
                dfirst = c-'0';
                if (len > MAX_INT_LEN || dfirst > MAX_INT_FIRSTDIGIT)
                    return false;
            }
            for (i = len - 1, j = 1; i >= 1; --i, j *= 10) {
                c = s.charAt(i);
                if (!Character.isDigit(c))
                    return false;
                rslt += (c-'0')*j;
            }
            if (len < MAX_INT_LEN) {
                c = s.charAt(i);
                if (!Character.isDigit(c))
                    return false;
                rslt += (c-'0')*j;
            }
            if (dfirst >= MAX_INT_FIRSTDIGIT && rslt > MAX_INT_LASTDEC)
                return false;
            rslt += dfirst*j;
        }
        intBox._n=rslt;
        return true;
    }

    // Get the value stored in an IntBoxSimple:
    public int get_n() {
        return _n;
    }
    public int v() { // alternative shorter version, v for "value"
        return _n;
    }
    // Make objects of IntBoxSimple (needed as constructors are not public):
    public static IntBoxSimple makeIntBoxSimple() {
        return new IntBoxSimple();
    }
    public static IntBoxSimple makeIntBoxSimple(int integerNumber) {
        return new IntBoxSimple(integerNumber);
    }

    // constructors are not public(!=:
    protected IntBoxSimple() {} {
        _n=0; // default value an IntBoxSimple holds
    }
    protected IntBoxSimple(int integerNumber) {
        _n=integerNumber;
    }
}
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
public class IntBoxSimpleTest {
    public static void main (String args[]) {
        IntBoxSimple ibs = IntBoxSimple.makeIntBoxSimple();
        String in = null;
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        do {
            System.out.printf(
                    "Enter an integer number in the range %d to %d:%n",
                        Integer.MIN_VALUE, Integer.MAX_VALUE);
            try { in = br.readLine(); } catch (IOException ex) {}
        } while(! IntBoxSimple.tryParse(in, ibs));
        System.out.printf("The number you have entered was: %d%n", ibs.v());
    }
}
public static int parseIntWithDefault(String str, int defaultInt) {
    return str.matches("-?\\d+") ? Integer.parseInt(str) : defaultInt;
}


int testId = parseIntWithDefault("1001", 0);
System.out.print(testId); // 1001

int testId = parseIntWithDefault("test1001", 0);
System.out.print(testId); // 1001

int testId = parseIntWithDefault("-1001", 0);
System.out.print(testId); // -1001

int testId = parseIntWithDefault("test", 0);
System.out.print(testId); // 0
int testId = NumberUtils.toInt("test", 0);
System.out.print(testId); // 0
public static long parseInteger(String s) {
    try {
        return Integer.parseInt(s);
    } catch (NumberFormatException e) {
        return Long.MIN_VALUE;
    }
}


// ...
long l = parseInteger("ABC");
if (l == Long.MIN_VALUE) {
    // ... error
} else {
    int i = (int) l;
}
Character.isDigit()
NumberUtils.isNumber()