java - 获取联系人列表时无法启动活动 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");
}
解决方案
有人能告诉我这个错误是什么意思吗?
您已调用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 应该用于的)。
你可以做两件事:
最有可能是正确的:调查为什么在大火中你的一个数据库行有一个
null
forid
值。这听起来根本不对。如果您想要一个神奇的值来表示一些特殊的东西,请考虑为此保留一个特殊的数字,例如 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));
但是,正如我所说,您更有可能首先更新您的数据库设计,以便在该列中不包含空值。
推荐阅读
- r - 如果单元格包含特定字符串,则复制相邻单元格的字符串
- c# - 动态 where 运算符 c#
- java - android 中 TableRow 的 Harmony OS 中的替代方案是什么?
- powerquery - Power Query - 可以使用 SQL 查询范围吗?
- sql-server - 针对存储过程运行计算机名称列表
- c - 使用 2 scanf("%[^\n]s") 但第二个被跳过
- php - 在 php 中验证字母数字代码并在 SQL 语句中使用它
- google-cloud-platform - GCP GCE 在没有 gcloud 命令的情况下建立跨项目 VM SSH 连接
- angular - ERROR TypeError: control.registerOnChange 不是动态添加组件时的函数
- java - 为什么编译接口后,“javap -v”中的“default”方法修饰符消失了?