为什么 HttpURLConnection return 的 getInputStream() 方法是一个 RealBufferedSource 类型的对象?

Why does the getInputStream() method of HttpURLConnection return an object of type RealBufferedSource?

我正在尝试使用以下代码从 Android Studio 中的 AsyncTask 发送 HTTP 请求。

protected Long doInBackground(URL... urls) {
    try {
        HttpURLConnection connection = (HttpURLConnection) urls[0].openConnection();
        connection.setRequestMethod("POST");
        connection.connect();

        byte[] loginRequestBytes = new Gson().toJson(loginRequest, LoginRequest.class).getBytes();
        connection.getOutputStream().write(loginRequestBytes);

        if (connection.getResponseCode() == HttpURLConnection.HTTP_OK) {
            ResponseBody responseBody = (ResponseBody) connection.getInputStream(); // ResponseBody extends InputStream
            loginResponse = new Gson().fromJson(responseBody.toString(), LoginResponse.class);
        }
    } catch (IOException e) {
        Log.e("HttpClient", e.getMessage(), e);
    }

    return null;
}

我的 ResponseBody class 扩展了 InputStream,所以我认为使用

ResponseBody responseBody = (ResponseBody) connection.getInputStream();

可以,但问题是:

我在我的代码中得到一个 ClassCastException,因为 connection.getInputStream() returns 一个 com.android.okhttp.okio.RealBufferedSource 类型的对象。为什么 getInputStream 没有按照 Java documentation 返回 InputStream?这是 android 特有的问题吗?

编辑: 我自己定义了 ResponseBody class(如下所示)。据我所知,它 不是 来自 okhttp 的那个,它确实扩展了 InputStream

public class ResponseBody extends InputStream {

    @Override
    public String toString() {
        StringBuilder stringBuilder = new StringBuilder();
        String line;

        try (BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(this, "UTF-8"))) {
            while ((line = bufferedReader.readLine()) != null) {
                stringBuilder.append(line);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }

        return stringBuilder.toString();
    }

    @Override
    public int read() throws IOException {
        return 0;
    }
}

getInputStream() 方法 执行 return 和 InputStream。但是您正试图将结果转换为 ResponseBody。除非结果对象是 ResponseBody 的子类型的实例,否则这将不起作用......它不是。

现在,不清楚您在这里尝试使用哪个 ResponseBody class,但是如果它是 okhttp3.ResponseBody (javadoc),那么您不能通过施放 InputStream 获得它。


I actually defined the ResponseBody class myself. It is a simple extension of InputStream (see edit), so I seems like the downward cast should work

啊。明白了。

不,那行不通。您不能将对象强制转换为它不是的类型。这不是类型转换对引用类型所做的...

你有一个匿名内部的实例class

  com.android.okhttp.okio.RealBufferedSource

它是 InputStream 的子类型。您正在尝试将其转换为 ResponseBody,它也是 InputStream 的子类型。但是 ResponseBody 不是超级 class 或匿名 class 的接口,因此类型转换无法成功。

我建议您将 ResponseBody 重写为 InputStream 的包装器 class 和/或使用此处列出的解决方案之一来提取 [=12= 的内容] 到 String

  • How to read / convert an InputStream into a String in Java?