Search code examples
javacastingurlconnectionupcasting

Confusion regarding upcasting in Java


I am writing a networking code in java and It looks like following:

   //Declaring the reference variable
   HttpsURLConnection httpsURLConnection = null;
   AuthHttpURLConnection authHttpURLConnection = null;

   httpsURLConnection = (HttpsURLConnection) ProxyUrlConnection.openConnection(url);

   httpsURLConnection.setSSLSocketFactory(getSocketFactory());

   authHttpURLConnection = new AuthHttpURLConnection(httpsURLConnection);

I am not the author of ProxyUrlConnection and AuthHttpURLConnection but here is a description of each:

ProxyURLConnection

public class ProxyURLConnection{
public static synchronized URLConnection openConnection(URL url) throws IOException {
    URLConnection urlConnection = null;
    urlConnection = url.openConnection();
    return urlConnection;
    }
... more stuff
}

AuthHttpURLConnection

public class AuthHttpUrlConnection() extends HttpURLConnection{

public AuthHttpURLConnection(HttpURLConnection connection) {
    super(connection.getURL());
    // sets up the auth headers
}

}

And finally HttpURLConnection and HttpsURLConnection

My specific questions:

  1. How am I able to do this casting? openConnection returns an object of URLConnection, how can I do this downcasting and not get any runtime errors?

    (HttpsURLConnection) ProxyUrlConnection.openConnection(url);
    
  2. How is the following implicit upcasting working?

    AuthHttpURLConnection(httpsURLConnection);
    

    I know upcasting is always legal but if I do this then isn't the instance become an object of httpURLConnection instead of httpsURLConnection and once that happen how I am able to call a method setSSLSocketFactory on an object of httpURLConnection since this method is only present in httpsURLConnection?


Solution

  • Generally speaking there are couple of possible runtime flows for the following code :

    
    
    httpsURLConnection = (HttpsURLConnection) ProxyUrlConnection.openConnection(url);
    httpsURLConnection.setSSLSocketFactory(getSocketFactory());
    
    
    1. If the passed url parameter has 'https://' scheme then it should work without any problems.
    2. If the passed url starts with any other scheme (eg. 'http://', 'ftp://') then ProxyUrlConnection.openConnection(url); might return a different implementation of the URLConnection (eg HttpURLConnection, JarURLConnection) then your code will still compile, however, during the application runtime you will get a ClassCastException which will prevent the further execution of the flow (hence coming to your question : setSSLSocketFactory will never be actually called for the other implementations of the URLConnection)

    It is fine to use that snippet as long as you have an explicit validation for the https:// scheme preceding this processing flow, otherwise you have to explicitly deal with the cases when a different implementation of URLConnection is returned to prevent a ClassCastException.

    Long story short :

    How am I able to do this casting? openConnection returns an object of URLConnection, how can I do this downcasting and not get any runtime errors?

    As long you have explicit casting then this code will compile. However, it will fail during the application runtime with ClassCastException if any other implementation of URLConnection is returned except HttpsURLConnection

    How I am able to call a method setSSLSocketFactory on an object of httpURLConnection since this method is only present in httpsURLConnection?

    Application execution flow will fail with ClassCastException prior reaching the setSSLSocketFactory method call if non 'https' URI is provided (see previous point)

    How is the following implicit upcasting working?

    AuthHttpURLConnection(httpsURLConnection); this implicit cast will always work as long as application flow reached this point which would have been insured that the connection is an instance of any subclass of HttpURLConnection otherwise ClassCastException would have been thrown prior to that point (see previous 2 points)

    Hope this helps.