Anyone care to shed some light?
I'll take a shot at this.
There are a couple of issues causing confusion I think: using interfaces in general, the use of "new" with interfaces, and the specific interfaces in the
JDBC code.
In the example Test and TestServlet, there are three interfaces that have objects created:
<snip>
I can see that you aren't instantiating an object of the interface with new, which doesn't work because interfaces are abstract. However, you still have an object of this interface, so that's a little weird.
<snip>
...not working with direct "objects" of a interface, which I didn't think you could have...
In Java there's no such thing as an "object of an interface" or suchlike. Objects are instances of classes. Now it's possible that a given class may implement any number of interfaces. If you create an object of such a class, you have just that -- an object that is of the type of that class.
Reference variables in Java can, however, have the type of a either a class or an interface. A reference variable whose type is that of a class points to an object that is an instance of that class (or to an instance of a subclass of that class, or to null). A reference variable whose type is that of an interface points to an object that is an instance of a class that implements that interface (or to an instance of a subclass of that class, or to null).
Take an example from the Java API. Here's the signature for the class ArrayList.
public class ArrayList extends AbstractList implements List, Cloneable,
java.io.Serializable
One way of creating an ArrayList object is like this:
ArrayList myStuff = new ArrayList() ;
Here myStuff is a reference variable of type "ArrayList" and it points to an object that is an instance of the class "ArrayList".
Another way of creating an ArrayList object is like this:
List myStuff = new ArrayList() ;
Here myStuff is a reference variable of type "List" (which is an interface) and it points to an object that is an instance of the class "ArrayList," which implements the List interface. The object is still an ArrayList, but we can get to it only through methods defined in List. (The code that gets executed is the code that's defined in the class for the actual type of the object.)
You can do this sort of thing because, as you can see from the definition of ArrayList, it implements the interface List, which means that it has implementations of all the methods called for by the List interface. (See previous discussions on interfaces and casting.)
Now, the next question is
why would you want to do this sort of thing. In general it's because you need an object that does what a List does but you don't particularly care what specific class the object is that will get the job done, you care only that the object fulfills the contract spelled out in the List interface.
(Maybe you'll later need to change the code to use a LinkedList instead of an ArrayList. Maybe you're sending myStuff to a method that takes any List as a parameter. Etc.)
Note you could also get instances of ArrayList with references of type Cloneable or Serializable, if you had a need for that:
Cloneable c = new ArrayList() ;
Serializable s = new ArrayList() ;
Now on to the use of the "new" keyword with interfaces.
Consider the following interface. Ignore that it doesn't have any methods.
interface Michael
{
}
Consider the following two lines of code. What's the difference?
Michael m = new Michael() ;
Michael mm = new Michael() {} ;
Consider them again for a second (it's a bit of a trick question).
The trick is that the first line is not valid Java code and the second is, but it does something that may be surprising, depending on your comfort level with interfaces.
The first line declares a reference variable m of type "Michael" -- which is perfectly OK. But you get into trouble with new Michael() because "Michael" is an interface. By definition, you can't create an instance of an interface. The compiler shrieks:
C:\Michael\javaranch\projects\Interfaces\TestMichael.java:10: Michael is abstract; cannot be instantiated
Michael m = new Michael() ;
^
1 error
Tool completed with exit code 1
The second line also declares a reference variable (mm) of type "Michael" -- again, which is perfectly OK. Then there's the cryptic part
new Michael() {} ;
This is a special syntax that Java supports for creating anonymous classes that implement (a single?) interface. This code does two things: (1) it defines an anonymous class "on the fly," so to speak, that extends Object and implements Michael, and (2) it creates an object that is an instance of that class. (Then in our case points the reference variable mm to that object.)
You can think of the code
Michael mm = new Michael() {} ;
as getting compiled to something like
private class
AnonymousClass extends Object implements Michael
{
}
Michael mm = new AnonymousClass() ;
Only you don't have the clutter of introducing a new class name in the anonymous version.
If you run this example you can see what I'm talking about:
Compiling this example results in 3 class files, 2 of which are "anonymous" within Java source code:
TestMichael.class
TestMichael$1.class
TestMichael$2.class
And running this example gives the following expected results:
TestMichael$1
TestMichael$2
Note that in the code at (1) you still have the handle "mm" in the scope of the main() method, so you can further manipulate this object if you want. However, at (2) when you define your anonymous subclass of Object that implements Michael, create an instance, and pass it as a parameter to perform() all in one shot, there's no longer any way of getting to that object within main().
I think you mentioned at some point, Jason, that you're familiar with using AWT and event interfaces. My code above at (2) is doing the same kind of thing as
I hope all this didn't muddy the waters too much. The point of it all is that there does exist a very specialized use of "new" with interfaces. But that doesn't change the fact that objects are instances of classes (or that reference variables have the type of either classes or interfaces.) When you wrote the bit about using new versus not using new and class versus interfaces, I wasn't sure that you had it all straight.
Now, on to the JDBC stuff.
I've installed mySQL and looked at the JDBC assignments, but haven't started working on them yet, so everything I'm about to write is just what I've surmised from looking at the API and source code.
Yes, Connection, Statement, and ResultSet are all interfaces. The reference variables con, statement, and rs are of type Connection, Statement, and ResultSet, respectively. (Remember, reference variables can have the type of an interface.) con points to an object that is an instance of a class that implements Connection. statement points to an object that is an instance of a class that implements Statement. rs points to an object that is an instance of a class that implements ResultSet.
What are the classes of these objects? To a certain degree, as a client of these classes, why should you care? (Yeah, I know as students of the language we're interested in such things.)
That's the beauty of interfaces. When you call DriverManager.getConnection( "jdbc:mysql://localhost/soup" ), it returns some object that is an instance of some class that implements the Connection interface. In a sense that's all you need to know to use it. You can then assign that object to con, and then call any method defined in the Connection interface on that object. The Connection interface defines a method Statement createStatement(). When you call con.createStatement() the code that gets executed is from con's class (whatever that may be) (if con's class directly implements Connection). createStatement() returns some object that is an instance of some class that implements the Statement interface. Etc.
If you're curious as to the exact class of these objects, just add the following code:
System.out.println( con.getClass().getName() ) ;
System.out.println( statement.getClass().getName() ) ;
System.out.println( rs.getClass().getName() ) ;
I'm taking a little shot in the dark here, but I think what you'll get is that con is of an an anonymous class in the org.gjt.mm.mysql package.
DriverManager maintains a Vector (think ArrayList) of objects that implement the Driver interface:
(Line 554 of DriverManager.java

private static java.util.Vector drivers = new java.util.Vector();
This, presumably, is a list of all the drivers that have loaded themselves and registered themselves with DriverManager by calling DriverManager.registerDriver( this ) somewhere in their code.
When you call DriverManager.getConnection( "jdbc:mysql://localhost/soup" ) eventually the private method getConnection() defined at line 488 gets called. Lines 506-521 -- cycle through the Vector looking to see if the
String you passed in represents a registered driver. If so, it calls connect() on that driver and the driver returns an object that is an instance of a class that implements Connection.
What kind of stuff are you importing into this program. I think you'll find all your mystery objects in the stuff that sets up the mySQL drivers.
I hope I haven't added to the confusion.