首页 > 解决方案 > 获取联系人列表时无法启动活动 java.lang.NumberFormatException: s == null。无法定位错误

问题描述

我正在关注有关 Android 开发的教程,其中包含 SQL。该程序是添加和检索所有创建的联系人。当我运行它时,出现了以下错误。

E/AndroidRuntime: FATAL EXCEPTION: main
    Process: com.test.contactmanager, PID: 7147
    java.lang.RuntimeException: Unable to start activity ComponentInfo{com.test.contactmanager/com.test.contactmanager.MainActivity}: java.lang.NumberFormatException: s == null
        at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2778)
        at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2856)
        at android.app.ActivityThread.-wrap11(Unknown Source:0)
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1589)
        at android.os.Handler.dispatchMessage(Handler.java:106)
        at android.os.Looper.loop(Looper.java:164)
        at android.app.ActivityThread.main(ActivityThread.java:6494)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:438)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:807)
     Caused by: java.lang.NumberFormatException: s == null
        at java.lang.Integer.parseInt(Integer.java:570)
        at java.lang.Integer.parseInt(Integer.java:643)
        at com.test.contactmanager.data.DatabaseHandler.getAllContacts(DatabaseHandler.java:132)
        at com.test.contactmanager.MainActivity.onCreate(MainActivity.java:32)
        at android.app.Activity.performCreate(Activity.java:7009)
        at android.app.Activity.performCreate(Activity.java:7000)
        at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1214)
        at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2731)
        at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2856) 
        at android.app.ActivityThread.-wrap11(Unknown Source:0) 
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1589) 
        at android.os.Handler.dispatchMessage(Handler.java:106) 
        at android.os.Looper.loop(Looper.java:164) 
        at android.app.ActivityThread.main(ActivityThread.java:6494) 
        at java.lang.reflect.Method.invoke(Native Method) 
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:438) 
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:807) 

有人能告诉我这个错误是什么意思吗?应该改变什么?我尝试调试但无济于事。阅读后我知道它正在发生,因为 NULL 在某处传递,但在添加第一个联系人时,id 应该为 NULL。如果没有,请告诉我我应该改变什么?

这是我的联系课程

public class Contact {
    //Contains Contact Information of a person
    String name;
    int id;
    String phoneNumber;

    public Contact(String name, int id, String phoneNumber) {
        this.name = name;
        this.id = id;
        this.phoneNumber = phoneNumber;
    }

    public Contact() {
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getPhoneNumber() {
        return phoneNumber;
    }

    public void setPhoneNumber(String phoneNumber) {
        this.phoneNumber = phoneNumber;
    }

}

这是发生问题的函数

主要活动

    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        DatabaseHandler databaseHandler = new DatabaseHandler(MainActivity.this);
        Contact Try2 = new Contact();       

        //Setting attributes of object
        Try2.setName("Try2");
        Try2.setPhoneNumber("01125532553");
        Try2.setId(0);
        //Adding contact
        databaseHandler.addContact(Try2);

        //Displaying contact in Log.d
        List<Contact> contactList = databaseHandler.getAllContacts(); //Error coming at this line
        for(Contact c:contactList)
        {
            Log.d("All_Contacts_Name","onCreate "+ c.getName());
            Log.d("All_Contacts_Number","Contact "+c.getPhoneNumber());
            Log.d("All_Contacts_Id","Contact "+c.getId());
        }

    }

getAllContact() 程序

public List<Contact> getAllContacts()
    {
        List<Contact> contactList = new ArrayList<>();
        SQLiteDatabase db = this.getWritableDatabase();
        String selectAll = "SELECT * FROM "+Util.TABLE_NAME;
        Cursor cursor = db.rawQuery(selectAll,null);

            if(cursor.moveToFirst())
            {
                do{
                    Contact contact = new Contact(); 
                    
                    contact.setId(Integer.parseInt(cursor.getString(0))); //Error coming at this line
                    contact.setName(cursor.getString(1));
                    contact.setPhoneNumber(cursor.getString(2));

                    contactList.add(contact);
                }while (cursor.moveToNext());
            }
        return contactList;
    }

编辑:这是我的 Util 类

public class Util {
    public static final String DATABASE_NAME ="contact_db";
    public static final int DATABASE_VERSION = 1;
    public static final String TABLE_NAME = "contact_table";
    public static final String KEY_ID = "id";
    public static final String KEY_NAME = "name";
}

这是 addContact 函数(用于添加联系人)

    public void addContact(Contact contact)
    {
        SQLiteDatabase db = this.getWritableDatabase(); // "this" means we need to invoke it in *this* class.
                                                        // getWritableDatabase gives us one empty database to work.
        ContentValues values = new ContentValues(); //Stores values for us (Secret tool we will use afterwards in line 65)
        //We will now be extracting values from contact
        values.put(Util.KEY_NAME,contact.getName());
        values.put(Util.KEY_PHONE_NUMBER,contact.getPhoneNumber());

        //Insert a row (it is essentially doing the same thing which onCreate was doing above, maybe).
        db.insert(Util.TABLE_NAME,null,values); //This will give db all the values required. Also, idk what nullColoumnHack is
        db.close(); //Remember kids, if you open dynamic memory then always close it. Not doing this results in memory leak.
        //Log.d("Added_Contacts","Contact Added");
    }

标签: javaandroidandroid-studioruntime-error

解决方案


有人能告诉我这个错误是什么意思吗?

您已调用Integer.parseInt(x),其中 x 计算为null

这发生在该堆栈跟踪中如此标记的行上(因此,第 132 行DatabaseHandler.java,因为那是调用 parseInt 的代码。该 parseInt 然后调用另一个 parseInt 并引发错误)。

通常要读取堆栈跟踪:

  • 首先扫描“由”行,然后跳过所有内容,直到找到最终原因。好吧,略过它,它确实提供了上下文。因此,忘记关于“无法启动活动”的 RuntimeException。这个想法是:发生了一些异常,并且由于该异常,活动无法启动。这是 godo 上下文,但最重要的问题是导致活动无法启动的原因。因此,我们得到了 NumberFormatException。
  • 然后,跳过您未编写的类中的任何方法。所以,跳过 java.lang.Number.parseInt 直到你到达你的 DatabaseHandler.java。这是关键线。

cursor.getString(0)解析为null,您传递给Integer.parseInt,这会导致空指针异常。null表示:“未知、不相关、不适用、未找到”。未知字符串的整数变体是什么?没有办法说,因此,例外。null并不意味着 '0' 或 'blank' - 如果它在你的代码中,更新它,并返回一个实际的 0 或空白(即,如果你曾经写过if (x == null || x.isEmpty()),这强烈表明你已经搞砸了;一旦你null在语义上对待类似于其他一些值,例如在这种情况下,将其视为空字符串,重新设计一些东西,这不是 null 应该用于的)。

你可以做两件事:

  • 最有可能是正确的:调查为什么在大火中你的一个数据库行有一个nullforid值。这听起来根本不对。如果您想要一个神奇的值来表示一些特殊的东西,请考虑为此保留一个特殊的数字,例如 0。当我们这样做时,为什么您的数据库中有跟踪数字的字符串?不应该只有……数字吗?如果有,cursor.getInt(0)也同样有效。.getInt(0)请注意,当您调用时,当 0-index 列中 DB 中的值为 时,会发生什么取决于游标的实现null。它可以抛出同样的 NPE。

  • 而是处理它为空的事实。您可以调用cursor.isNull(0)以检查 FIRST,也可以只获取字符串,而不将其传递给 Integer.parseInt,检查它是否为空,然后采取相应措施。例如:

// instead of:
contact.setId(Integer.parseInt(cursor.getString(0)));

// do:
String rawId = cursor.getString(0);
if (rawId != null) contact.setId(Integer.parseInt(rawId));

但是,正如我所说,您更有可能首先更新您的数据库设计,以便在该列中不包含空值。


推荐阅读