Cara yang baik untuk merangkum Integer.parseInt ()


93

Saya memiliki proyek yang sering kami gunakan Integer.parseInt()untuk mengubah String menjadi int. Ketika terjadi kesalahan (misalnya, Stringbukan angka tetapi huruf a, atau apa pun) metode ini akan mengeluarkan pengecualian. Namun, jika saya harus menangani pengecualian dalam kode saya di mana-mana, ini mulai terlihat sangat jelek dengan sangat cepat. Saya ingin memasukkan ini ke dalam metode, namun, saya tidak tahu cara mengembalikan nilai bersih untuk menunjukkan bahwa konversinya salah.

Di C ++ saya bisa saja membuat metode yang menerima pointer ke int dan membiarkan metode itu sendiri mengembalikan true atau false. Namun, sejauh yang saya tahu, hal ini tidak mungkin dilakukan di Jawa. Saya juga dapat membuat objek yang berisi variabel benar / salah dan nilai yang dikonversi, tetapi ini juga tampaknya tidak ideal. Hal yang sama berlaku untuk nilai global, dan ini mungkin memberi saya masalah dengan multithreading.

Jadi, apakah ada cara yang bersih untuk melakukan ini?


Semua karakter dalam string harus berupa angka desimal, kecuali karakter pertama… . Daripada menangani pengecualian di mana pun dalam kode, cukup periksa format string sebelum memanggil metode parse.
Lightman

Hampir tidak mungkin untuk menulis regex yang akan menangkap semua bilangan bulat bertanda tangan 32-bit yang valid dan tidak ada yang tidak valid. 2147483647 adalah legal intsedangkan 2147483648 tidak.
Seva Alekseyev

Jawaban:


142

Anda bisa mengembalikan, Integerbukan int, mengembalikan jika nullparse gagal.

Sayang sekali Java tidak menyediakan cara untuk melakukan ini tanpa ada pengecualian yang dilemparkan secara internal - Anda dapat menyembunyikan pengecualian (dengan menangkapnya dan mengembalikan nol), tetapi itu masih bisa menjadi masalah kinerja jika Anda mengurai ratusan ribuan bit data yang disediakan pengguna.

EDIT: Kode untuk metode seperti itu:

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

Perhatikan bahwa saya tidak yakin dari atas kepala saya apa yang akan dilakukan jika textnol. Anda harus mempertimbangkan bahwa - jika itu merepresentasikan bug (mis. Kode Anda mungkin memberikan nilai yang tidak valid, tetapi tidak boleh memberikan null) maka memberikan pengecualian adalah tindakan yang tepat; jika itu tidak mewakili bug maka Anda mungkin harus mengembalikan nol seperti yang Anda lakukan untuk nilai tidak valid lainnya.

Awalnya jawaban ini menggunakan new Integer(String)konstruktor; sekarang menggunakan Integer.parseIntdan operasi tinju; dengan cara ini nilai-nilai kecil akan dimasukkan ke dalam kotak ke Integerobjek yang di- cache , membuatnya lebih efisien dalam situasi tersebut.


1
Bagaimana ini membantu? Situs panggilan akan membutuhkan: <b> temp = tryParse (...); if (temp! = Null) {target = temp; } else {lakukan tindakan pemulihan}; </b> dengan kemungkinan pengecualian lemparan di bagian pemulihan. Dalam formulasi asli, situs panggilan memerlukan <b> try target = (...). ParseInt; catch (...) {do recovery action} </b> dengan pengecualian lemparan sepele dalam pemulihan yang sedang diimplementasikan hanya dengan menghapus klausa catch. Bagaimana solusi yang diusulkan membuat ini lebih sederhana untuk dipahami (ini memiliki trik ajaib) atau mengurangi jumlah kode dengan cara apa pun?
Ira Baxter

15
Biasanya lebih bersih kode untuk memeriksa nullreferensi daripada menangani pengecualian secara teratur.
Adam Maras

Bahkan lebih bersih untuk menghindari melewatkan null sebagai nilai tetapi entah bagaimana menunjukkan bahwa kesalahan en telah terjadi; pengecualian tidak boleh digunakan untuk kontrol aliran.
Esko

2
@ Steve Kuo: Mengapa? Dimana manfaatnya? Mereka berdua membuat Integer baru setiap kali? Jika ada, saya tergoda untuk menggunakan Integer.parseInt dan membiarkan autoboxing mengurusnya, untuk memanfaatkan cache untuk nilai-nilai kecil.
Jon Skeet

1
@Vlasec Dan bukan hanya Opsional, tetapi versi khusus untuk primitif, seperti OpsionalInt.
Joshua Taylor

37

Perilaku apa yang Anda harapkan jika itu bukan angka?

Jika, misalnya, Anda sering memiliki nilai default untuk digunakan saat inputnya bukan angka, maka metode seperti ini bisa berguna:

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

Metode serupa dapat ditulis untuk perilaku default yang berbeda ketika input tidak dapat diurai.


29

Dalam beberapa kasus Anda harus menangani kesalahan penguraian sebagai situasi cepat-gagal, tetapi dalam kasus lain, seperti konfigurasi aplikasi, saya lebih suka menangani masukan yang hilang dengan nilai default menggunakan Apache Commons Lang 3 NumberUtils .

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

Sebagian besar waktu Anda sudah menggunakan apache commons dalam proyek Anda karena alasan lain (seperti StringUtils), itu menjadi berguna.
Ratata Tata

16

Untuk menghindari penanganan pengecualian, gunakan ekspresi reguler untuk memastikan Anda memiliki semua digit terlebih dahulu:

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

Terima kasih atas jawaban Anda. Saya membaca sebagian besar jawaban di halaman ini, saya pribadi telah menulis solusi coba / tangkap. namun inilah masalah saya, meskipun kecil, dengan solusi itu. sebagian besar IDE akan tersendat dengan menganalisis aliran kode Anda ketika Anda mencoba / menangkap di dalam loop. itulah mengapa solusi tanpa coba / tangkap adalah apa yang saya butuhkan.
victor n.

4
Hati-hati. Regex dengan kecocokan bilangan bulat yang dimulai dengan 0 yang kemudian akan menampilkan NumberFormatException. Coba ini ^ (?: [1-9] \ d * | 0) $ dari stackoverflow.com/questions/12018479/…
Angsa

5
Regex khusus ini tidak akan menangani angka negatif.
Brad Cupit

7
juga ini tidak mencakup rentang angka yang di luar batas bilangan bulat
Mohammad Yahia

10

Ada Ints.tryParse()di Jambu Biji . Itu tidak melempar pengecualian pada string non-numerik, namun itu melempar pengecualian pada string nol.


4

Setelah membaca jawaban atas pertanyaan, saya pikir mengenkapsulasi atau membungkus metode parseInt tidak perlu, bahkan mungkin bukan ide yang bagus.

Anda dapat mengembalikan 'null' seperti yang disarankan Jon, tetapi itu kurang lebih menggantikan konstruksi coba / tangkap dengan pemeriksaan null. Hanya ada sedikit perbedaan pada perilaku jika Anda 'lupa' menangani kesalahan: jika Anda tidak menangkap pengecualian, tidak ada tugas dan variabel sisi kiri mempertahankan nilai lama. Jika Anda tidak menguji null, Anda mungkin akan terkena JVM (NPE).

saran menguap terlihat lebih elegan bagi saya, karena saya tidak suka mengembalikan nol untuk menandakan beberapa kesalahan atau keadaan luar biasa. Sekarang Anda harus memeriksa persamaan referensial dengan objek yang telah ditentukan sebelumnya, yang mengindikasikan adanya masalah. Tapi, seperti yang dikatakan orang lain, jika lagi Anda 'lupa' untuk memeriksa dan String tidak dapat diuraikan, program akan melanjutkan dengan int yang dibungkus di dalam objek 'ERROR' atau 'NULL' Anda.

Solusi Nikolay bahkan lebih berorientasi objek dan akan bekerja dengan metode parseXXX dari kelas pembungkus lain juga. Tetapi pada akhirnya, dia hanya mengganti NumberFormatException dengan pengecualian OperationNotSupported - sekali lagi Anda perlu mencoba / menangkap untuk menangani masukan yang tidak dapat diuraikan.

Jadi, kesimpulan saya untuk tidak merangkum metode parseInt biasa. Saya hanya akan merangkum jika saya dapat menambahkan beberapa penanganan kesalahan (tergantung aplikasi) juga.


4

Mungkin Anda bisa menggunakan sesuatu seperti ini:

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

}

Saya suka solusi Anda menggunakan pola mungkin. Very haskelly;)
rodrigoelp

1
Solusi ini sekarang sudah usang karena ada java.util.
Opsional

2

Anda juga bisa meniru perilaku C ++ yang Anda inginkan dengan sangat sederhana

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

Anda akan menggunakan metode seperti ini:

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

Setelah itu variabel resultitu benar jika semuanya baik-baik saja dan byRef[0]berisi nilai parsing.

Secara pribadi, saya akan tetap menangkap pengecualian.


2

Jawaban yang diberikan oleh Jon Skeet baik-baik saja, tapi saya tidak suka mengembalikan nullobjek Integer. Saya menemukan ini membingungkan untuk digunakan. Karena Java 8 ada opsi yang lebih baik (menurut saya), menggunakan OptionalInt:

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

Ini membuatnya eksplisit bahwa Anda harus menangani kasus di mana tidak ada nilai yang tersedia. Saya lebih suka jika fungsi semacam ini akan ditambahkan ke perpustakaan java di masa mendatang, tetapi saya tidak tahu apakah itu akan pernah terjadi.



1

Java saya sedikit berkarat, tetapi izinkan saya melihat apakah saya dapat mengarahkan Anda ke arah yang benar:

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

}

Jika nilai pengembalian Anda adalah null, Anda memiliki nilai yang buruk. Jika tidak, Anda memiliki file Integer.


OP menginginkan hasil konversi (sebagai referensi) ditambah indikasi bahwa konversi berhasil (atau tidak).
menguap

1
@yawn: Dan referensi null memberikan indikasi yang tepat.
Jon Skeet

@ John Skeet: benar tetapi saya membaca maksudnya secara berbeda. Dia menulis sesuatu seperti menggunakan objek perantara untuk membedakan antara keberhasilan / kegagalan + nilai. Berasal dari latar belakang C ++ saya pikir jika dia ingin menggunakan null (bukan sebuah objek) dia tidak akan menanyakan pertanyaan itu sejak awal.
menguap

Ada perbedaan besar antara "nilai" dan "objek". Referensi null adalah nilai bersih, tetapi bukan objek.
Jon Skeet

1. Tidak ada Integer.tryParsedi Integerkelas Java standar . 2. Melakukan new Integertidak perlu (dan tidak disarankan) karena Java melakukan tinju dan unboxing secara otomatis. Java Anda tidak hanya sedikit berkarat, tetapi juga sangat berkarat.
ADTC

1

Bagaimana dengan membagi metode parseInt ?

Sangat mudah, cukup salin-tempel konten ke utilitas baru yang mengembalikan Integeratau Optional<Integer>dan ganti lemparan dengan pengembalian. Tampaknya tidak ada pengecualian dalam kode yang mendasarinya, tetapi lebih baik periksa .

Dengan melewatkan seluruh perkecualian penanganan barang, Anda dapat menghemat waktu pada masukan yang tidak valid. Dan metode ini sudah ada sejak JDK 1.0, jadi sepertinya Anda tidak perlu melakukan banyak hal untuk menjaganya agar tetap mutakhir.


0

Saya sarankan Anda mempertimbangkan metode seperti

 IntegerUtilities.isValidInteger(String s)

yang kemudian Anda terapkan sesuai keinginan Anda. Jika Anda ingin hasilnya dibawa kembali - mungkin karena Anda tetap menggunakan Integer.parseInt () - Anda dapat menggunakan trik array.

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

di mana Anda menetapkan hasil [0] ke nilai integer yang ditemukan dalam proses.


0

Ini agak mirip dengan solusi 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());
 }

Metode utama mendemonstrasikan kode. Cara lain untuk mengimplementasikan antarmuka Parser jelas hanya dengan menyetel "\ D +" dari konstruksi, dan metode tersebut tidak melakukan apa pun.


0

Anda bisa menggulung sendiri, tapi itu semudah menggunakan StringUtils.isNumeric() metode commons lang . Ini menggunakan Character.isDigit () untuk mengulangi setiap karakter dalam String.


Maka tidak akan berhasil jika angka tersebut mengandung angka yang terlalu besar. Integer.parseInt membuat pengecualian untuk angka yang lebih besar dari Integer.MAX_VALUE (tentu saja sama untuk sisi negatifnya).
Searles

0

Cara mereka menangani masalah ini secara rekursif. Misalnya saat membaca data dari konsol:

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

Untuk menghindari pengecualian, Anda dapat menggunakan Format.parseObjectmetode Java . Kode di bawah ini pada dasarnya adalah versi sederhana dari kelas IntegerValidator 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;
}

Anda dapat menggunakan AtomicIntegeratau int[]trik array tergantung pada preferensi Anda.

Ini tes saya yang menggunakannya -

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

0

Saya juga mengalami masalah yang sama. Ini adalah metode yang saya tulis untuk meminta input pengguna dan tidak menerima input kecuali integernya. Harap dicatat bahwa saya seorang pemula jadi jika kode tidak berfungsi seperti yang diharapkan, salahkan pengalaman saya!

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
Jangan gunakan System.out.println (adalah praktik yang buruk). Masalah dengan menggunakannya, adalah program Anda akan menunggu sampai println selesai. Pendekatan yang lebih baik adalah dengan menggunakan kerangka kerja logging.
Omar Hrynkiewicz

0

Ini adalah jawaban atas pertanyaan 8391979, "Apakah java memiliki int.tryparse yang tidak memunculkan pengecualian untuk data buruk? [Duplikat]" yang ditutup dan ditautkan ke pertanyaan ini.

Sunting 2016 08 17: Menambahkan metode ltrimZeroes dan memanggilnya di tryParse (). Tanpa nol di depan numberString dapat memberikan hasil yang salah (lihat komentar dalam kode). Sekarang ada juga metode String ltrimZeroes (String numberString) statis publik yang bekerja untuk "bilangan" positif dan negatif (END Edit)

Di bawah ini Anda menemukan kelas Wrapper (tinju) yang belum sempurna untuk int dengan metode tryParse () yang dioptimalkan dengan kecepatan tinggi (mirip seperti di C #) yang mengurai string itu sendiri dan sedikit lebih cepat daripada Integer.parseInt (String s) dari 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;
    }
}

Program uji / contoh untuk kelas 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

Coba dengan ekspresi reguler dan argumen parameter default

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

jika Anda menggunakan apache.commons.lang3 maka dengan menggunakan NumberUtils :

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

0

Saya ingin memasukkan proposal lain yang berfungsi jika seseorang secara khusus meminta bilangan bulat: Cukup gunakan long dan gunakan Long.MIN_VALUE untuk kasus kesalahan. Ini mirip dengan pendekatan yang digunakan untuk karakter di Reader di mana Reader.read () mengembalikan integer dalam rentang karakter atau -1 jika pembaca kosong.

Untuk Float dan Double, NaN dapat digunakan dengan cara serupa.

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

Mempertimbangkan jawaban yang ada, saya telah menyalin dan meningkatkan kode sumber Integer.parseIntuntuk melakukan pekerjaan itu, dan solusi saya

  • tidak menggunakan coba-tangkap yang berpotensi lambat (tidak seperti Lang 3 NumberUtils ),
  • tidak menggunakan regexps yang tidak dapat menangkap angka yang terlalu besar,
  • menghindari tinju (tidak seperti Jambu Ints.tryParse() ),
  • tidak memerlukan alokasi apapun (tidak seperti int[], Box,OptionalInt ),
  • menerima salah CharSequencesatu atau sebagian darinya, bukan keseluruhanString ,
  • dapat menggunakan radix mana saja Integer.parseInt bisa, yaitu [2,36],
  • tidak bergantung pada perpustakaan mana pun.

Satu-satunya kelemahan adalah tidak ada perbedaan antara toIntOfDefault("-1", -1)dan 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

Mungkin seseorang mencari pendekatan yang lebih umum, karena Java 8 ada Paket java.util.functionyang memungkinkan untuk mendefinisikan Fungsi Pemasok. Anda bisa memiliki fungsi yang mengambil pemasok dan nilai default sebagai berikut:

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

Dengan fungsi ini, Anda dapat menjalankan metode parsing apa pun atau bahkan metode lain yang dapat menampilkan Exception sambil memastikan bahwa tidak ada Exception yang dapat dilempar:

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

-1

Anda dapat menggunakan Objek Null seperti ini:

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

    }

}

Hasil dari main dalam contoh ini adalah:

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

Dengan cara ini Anda selalu dapat menguji konversi yang gagal tetapi masih bekerja dengan hasil sebagai instans Integer. Anda mungkin juga ingin mengubah angka yang diwakili oleh NULL (≠ 0).


Bagaimana jika 'String integer' adalah String literal "0"? Anda tidak akan pernah tahu jika ada masukan yang tidak valid.
Bart Kiers

Saya rasa itu tergantung pada apakah operator == untuk dua Integer membandingkan nilai atau referensi. Jika membandingkan nilai, masalahnya ada. Jika membandingkan referensi, itu akan bekerja dengan cara yang setara dengan jawaban saya.
Adam Maras

Mengapa suara negatifnya? Jawaban saya benar dan menawarkan keuntungan (lebih dari nol) bahwa Anda selalu berurusan dengan contoh Integer yang valid (bukan nol) yang membebaskan Anda dari harus berurusan dengan NPE.
menguap

Membedakan null dari integer sebenarnya berguna . Anda harus menguji hasil untuk nullity, untuk mengetahui apakah parse berhasil atau tidak. Menyembunyikan di belakang dan objek yang dapat digunakan adalah resep untuk masalah, IMO.
Jon Skeet

Lebih banyak suara negatif - menarik! Karena / saya baru mengenal SO dan semua bisa salah satu pemilih menjelaskan kepada saya mengapa?
menguap

-1

Anda tidak boleh menggunakan Pengecualian untuk memvalidasi nilai Anda .

Untuk karakter tunggal, ada solusi sederhana:

Character.isDigit()

Untuk nilai yang lebih panjang, lebih baik menggunakan beberapa kegunaan. NumberUtils yang disediakan oleh Apache akan bekerja dengan sempurna di sini:

NumberUtils.isNumber()

Silakan periksa https://commons.apache.org/proper/commons-lang/javadocs/api-2.6/org/apache/commons/lang/math/NumberUtils.html


«Memeriksa apakah String merupakan nomor Java yang valid. Angka yang valid mencakup heksadesimal yang ditandai dengan kualifikasi 0x, notasi ilmiah dan angka-angka yang ditandai dengan kualifikasi jenis (misalnya 123L). » Ini bukan yang bisa diurai Integer.parseInt.
Miha_x64
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.