Cách tốt để đóng gói Integer.parseInt ()


92

Tôi có một dự án mà chúng tôi thường sử dụng Integer.parseInt()để chuyển đổi một Chuỗi thành một int. Khi có sự cố xảy ra (ví dụ: Stringkhông phải là số mà là chữ cái a, hoặc bất cứ điều gì), phương thức này sẽ đưa ra một ngoại lệ. Tuy nhiên, nếu tôi phải xử lý các ngoại lệ trong mã của mình ở mọi nơi, điều này bắt đầu trông rất xấu rất nhanh. Tôi muốn đặt điều này trong một phương pháp, tuy nhiên, tôi không có manh mối nào về cách trả lại giá trị sạch để cho thấy rằng chuyển đổi đã xảy ra sai sót.

Trong C ++, tôi có thể đã tạo một phương thức chấp nhận một con trỏ tới một int và để chính phương thức đó trả về true hoặc false. Tuy nhiên, theo như tôi biết, điều này là không thể trong Java. Tôi cũng có thể tạo một đối tượng có chứa biến true / false và giá trị được chuyển đổi, nhưng điều này có vẻ không lý tưởng. Điều tương tự cũng xảy ra đối với giá trị toàn cầu và điều này có thể gây cho tôi một số rắc rối với đa luồng.

Vì vậy, có một cách sạch sẽ để làm điều này?


Các nhân vật trong chuỗi tất cả phải số thập phân chữ số, ngoại trừ các ký tự đầu tiên ... . Thay vì xử lý các ngoại lệ ở mọi nơi trong mã, chỉ cần kiểm tra định dạng chuỗi trước khi gọi phương thức phân tích cú pháp.
Lightman

Tiếp theo là không thể viết một regex sẽ nắm bắt tất cả các số nguyên có dấu 32-bit hợp lệ và không có số nào không hợp lệ. 2147483647 là hợp pháp inttrong khi 2147483648 thì không.
Seva Alekseyev

Câu trả lời:


142

Bạn có thể trả về một Integerthay vì một int, trả về khi nullphân tích cú pháp thất bại.

Thật tiếc khi Java không cung cấp cách thực hiện điều này mà không có một ngoại lệ nào được đưa ra bên trong - bạn có thể ẩn ngoại lệ (bằng cách bắt nó và trả về null), nhưng nó vẫn có thể là một vấn đề về hiệu suất nếu bạn đang phân tích cú pháp hàng trăm trong số hàng nghìn bit dữ liệu do người dùng cung cấp.

CHỈNH SỬA: Mã cho một phương pháp như vậy:

public static Integer tryParse(String text) {
  try {
    return Integer.parseInt(text);
  } catch (NumberFormatException e) {
    return null;
  }
}

Lưu ý rằng tôi không chắc chắn điều này sẽ làm gì nếu textvô hiệu. Bạn nên xem xét điều đó - nếu nó đại diện cho một lỗi (tức là mã của bạn có thể chuyển một giá trị không hợp lệ, nhưng không bao giờ nên vượt qua null) thì việc ném một ngoại lệ là phù hợp; nếu nó không đại diện cho một lỗi thì bạn có thể chỉ nên trả về null như cách bạn làm cho bất kỳ giá trị không hợp lệ nào khác.

Ban đầu câu trả lời này sử dụng hàm new Integer(String)tạo; nó bây giờ sử dụng Integer.parseIntvà một hoạt động quyền anh; theo cách này, các giá trị nhỏ sẽ được chuyển vào Integercác đối tượng được lưu trong bộ nhớ cache , làm cho nó hiệu quả hơn trong những trường hợp đó.


1
Làm thế nào để giúp đỡ? Trang web cuộc gọi sẽ yêu cầu: <b> temp = tryParse (...); if (temp! = null) {target = temp; } else {thực hiện hành động khôi phục}; </b> với một ngoại lệ có thể ném trong phần khôi phục. Trong công thức ban đầu, trang web cuộc gọi yêu cầu <b> try target = (...). ParseInt; catch (...) {do recovery action} </b> với một ngoại lệ ném tầm thường trong quá trình khôi phục đang được thực hiện bằng cách đơn giản loại bỏ mệnh đề catch. Làm thế nào để giải pháp được đề xuất làm cho điều này trở nên đơn giản hơn để hiểu (nó có một trò ảo thuật) hoặc giảm số lượng mã theo bất kỳ cách nào?
Ira Baxter

15
Nói chung, mã để kiểm tra các nulltham chiếu sẽ sạch hơn so với xử lý các ngoại lệ một cách thường xuyên.
Adam Maras 28/09/09

Nó thậm chí còn gọn gàng hơn để tránh chuyển null làm giá trị nhưng thay vào đó bằng cách nào đó chỉ ra rằng lỗi vi đã xảy ra; ngoại lệ không nên được sử dụng để kiểm soát luồng.
Esko 28/09/09

2
@Steve Kuo: Tại sao? Lợi ích ở đâu? Cả hai đều tạo một Số nguyên mới mỗi lần? Nếu có gì đó, tôi muốn sử dụng Integer.parseInt và để autoboxing xử lý nó, để tận dụng bộ nhớ cache cho các giá trị nhỏ.
Jon Skeet 28/09/09

1
@Vlasec Và không chỉ là Tùy chọn, mà còn là các phiên bản chuyên biệt cho các phiên bản ban đầu, như OptionalInt.
Joshua Taylor

37

Bạn mong đợi hành vi nào khi nó không phải là một con số?

Ví dụ: nếu bạn thường có giá trị mặc định để sử dụng khi đầu vào không phải là số, thì một phương thức như thế này có thể hữu ích:

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

Các phương thức tương tự có thể được viết cho các hành vi mặc định khác nhau khi không thể phân tích cú pháp đầu vào.


29

Trong một số trường hợp, bạn nên xử lý lỗi phân tích cú pháp như các tình huống không nhanh, nhưng trong các trường hợp khác, chẳng hạn như cấu hình ứng dụng, tôi thích xử lý đầu vào bị thiếu với các giá trị mặc định bằng cách sử dụng Apache Commons Lang 3 NumberUtils .

int port = NumberUtils.toInt(properties.getProperty("port"), 8080);

Hầu hết thời gian bạn đã sử dụng dấu phẩy apache trong dự án của mình vì các lý do khác (như StringUtils), điều đó trở nên hữu ích.
Ratata Tata,

16

Để tránh xử lý các ngoại lệ, hãy sử dụng một biểu thức chính quy để đảm bảo bạn có tất cả các chữ số trước:

//Checking for Regular expression that matches digits
if(value.matches("\\d+")) {
     Integer.parseInt(value);
}

Cảm ơn về câu trả lời của bạn. Tôi đã đọc qua hầu hết các câu trả lời trên trang này, cá nhân tôi đã viết giải pháp thử / bắt. tuy nhiên đây là vấn đề của tôi, mặc dù nhỏ, với giải pháp đó. hầu hết các IDE sẽ gặp khó khăn với việc phân tích luồng mã của bạn khi bạn thử / bắt bên trong một vòng lặp. đó là lý do tại sao tôi cần một giải pháp mà không cần thử / bắt.
người chiến thắng n.

4
Hãy cẩn thận. Regex với khớp với một số nguyên bắt đầu bằng 0, sau đó sẽ ném ra một NumberFormatException. Hãy thử cái này ^ (?: [1-9] \ d * | 0) $ từ stackoverflow.com/questions/12018479/…
Goose,

5
Regex cụ thể này sẽ không xử lý các số âm.
Brad Cupit

7
điều này cũng không bao gồm các dãy số đó là ngoài giới hạn số nguyên
Mohammad Yahia

10

Ints.tryParse()trong Ổi . Nó không ném ngoại lệ trên chuỗi không phải số, tuy nhiên nó ném ngoại lệ trên chuỗi null.


4

Sau khi đọc câu trả lời cho câu hỏi, tôi nghĩ rằng việc đóng gói hoặc gói phương thức parseInt là không cần thiết, thậm chí có thể không phải là một ý kiến ​​hay.

Bạn có thể trả về 'null' như Jon đề xuất, nhưng điều đó ít nhiều thay thế một cấu trúc try / catch bằng một dấu kiểm. Chỉ có một chút khác biệt về hành vi nếu bạn 'quên' xử lý lỗi: nếu bạn không nắm bắt được ngoại lệ, sẽ không có phép gán nào và biến bên trái sẽ giữ giá trị cũ. Nếu bạn không kiểm tra null, có thể bạn sẽ bị JVM (NPE) tấn công.

gợi ý của ngáp trông thanh lịch hơn đối với tôi, bởi vì tôi không thích trả về null để báo hiệu một số lỗi hoặc trạng thái đặc biệt. Bây giờ bạn phải kiểm tra sự bình đẳng tham chiếu với một đối tượng được xác định trước, điều đó chỉ ra một vấn đề. Tuy nhiên, như những người khác tranh luận, nếu một lần nữa bạn 'quên' kiểm tra và một Chuỗi không thể phân tích được, chương trình sẽ tiếp tục với int được bao bọc bên trong đối tượng 'ERROR' hoặc 'NULL' của bạn.

Giải pháp của Nikolay thậm chí còn được định hướng đối tượng hơn và sẽ hoạt động với các phương thức phân tích cú pháp từ các lớp trình bao bọc khác. Nhưng cuối cùng, anh ấy chỉ thay thế NumberFormatException bằng một ngoại lệ OperationNotSupported - một lần nữa bạn cần thử / bắt để xử lý các đầu vào không thể phân tích.

Vì vậy, kết luận của tôi là không đóng gói phương thức parseInt đơn giản. Tôi chỉ đóng gói nếu tôi cũng có thể thêm một số xử lý lỗi (phụ thuộc vào ứng dụng).


4

Có thể bạn có thể sử dụng một cái gì đó như thế này:

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ôi thích giải pháp của bạn bằng cách sử dụng mô hình có thể. Rất haskelly;)
rodrigoelp

1
Giải pháp này hiện đang lỗi thời vì có java.util.Optional kể từ Java 8 :)
Vlasec

2

Bạn cũng có thể sao chép hành vi C ++ mà bạn muốn rất đơn giản

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;
    }
}

Bạn sẽ sử dụng phương pháp như vậy:

int[] byRef = new int[1];
boolean result = parseInt("123",byRef);

Sau đó, biến resultđó là true nếu mọi thứ diễn ra suôn sẻ và byRef[0]chứa giá trị được phân tích cú pháp.

Cá nhân tôi, tôi sẽ cố gắng bắt ngoại lệ.


2

Câu trả lời được đưa ra bởi Jon Skeet là tốt, nhưng tôi không thích trả lại một nullđối tượng Integer. Tôi thấy điều này khó hiểu khi sử dụng. Vì Java 8 có một lựa chọn tốt hơn (theo ý kiến ​​của tôi), sử dụng OptionalInt:

public static OptionalInt tryParse(String value) {
 try {
     return OptionalInt.of(Integer.parseInt(value));
  } catch (NumberFormatException e) {
     return OptionalInt.empty();
  }
}

Điều này làm rõ ràng rằng bạn phải xử lý trường hợp không có giá trị nào. Tôi muốn nếu loại chức năng này sẽ được thêm vào thư viện java trong tương lai, nhưng tôi không biết liệu điều đó có bao giờ xảy ra hay không.



1

Java của tôi hơi cũ, nhưng hãy để tôi xem liệu tôi có thể chỉ cho bạn đúng hướng không:

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;
    }

}

Nếu giá trị trả lại của bạn là null, bạn có một giá trị xấu. Nếu không, bạn có một hợp lệ Integer.


OP muốn kết quả chuyển đổi (như một tham chiếu) cộng với một chỉ báo rằng chuyển đổi đã thành công (hay không).
ngáp 28/09/09

1
@yawn: Và một tham chiếu rỗng cung cấp chính xác dấu hiệu đó.
Jon Skeet 28/09/09

@John Skeet: đúng nhưng tôi đọc ý định của anh ấy khác. Anh ấy đã viết một cái gì đó giống như sử dụng một đối tượng trung gian để phân biệt giữa thành công / thất bại + giá trị. Xuất thân từ nền tảng C ++, tôi nghĩ nếu anh ấy muốn sử dụng null (thay vì một đối tượng) thì anh ấy sẽ không đặt câu hỏi ngay từ đầu.
ngáp 28/09/09

Có một sự khác biệt lớn giữa "giá trị" và "đối tượng". Tham chiếu null là một giá trị sạch, nhưng không phải là một đối tượng.
Jon Skeet 28/09/09

1. Không có Integer.tryParsetrong Integerlớp Java tiêu chuẩn . 2. Việc làm new Integernày là không cần thiết (và được khuyến nghị không nên làm) vì Java thực hiện quyền anh và mở hộp tự động. Java của bạn không chỉ bị gỉ một chút mà còn rất gỉ.
ADTC

1

Còn về việc tạo phương thức parseInt ?

Thật dễ dàng, chỉ cần sao chép và dán nội dung vào một tiện ích mới trả về Integerhoặc Optional<Integer>và thay thế ném bằng trả về. Có vẻ như không có ngoại lệ trong mã cơ bản, nhưng hãy kiểm tra tốt hơn .

Bằng cách bỏ qua toàn bộ nội dung xử lý ngoại lệ, bạn có thể tiết kiệm thời gian đối với các đầu vào không hợp lệ. Và phương pháp đã có kể từ JDK 1.0, vì vậy không có khả năng bạn sẽ phải làm gì nhiều để luôn cập nhật nó.


0

Tôi khuyên bạn nên xem xét một phương pháp như

 IntegerUtilities.isValidInteger(String s)

mà sau đó bạn triển khai khi bạn thấy phù hợp. Nếu bạn muốn kết quả được lưu lại - có lẽ vì bạn vẫn sử dụng Integer.parseInt () - bạn có thể sử dụng thủ thuật mảng.

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

nơi bạn đặt kết quả [0] thành giá trị số nguyên được tìm thấy trong quy trình.


0

Điều này hơi giống với giải pháp của 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());
 }

Phương pháp chính trình diễn mã. Một cách khác để triển khai giao diện Trình phân tích cú pháp rõ ràng là chỉ thiết lập "\ D +" từ quá trình xây dựng và không cần thực hiện các phương thức nào.


0

Bạn có thể tự cuộn, nhưng cũng dễ dàng sử dụng StringUtils.isNumeric() phương pháp của commons lang . Nó sử dụng Character.isDigit () để lặp lại từng ký tự trong Chuỗi.


Sau đó, nó sẽ không hoạt động nếu chữ số chứa một số quá lớn. Integer.parseInt ném một ngoại lệ cho các số lớn hơn Integer.MAX_VALUE (tất nhiên là tương tự cho phía âm).
Searles

0

Cách tôi xử lý vấn đề này là đệ quy. Ví dụ khi đọc dữ liệu từ bảng điều khiển:

Java.util.Scanner keyboard = new Java.util.Scanner(System.in);

public int GetMyInt(){
    int ret;
    System.out.print("Give me an Int: ");
    try{
        ret = Integer.parseInt(keyboard.NextLine());

    }
    catch(Exception e){
        System.out.println("\nThere was an error try again.\n");
        ret = GetMyInt();
    }
    return ret;
}

0

Để tránh một ngoại lệ, bạn có thể sử dụng Format.parseObjectphương pháp của Java . Đoạn mã dưới đây về cơ bản là phiên bản đơn giản hóa của lớp IntegerValidator của Apache Common .

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;
}

Bạn có thể sử dụng AtomicInteger hoặc int[]thủ thuật mảng tùy theo sở thích của bạn.

Đây là thử nghiệm của tôi sử dụng nó -

int[] i = new int[1];
Assert.assertTrue(IntUtils.tryParse("123", i));
Assert.assertEquals(123, i[0]);

0

Tôi cũng đang gặp vấn đề tương tự. Đây là một phương thức tôi đã viết để yêu cầu người dùng nhập và không chấp nhận đầu vào trừ khi nó là số nguyên. Xin lưu ý rằng tôi là người mới bắt đầu nên nếu mã không hoạt động như mong đợi, hãy đổ lỗi cho sự thiếu kinh nghiệm của tôi!

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();
}

1
Không sử dụng System.out.println (là một thực tiễn xấu). Vấn đề khi sử dụng nó, là chương trình của bạn sẽ đợi cho đến khi println kết thúc. Cách tiếp cận tốt hơn là sử dụng khung ghi nhật ký.
Omar Hrynkiewicz

0

Đây là câu trả lời cho câu hỏi 8391979, "Liệu java có int.tryparse không đưa ra ngoại lệ cho dữ liệu xấu? [Trùng lặp]" được đóng và liên kết với câu hỏi này.

Chỉnh sửa 2016 08 17: Đã thêm các phương thức ltrimZeroes và gọi chúng trong tryParse (). Không có các số 0 đứng đầu trong chuỗi số có thể cho kết quả sai (xem chú thích trong mã). Hiện tại cũng có phương thức String tĩnh công khai ltrimZeroes (Chuỗi số) hoạt động cho các "số" dương và âm (END Chỉnh sửa)

Dưới đây, bạn tìm thấy một lớp Wrapper (quyền anh) thô sơ cho int với phương thức tryParse () được tối ưu hóa tốc độ cao (tương tự như trong C #), tự phân tích cú pháp chuỗi và nhanh hơn một chút so với Integer.parseInt (String s) từ Java:

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;
    }
}

Chương trình thử nghiệm / ví dụ cho lớp IntBoxSimple:

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());
    }
}

0

Thử với biểu thức chính quy và đối số tham số mặc định

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

nếu bạn đang sử dụng apache.commons.lang3 thì bằng cách sử dụng NumberUtils :

int testId = NumberUtils.toInt("test", 0);
System.out.print(testId); // 0

0

Tôi muốn đưa vào một đề xuất khác hoạt động nếu một đề xuất cụ thể yêu cầu số nguyên: Chỉ cần sử dụng long và sử dụng Long.MIN_VALUE cho các trường hợp lỗi. Điều này tương tự như cách tiếp cận được sử dụng cho các ký tự trong Reader trong đó Reader.read () trả về một số nguyên trong phạm vi của một ký tự hoặc -1 nếu trình đọc trống.

Đối với Float và Double, NaN có thể được sử dụng theo cách tương tự.

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;
}

0

Xem xét các câu trả lời hiện có, tôi đã sao chép mã nguồn được dán và nâng cao Integer.parseIntđể thực hiện công việc và giải pháp của tôi

  • không sử dụng tính năng thử bắt chậm tiềm ẩn (không giống như Lang 3 NumberUtils ),
  • không sử dụng regexps không thể bắt số lượng quá lớn,
  • tránh đấm bốc (không giống như Guava Ints.tryParse()),
  • không đòi hỏi bất kỳ phân bổ (không giống như int[], Box,OptionalInt ),
  • chấp nhận bất kỳ CharSequencehoặc một phần của nó thay vì toàn bộ String,
  • có thể sử dụng bất kỳ cơ số nào Integer.parseIntcó thể, tức là [2,36],
  • không phụ thuộc vào bất kỳ thư viện nào.

Nhược điểm duy nhất là không có sự khác biệt giữa toIntOfDefault("-1", -1)toIntOrDefault("oops", -1).

public static int toIntOrDefault(CharSequence s, int def) {
    return toIntOrDefault0(s, 0, s.length(), 10, def);
}
public static int toIntOrDefault(CharSequence s, int def, int radix) {
    radixCheck(radix);
    return toIntOrDefault0(s, 0, s.length(), radix, def);
}
public static int toIntOrDefault(CharSequence s, int start, int endExclusive, int def) {
    boundsCheck(start, endExclusive, s.length());
    return toIntOrDefault0(s, start, endExclusive, 10, def);
}
public static int toIntOrDefault(CharSequence s, int start, int endExclusive, int radix, int def) {
    radixCheck(radix);
    boundsCheck(start, endExclusive, s.length());
    return toIntOrDefault0(s, start, endExclusive, radix, def);
}
private static int toIntOrDefault0(CharSequence s, int start, int endExclusive, int radix, int def) {
    if (start == endExclusive) return def; // empty

    boolean negative = false;
    int limit = -Integer.MAX_VALUE;

    char firstChar = s.charAt(start);
    if (firstChar < '0') { // Possible leading "+" or "-"
        if (firstChar == '-') {
            negative = true;
            limit = Integer.MIN_VALUE;
        } else if (firstChar != '+') {
            return def;
        }

        start++;
        // Cannot have lone "+" or "-"
        if (start == endExclusive) return def;
    }
    int multmin = limit / radix;
    int result = 0;
    while (start < endExclusive) {
        // Accumulating negatively avoids surprises near MAX_VALUE
        int digit = Character.digit(s.charAt(start++), radix);
        if (digit < 0 || result < multmin) return def;
        result *= radix;
        if (result < limit + digit) return def;
        result -= digit;
    }
    return negative ? result : -result;
}
private static void radixCheck(int radix) {
    if (radix < Character.MIN_RADIX || radix > Character.MAX_RADIX)
        throw new NumberFormatException(
                "radix=" + radix + " ∉ [" +  Character.MIN_RADIX + "," + Character.MAX_RADIX + "]");
}
private static void boundsCheck(int start, int endExclusive, int len) {
    if (start < 0 || start > len || start > endExclusive)
        throw new IndexOutOfBoundsException("start=" + start + " ∉ [0, min(" + len + ", " + endExclusive + ")]");
    if (endExclusive > len)
        throw new IndexOutOfBoundsException("endExclusive=" + endExclusive + " > s.length=" + len);
}

0

Có thể ai đó đang tìm kiếm một cách tiếp cận chung chung hơn, vì Java 8 có Gói java.util.functioncho phép xác định Chức năng của Nhà cung cấp. Bạn có thể có một hàm lấy nhà cung cấp và giá trị mặc định như sau:

public static <T> T tryGetOrDefault(Supplier<T> supplier, T defaultValue) {
    try {
        return supplier.get();
    } catch (Exception e) {
        return defaultValue;
    }
}

Với chức năng này, bạn có thể thực thi bất kỳ phương thức phân tích cú pháp nào hoặc thậm chí các phương thức khác có thể ném Ngoại lệ trong khi đảm bảo rằng không bao giờ có thể ném Ngoại lệ:

Integer i = tryGetOrDefault(() -> Integer.parseInt(stringValue), 0);
Long l = tryGetOrDefault(() -> Long.parseLong(stringValue), 0l);
Double d = tryGetOrDefault(() -> Double.parseDouble(stringValue), 0d);

-1

Bạn có thể sử dụng Null-Object như sau:

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));

    }

}

Kết quả của main trong ví dụ này là:

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

Bằng cách này, bạn luôn có thể kiểm tra chuyển đổi không thành công nhưng vẫn hoạt động với kết quả dưới dạng phiên bản Số nguyên. Bạn cũng có thể muốn điều chỉnh số NULL đại diện (≠ 0).


Điều gì sẽ xảy ra nếu 'Số nguyên chuỗi' là chữ "0" của Chuỗi? Bạn sẽ không bao giờ biết nếu có đầu vào không hợp lệ.
Bart Kiers

Tôi đoán rằng điều đó phụ thuộc vào việc toán tử == cho hai Số nguyên so sánh các giá trị hoặc tham chiếu. Nếu nó so sánh các giá trị, vấn đề tồn tại. Nếu nó so sánh các tài liệu tham khảo, nó sẽ hoạt động theo cách tương đương với câu trả lời của tôi.
Adam Maras 28/09/09

Tại sao lại ủng hộ? Câu trả lời của tôi là đúng và mang lại lợi thế (hơn null) là bạn luôn xử lý một phiên bản hợp lệ của Integer (thay vì null) giúp bạn không phải đối phó với NPE.
ngáp 28/09/09

Tuy nhiên, việc phân biệt null với số nguyên thực là hữu ích . Bạn nên kiểm tra kết quả về tính vô hiệu, để biết liệu phân tích cú pháp có thành công hay không. Ẩn sau đó và đối tượng có thể sử dụng khác là một công thức cho các vấn đề, IMO.
Jon Skeet

Nhiều phiếu phản đối hơn - thú vị! Vì / tôi là người mới tham gia SO và tất cả các cử tri có thể giải thích cho tôi lý do tại sao không?
ngáp 28/09/09

-1

Bạn không nên sử dụng Ngoại lệ để xác thực các giá trị của mình .

Đối với một ký tự, có một giải pháp đơn giản:

Character.isDigit()

Đối với các giá trị dài hơn, tốt hơn nên sử dụng một số utils. NumberUtils do Apache cung cấp sẽ hoạt động hoàn hảo ở đây:

NumberUtils.isNumber()

Vui lòng kiểm tra https://commons.apache.org/proper/commons-lang/javadocs/api-2.6/org/apache/commons/lang/math/NumberUtils.html


«Kiểm tra xem chuỗi có phải là số Java hợp lệ hay không. Các số hợp lệ bao gồm hệ thập lục phân được đánh dấu bằng bộ định tính 0x, ký hiệu khoa học và các số được đánh dấu bằng bộ định loại loại (ví dụ: 123L). » Đây không phải là thứ có thể được phân tích cú pháp Integer.parseInt.
Miha_x64
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.