16

Relatively new Java programmer and I've been taught that you can't create an instance of an abstract class. I've also done a little research and I learned that in most cases when it appears an abstract class is being created, it is actually an anonymous subclass. But here is the issue I ran into:

Java's URL class has a method openConnection that returns a URLConnection. URLConnection is an abstract class, and the Java documentation also lists all of its subclasses as abstract..... so I'm really lost. What's being returned?

Mureinik
  • 297,002
  • 52
  • 306
  • 350
Ausome
  • 203
  • 1
  • 6
  • 7
    A subclass of `URLConnection`, just like you said. – Dave Newton May 01 '15 at 14:04
  • 4
    The concrete class of the returned `URLConnection` is probably marked as `private`. – Colonel Thirty Two May 01 '15 at 14:04
  • Also have a look at http://stackoverflow.com/questions/2793150/using-java-net-urlconnection-to-fire-and-handle-http-requests. – mattias May 01 '15 at 14:04
  • polymorphic concept will apply here. type of the class will be URLConnction and you will return instance of its subclass – Muneeb Nasir May 01 '15 at 14:07
  • 1
    Just for the case: `System.out.println(theConnection.getClass());` will give you the answer (without any explaination of why it's exactly *this* one, of course...) – Marco13 May 01 '15 at 22:36
  • Anonymous classes aren't in the docume9ntation, that may help clear things up. *(Though I think this particular example is actually returning an undocumented implementation. See [this question](http://stackoverflow.com/q/1834826/1858327) for more information on undocumented classes from Sun.)* – Captain Man May 02 '15 at 15:45

6 Answers6

16

What is being returned is a non-abstract subclass that you won't find in the API documentation, for example sun.net.www.protocol.http.HttpUrlConnection. If you run the same code from an applet in a browser, you'll likely get a different one, usually something that wraps the browser's native connections.

So there's no trick and no magic there, just that some classes don't show up in the API docs as they're considered internal to the implementation and subject to change.

There are plenty of similar examples, DocumentBuilderFactory or TransformerFactory are both abstract but their newInstance() method will return a subclass, usually packaged separately (e.g. Saxon).

But there are also different solutions to the same problem: JDBC defines the Driver interface (rather than an abstract class), and a DriverManager utility class with static methods to load the different driver implementations. Instead of extending an abstract class, database driver vendors are required to implement the Driver interface.

By the way, to find the actual runtime class of the object, just call getClass() on them.

biziclop
  • 48,926
  • 12
  • 77
  • 104
  • [This answer](http://stackoverflow.com/a/1834836/1858327) from another question further explains why these classes aren't in the documentation. – Captain Man May 02 '15 at 15:47
14

openConnection returns some concrete class which extendsURLConnection. The method's signature is defined as returning URLConnection since your code using it should not rely on any specific implementation.

Mureinik
  • 297,002
  • 52
  • 306
  • 350
  • 3
    Everything in this answer is correct but I don't think it answers the question about what is actually being returned. – Captain Man May 01 '15 at 17:47
10

Polymorphism concept will apply here.

The type of objects will be the URLConnection(Parent class\interface) and and object will be of its child class(extends or implements( in case of interface)).

Following example might make this thing clear to you.

abstract class URLConnection {
  // some methods. 
}

Let's suppose you have your own class.

class ConnectionClass extends URLConnection {
  // some methods 
} 

class Main {
  URLConnection connect = null

  public URLConnection getUrl() {
    return connect = new ConnectionClass();
  }
}

You will return object of class, who gives implementation of openConnection() of URLConnection class. Same concepts apply in interface case.

Muneeb Nasir
  • 2,414
  • 4
  • 31
  • 54
7

Could be Anonymous Class

Say you have an abstract class...

abstract class Vehicle {
    abstract public void move();
}

Without ever making a class Car extends Vehicle or class Boat extends Vehicle you can do this with the magic of Anonymous Classes. (Which may be why the javadoc does not say there is a subclass because it is anonymous and therefore cannot be referenced by the public api, which the javadoc represents.)

class Example {

    public Vehicle foo() {

        Vehicle car = new Vehicle {
            @Override
            public void move() {
                // do some car movement, i.e. driving
            }
        }

        return car;
    }

    public Vehicle bar() {

        Vehicle boat = new Vehicle {
            @Override
            public void move() {
                // do some boat movement, i.e. boating
            }
        }

        return boat;
    }
}

So no you can't instantiate an abstract class... but that's not really the whole truth, you can do it as an Anonymous Class and implement the methods on the spot. This technically is not instantiating an abstract class though, but it's what gets done a lot when you see this sort of thing.


Could be private Inner Class

Again, say you have an abstract class...

abstract class Vehicle {
    abstract public void move();
}

If the inner class was private then only the class that is encasing it could instantiate it. (Which may be why the javadoc does not say there is a subclass because it is private and therefore hidden from the public api, which the javadoc represents.)

class Example {

    private class Car extends Vehicle {
        @Override
        public void move() {
            // do some car movement, i.e. driving
        }
    }

    private class Boat extends Vehicle {
        @Override
        public void move() {
            // do some boat movement, i.e. boating
        }
    }

    public Vehicle foo() {
        return new Car();
    }

    public Vehicle bar() {
        return new Boat();
    }
}

This doesn't explain anything about instantiating abstract classes, but it may help answer about URL, openConnection, and URLConnection.

Captain Man
  • 6,997
  • 6
  • 48
  • 74
2

It's a class extending URLConnection that is being returned. It's a way of hiding implementation detail as different implementation of URLConnection can be returned depending on the input parameters.

Kai
  • 15,284
  • 6
  • 51
  • 82
1

When all subclasses are abstract, then it's because you can only use the classes by creating it in a factory. If you check carefully the code in Using java.net.URLConnection to fire and handle HTTP requests , you will see that URLConnection object is never instanced. Instead, we get it by calling openConnection like this:

URLConnection connection = new URL(url + "?" + query).openConnection();
Community
  • 1
  • 1
JFPicard
  • 5,029
  • 3
  • 19
  • 43