【问题标题】:Code skips to finally after HTTPURLConnection connectHTTPURLConnection 连接后代码跳转到 finally
【发布时间】:2016-03-06 16:43:11
【问题描述】:

我正在尝试通过在 Google Udacity 课程中创建电影应用来学习 Android 开发。在我下面的代码中,执行 urlConnection.connect() 后,代码会自动转到 finally 块,没有任何错误/异常。

你能帮我看看我的代码有什么问题吗?谢谢!

    public class FetchMoviesTask extends AsyncTask<Void, Void, String> {

    private final String LOG_TAG = FetchMoviesTask.class.getSimpleName();

    protected String doInBackground(Void... params) {

        String JSONResponse = null;

        //These are declared outside as they'll be used in both try and finally  blocks
        BufferedReader reader = null;
        HttpURLConnection urlConnection = null;

        try {

            //construct your URL from a URI
            Uri.Builder URIbuilder = new Uri.Builder();
            URIbuilder.scheme("http")
                    .authority("api.themoviedb.org")
                    .appendPath("3")
                    .appendPath("movie")
                    .appendPath("popular")
                    .appendQueryParameter("api_key", BuildConfig.TMDB_API_KEY);

            //instantiate URL
            URL popularURL = new URL(URIbuilder.toString());

            Log.v(LOG_TAG, "Built URL: " + popularURL.toString());

            //create and open HTTP connection
            urlConnection = (HttpURLConnection) popularURL.openConnection();
            urlConnection.setRequestMethod("GET");
            urlConnection.connect();

            //InputStream is needed to read the response
            //http://developer.android.com/reference/java/net/HttpURLConnection.html
            InputStream inputStream = urlConnection.getInputStream();
            if (inputStream == null) {
                Log.e(LOG_TAG, "Null input stream");
                return null; //no data returned from HTTP request
            }

            //!!want to see what InputStream looks like
            Log.v(LOG_TAG, "inputStream.toString(): " + inputStream.toString());

            //BufferedReader is used to wrap a Reader and buffer its input
            //to read InputStream, a "reader" is required and that's InputStreamReader (duh)
            //http://developer.android.com/reference/java/io/BufferedReader.html
            reader = new BufferedReader(new InputStreamReader(inputStream));

            //!!want to see what BufferedReader looks like
            Log.v(LOG_TAG, "reader.toString(): " + reader.toString());

            //replaced StringBuffer w/ StringBuilder. will it work?
            StringBuilder builder = new StringBuilder();
            String line;
            while ((line = reader.readLine()) != null) {
                // Since it's JSON, adding a newline isn't necessary (it won't affect parsing)
                // But it does make debugging a *lot* easier if you print out the completed
                // buffer for debugging.
                builder.append(line + "\n");
            }

            if (builder.length() == 0) return null; //empty stream. no point in parsing

            JSONResponse = builder.toString();

            Log.v(LOG_TAG, "JSON Response: " + JSONResponse);

            return parseJSON(JSONResponse);

        } catch (IOException e) {
            Log.e(LOG_TAG, "Error", e);
            return null;
        } catch (JSONException e) {
            Log.e(LOG_TAG, "Error parsing JSON", e);
            return null;
        } catch (Error e) {
            Log.e(LOG_TAG, "Unknown error", e);
        } finally {
            if (urlConnection != null) urlConnection.disconnect();
            if (reader != null) {
                try {
                    reader.close();
                } catch (IOException e) {
                    Log.e(LOG_TAG, "Error closing stream", e);
                }
            }

            //will only be triggered if there's an error getting/parsing data
            return null;
        }

    }

【问题讨论】:

  • 你有任何日志输出吗?
  • 如果 try 中至少有一行代码被执行,则保证执行 finally 块......而不是发生异常。
  • 它可以直接进入 finally 块的唯一条件是 InputStream 为空,但我可以看到一个日志条目
  • "代码自动转到 finally 块" -- 在您的代码中,如果connect() 抛出不是IOExceptionJSONException 或@987654326 的东西,就会发生这种情况@。例如,如果您没有INTERNET 权限,您将获得SecurityException,这些都不是。

标签: java android


【解决方案1】:

CommonsWare 向我指出了问题的可能原因,即缺少 INTERNET 权限。添加它解决了我的问题。感谢大家的回复!

【讨论】:

    【解决方案2】:

    问题在于您的代码中的这条注释:

    //will only be triggered if there's an error getting/parsing data
    

    那是假的。

    如果定义了 finally 块,则不会忽略 try 块中的 return,仅当该 finally 块也包含 return 时。

    换句话说,如果你在tryfinally 中都有“return”,那么finally 中的那个就是被执行的那个。

    来源:Java try-finally return design question

    编辑:
    你可能想看看这个:Does finally always execute in Java?

    【讨论】:

    • 这不应该被回答,但应该被标记为重复,参考您提供的链接。
    • 感谢您的回答——但这不是我的问题。我的问题是在connect()语句之后,它之后的代码被跳过并直接进入finally块,没有提供线索,甚至没有进入catch子句。
    • 您的意思是Log.vs 不显示吗?如果是,你确定URL.connect()节目之前的那些吗?
    • 那你应该澄清你的问题。
    • OP提到的问题发生在这里提到的问题之前。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-01-12
    • 2015-04-08
    • 2014-09-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-10-27
    相关资源
    最近更新 更多