0

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?

java_doctor_101
  • 3,287
  • 4
  • 46
  • 78
  • Is there a mistake in your description for ProxyUrlConnection? The method signature shows it returns a ProxyUrlConntection but the body is actually returning a URLConnection. – Ishnark Apr 13 '17 at 20:09
  • How do you know that the code hidden behind the comment `//sets up the proxy here` is creating a `URLConnection`, and not some subclass of it? Because `URLConnection` is `abstract`, so it **must** create a subclass. Well, actually, you also do know that it **does** create a subclass of `HttpsURLConnection`, because otherwise the cast would fail. Whether you get a `HttpURLConnection`, `HttpsURLConnection`, or some other subclass depends on the `url` given, e.g. if it started with `ftp://`, you might get an `FtpURLConnection` (if such exists). – Andreas Apr 13 '17 at 20:10
  • 1
    You seem to be confusing *declared* variable/parameter/return type with *actual* object type. Perhaps you should re-read the **inheritance** section of your favorite Java guide. If you don't have a favorite, you might read [The Java™ Tutorials - Inheritance](https://docs.oracle.com/javase/tutorial/java/IandI/subclasses.html). – Andreas Apr 13 '17 at 20:12
  • Note that openConnection() is not returning an object -- it's returning a reference to an object that is an instance of some subclass of URLConnection. If you cast correctly, the cast will work. Otherwise, it will throw an exception. The call to AuthHttpURLConnection() is not a cast, but a call to a constructor. – Andy Thomas Apr 13 '17 at 20:12
  • Thanks for your comments guys. @Ishnark you are right, the return type is URLConnection, a typo. Second Andres, code inside //sets up proxy is basically urlConnection = url.openConnection(proxy); which again return URLConnection object and not any concrete class. Third Andy : isn't this call to constructor same as implicit casting, I am passing a parameter of type HttpsURlConnection and it's being implicity upcasted to HttpUrlConnection? – java_doctor_101 Apr 13 '17 at 21:40
  • @Andreas I think your comment made most sense. I would like to agree with you and actually would like to confirm that upcasting can only work if the object I am casting is actually of the type HttpsUrlConnection. There is definitely some of the implimentation that is hidden from me but that has been my understanding so far and I posted this question more to just confirm if my understanding is correct. Can you please post an answer elaborating my specific question 1 and 2? Thanks! – java_doctor_101 Apr 13 '17 at 21:44

1 Answers1

1

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.

Ruben
  • 761
  • 5
  • 9