我无法在我身边产生空指针异常。但是,我确实从用户那里收到了很多空指针异常崩溃报告。
public static Currency getStockCurrency(PortfolioRealTimeInfo portfolioRealTimeInfo, Code code) {
//////////////////////////////////////////
// Get traded currency in this stock code.
//////////////////////////////////////////
final Currency stockCurrency;
org.yccheok.jstock.engine.currency.Currency c = portfolioRealTimeInfo.currencies.get(code);
if (c == null) {
Country stockCountry = org.yccheok.jstock.engine.Utils.toCountry(code);
stockCurrency = stockCountry.stockCurrency;
} else {
stockCurrency = c;
}
return stockCurrency;
}
public static double getExchangeRate(PortfolioRealTimeInfo portfolioRealTimeInfo, Currency localCurrency, Code code) {
final Currency stockCurrency = getStockCurrency(portfolioRealTimeInfo, code);
return getExchangeRate(portfolioRealTimeInfo, localCurrency, stockCurrency);
}
public static double getExchangeRate(PortfolioRealTimeInfo portfolioRealTimeInfo, Currency localCurrency, Currency stockCurrency) {
// Possible null.
if (localCurrency == null) {
if (stockCurrency.toString().equals("GBX")) {
NPE发生在
行if (stockCurrency.toString().equals("GBX")) {
然而,我不明白
stockCurrency
永远不能为空,因为getStockCurrency
永远不会返回null,因为stockCurrency = stockCountry.stockCurrency;
。 stockCountry
不为null,因为此时不会发生崩溃。 stockCountry
的成员不能为null,因为stockCountry
是一个枚举。我认为没有任何理由可以stockCurrency
为空:https://github.com/yccheok/jstock/blob/master/src/org/yccheok/jstock/engine/Country.java#L29 Currency.valueOf
永远不会返回null。它可能会抛出一些异常。但是,我从未收到过这样的例外:https://github.com/yccheok/jstock/blob/master/src/org/yccheok/jstock/engine/currency/Currency.java#L52 任何想法为什么NPE发生在行
if (stockCurrency.toString().equals("GBX")) {
使用Android 5.0的某些设备可提供更好的异常信息
java.lang.NullPointerException: Attempt to invoke virtual method 'boolean java.lang.String.equals(java.lang.Object)' on a null object reference
at org.yccheok.jstock.portfolio.m.a(SourceFile:244)
at org.yccheok.jstock.portfolio.m.a(SourceFile:272)
at org.yccheok.jstock.gui.portfolio.BuyPortfolioFragment.b(SourceFile:206)
at org.yccheok.jstock.gui.portfolio.BuyPortfolioFragment.b(SourceFile:314)
at org.yccheok.jstock.gui.portfolio.BuyPortfolioFragment.h(SourceFile:841)
at org.yccheok.jstock.gui.portfolio.BuyPortfolioFragment.a(SourceFile:793)
at org.yccheok.jstock.gui.portfolio.fd.a(SourceFile:521)
at org.yccheok.jstock.gui.portfolio.fd.onLoadFinished(SourceFile:488)
at android.support.v4.app.LoaderManagerImpl$LoaderInfo.callOnLoadFinished(SourceFile:427)
at android.support.v4.app.LoaderManagerImpl$LoaderInfo.onLoadComplete(SourceFile:395)
at android.support.v4.a.o.b(SourceFile:104)
at android.support.v4.a.a.b(SourceFile:223)
at android.support.v4.a.b.a(SourceFile:61)
at android.support.v4.a.q.e(SourceFile:461)
at android.support.v4.a.q.c(SourceFile:47)
at android.support.v4.a.w.handleMessage(SourceFile:474)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:145)
at android.app.ActivityThread.main(ActivityThread.java:5944)
at java.lang.reflect.Method.invoke(Native Method)
at java.lang.reflect.Method.invoke(Method.java:372)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1399)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1194)
似乎stockCurrency.toString()
已成功执行,但它返回null。但是,对我来说似乎很奇怪,因为stockCurrency.toString()
不应该假设返回null。 (这是因为Currency
的{{1}}工厂方法不接受空值)
p / s我正在使用ProGuard。但是,我无法想象它是如何导致这次神秘崩溃的。
p / s / s该应用可能会将我的自定义valueOf
混淆为标准Currency
?
答案 0 :(得分:1)
这个问题的原因是,Currency
对象的创建不是通过普通的构造函数或工厂方法完成的。
这是通过Gson序列化完成的。
这是导致这种奇怪行为的因素
Currency
类生成的。Currency
类。因此,如果我们通过以下字符串
对PortfolioRealTimeInfo执行反序列化String data = "{\"currencies\":[[{\"code\":\"4677.KL\"},{\"a\":\"MYR\"}],[{\"code\":\"5247.KL\"},{\"a\":\"MYR\"}],[{\"code\":\"5183.KL\"},{\"a\":\"MYR\"}],[{\"code\":\"6947.KL\"},{\"a\":\"MYR\"}],[{\"code\":\"6742.KL\"},{\"a\":\"MYR\"}]],\"stockPrices\":[[{\"code\":\"4677.KL\"},1.67],[{\"code\":\"5247.KL\"},3.18],[{\"code\":\"6947.KL\"},6.04]],\"exchangeRates\":{},\"exchangeRatesTimestamp\":0,\"stockPricesTimestamp\":1430906678615}";
我们会失败。
请注意,对于{\"a\":\"MYR\"}
,a
是对Currency
currency
成员进行模糊处理的结果。
当我们决定不混淆Currency
时,Gson会帮助"帮助"我们创建一个非空Currency
对象,其成员变量currency
为空。
答案 1 :(得分:0)
这是一个疯狂的猜测,但我认为这是因为在这一行:
UnitedKingdom("/images/16x16/gb.png", "United Kingdom", Currency.newInstance("GBX"), Currency.newInstance("GBP")),
这应该是
UnitedKingdom("/images/16x16/gb.png", "United Kingdom", Currency.newInstance("GBP"), Currency.newInstance("GBP")),
可能是这个
if (stockCurrency.toString().equals("GBX")) {
应该是这个
if (stockCurrency.toString().equals("GBP")) {
但即使不是,我认为您应该为货币设置enum
,并手动指定它们(例如在static {}
初始化程序块中,而不是使用反射。
答案 2 :(得分:0)
stockCurrency.toString()方法返回的字符串返回null,例如尝试添加if条件以确保它不为null,或者如果您正在使用某些日志记录机制尝试记录应该应该的字符串值在返回之前由toString()方法返回,你会发现它返回null。然后从那里开始调试。