This question already has answers here:
What is a NullPointerException, and how do I fix it?
(12个答案)
4年前关闭。
目前有一个Android应用程序的问题,我认为该线程试图在正确实例化之前使用一个对象。
这是我的课程的构造函数:
这是fetch()函数,用于从HTTP响应中检索JSONObject:
最后是get()方法,该方法用于从JSONObject检索字符串:
NullPointerException被“值= stockQuote.getString(key);”引发-有时但并非每次都如此。我认为这是因为它试图在解析HTML响应之前访问stockQuote?
我猜想有一个明显的解决方案,但是我以前从未遇到过这个问题。有任何想法吗?
这样,在
(当然,如果您需要将
您还可以更轻松地测试
(12个答案)
4年前关闭。
目前有一个Android应用程序的问题,我认为该线程试图在正确实例化之前使用一个对象。
这是我的课程的构造函数:
String name;
String price;
String percentChange;
String peRatio;
private String ticker;
private JSONObject stockQuote;
public Stock(String ticker) {
this.ticker = ticker;
// Build query and URL.
String url = "http://query.yahooapis.com/v1/public/yql?q=";
String query = "select%20*%20from%20yahoo.finance.quotes%20where%20symbol%20in%20(\"" +
ticker +
"\")&env=store://datatables.org/alltableswithkeys&format=json";
url += query;
stockQuote = fetch(url);
name = get("symbol");
price = get("Ask");
}
这是fetch()函数,用于从HTTP响应中检索JSONObject:
private JSONObject fetch(String myurl) throws IOException {
InputStream is = null;
String contentAsString = "";
try {
URL url = new URL(myurl);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setReadTimeout(10000 /* milliseconds */);
conn.setConnectTimeout(15000 /* milliseconds */);
conn.setRequestMethod("GET");
conn.setDoInput(true);
// Starts the query
conn.connect();
int response = conn.getResponseCode();
is = conn.getInputStream();
// Convert the InputStream into a string
contentAsString = readIt(is);
// Makes sure that the InputStream is closed after the app is
// finished using it.
} finally {
if (is != null) {
is.close();
}
}
JSONObject queryResult = null;
try {
JSONObject json = new JSONObject(contentAsString);
queryResult = json.getJSONObject("query").getJSONObject("results").getJSONObject("quote");
} catch (JSONException e) {
System.err.println("Failed to decode JSON");
}
return queryResult;
}
最后是get()方法,该方法用于从JSONObject检索字符串:
public String get(String key) {
String value = null;
try {
value = stockQuote.getString(key);
} catch (JSONException e) {
System.err.println("Couldn't find " + key);
}
return value;
}
NullPointerException被“值= stockQuote.getString(key);”引发-有时但并非每次都如此。我认为这是因为它试图在解析HTML响应之前访问stockQuote?
我猜想有一个明显的解决方案,但是我以前从未遇到过这个问题。有任何想法吗?
最佳答案
我怀疑这里的主要问题是可见性之一,如@shmosel在上面的注释中所述:由于stockQuote
是非最终的,因此不能保证分配的值在构造函数完成后对所有线程都是可见的。使stockQuote
最终应该解决此问题。
我可以建议在这样的构造函数中进行工作是个坏主意吗:它很难测试(Miško Hevery的相关文章很不错),并且您正在构造函数中调用外来方法,不建议这样做(例如,通过Java Concurrency In Practice)。
取而代之的是,您可以将工作(下载代码)移动到静态的工厂方法中,这具有修复竞态条件的其他好处:
public static Stock create(String ticker) {
// Build query and URL.
String url = "http://query.yahooapis.com/v1/public/yql?q=";
String query = "select%20*%20from%20yahoo.finance.quotes%20where%20symbol%20in%20(\"" +
ticker +
"\")&env=store://datatables.org/alltableswithkeys&format=json";
url += query;
JSONObject stockQuote = fetch(url);
return new Stock(ticker, stockQuote);
}
private Stock(String ticker, JSONObject stockQuote) {
this.ticker = ticker;
this.stockQuote = stockQuote;
if (stockQuote == null) throw new NullPointerException();
name = get("symbol");
price = get("Ask");
}
这样,在
Stock
可用之前就不能有stockQuote
的实例,因此调用NullPointerException
时无法获得get
。 (还应将get
设置为final
,这样它也不是外来方法)。(当然,如果您需要将
Stock
子类化,那么这样做就不太容易了。)您还可以更轻松地测试
Stock
类,因为您可以直接注入JSONObject
,而不必下载“真实的”类(如果使构造函数为非私有的)。10-08 03:00