jQuery in Action, 2nd edition*
The moose likes Beginning Java and the fly likes I didn't think you could instantiate an Interface Big Moose Saloon
  Search | Java FAQ | Recent Topics | Flagged Topics | Hot Topics | Zero Replies
Register / Login


Win a copy of Murach's Java Servlets and JSP this week in the Servlets forum!
JavaRanch » Java Forums » Java » Beginning Java
Bookmark "I didn Watch "I didn New topic
Author

I didn't think you could instantiate an Interface

Phil Hopgood
Ranch Hand

Joined: Jul 14, 2008
Posts: 47
Hi All,

Before we start, I have searched on JavaRanch and googled on this topic and it just confused me even more. So I'm sorry if the answer was out there and it passed me by.

With ref to the following from Head 1st Java chap12:



As far as I can see from the API docs Sequencer is an interface in the javax.sound.midi package. MidiSystem.getSequencer() returns a Sequencer which is an interface.

from the API docs:
"public static Sequencer getSequencer()throws MidiUnavailableException
...... The returned Sequencer instance is........."

I didn't think you could instantiate an Interface yet getSequencer()returns me one, how does that work?

Also, I can see that the signature for the open() method is inherited by Sequencer from the MidiDevice interface but the class javax.sound.midi.MidiSystem has no implementation for open() so I'm at a loss to know where that's been implemented.

Similarly setSequence() which is part of the Sequencer interface contract so where is that implemented? and what about all the other methods in the Sequencer interface, where are they implemented?

I'm confused.

Regards and thanks for any light you can shed on this for me....... can't help thinking I'm missing something fundamental here.

Phil.
Jesus Angeles
Ranch Hand

Joined: Feb 26, 2005
Posts: 2049
Yes, there is one and only one thing you are missing.

You are missing - the implementation of the Sequencer interface.

The getSequencer() returns an object (or null) that is an 'implementation' of the Sequencer interface. (In OO speak, it returns 'a Sequencer'.)

Example,

class MyBabySequencer implements Sequencer{
...
...
}

getSequencer() can return MyBabySequencer because MyBabySequencer is an 'implementation' of Sequencer.

open() method is implemented, guess where....., ... yes, in the 'implementation' like below

class MyBabySequencer implements Sequencer{
...
...

...open(){

}
}

I dont have the book at the moment, so I dont know which implementation class was used, or if it is mentioned in the book.

I hope it helps. If it doesnt help, please ignore it, so that you wont be confused.

Another thing, yes, an interface cannot be instantiated.
Steve Luke
Bartender

Joined: Jan 28, 2003
Posts: 4164
    
  21

You can't instantiate an interface, but you can instantiate a class that implements the interface, then reference the implementing class as if it were the interface (which is the power of interfaces).

A common example is the collections framework. We have java.util.List which is an interface. We have a class java.util.ArrayList that implements the java.util.List interface. So we can do this:
List myList = new ArrayList();
Now, as far as the rest of my code is concerned, myList is of the type java.util.List. Down below the code the runtime knows that the ArrayList is there and any time my code calls a method on myList, it executes the method from ArrayList.

For the midi example you provide, the same is true. MidiSystem.getSequencer() is instantiating some class that implements the Sequencer interface. Which specific class it returns isn't important (which is why you get the interface and not a reference to the actual class), but you know that you can use all the methods that Sequencer defines as part of its interface.

I hope this helps.


Steve
Ulf Dittmer
Marshal

Joined: Mar 22, 2005
Posts: 41052
    
  43
The returned Sequencer instance

That's a bit of sloppy language. What it means -as Jesus pointed out- is "The returned object instance -which implements the Sequencer interface- ..."

You can find out the class of the object by calling "sequencer.getClass().getName()". Most likely it's in the "com.sun.*" or "sun.*" hierarchy.


Ping & DNS - my free Android networking tools app
Phil Hopgood
Ranch Hand

Joined: Jul 14, 2008
Posts: 47
Phew, thanks for that guys, I thought I was going mad there for a bit.
Phil Hopgood
Ranch Hand

Joined: Jul 14, 2008
Posts: 47
OK so I now know the returned object instance is com.sun.media.sound.RealTimeSequencer and after a bit of googling I find that this does indeed implement the Sequencer interface, ref: here

...... I almost hesitate to ask this question, why can't I just accept that it returns an object instance that'll do the business! I've just got a fetish for tying up the loose ends I guess.

I can see that com.sun.media.sound.RealTimeSequencer inherits on down from java.lang.Object but if I look at the API docs (not thosein the link) for that I don't see any reference to com.sun.media.sound, etc. so what does com.sun.media.sound mean? Is this some third party, system dependent link class or what?

...... what is docjar anyway?

Regards,
Phil.
Ulf Dittmer
Marshal

Joined: Mar 22, 2005
Posts: 41052
    
  43
I can see that com.sun.media.sound.RealTimeSequencer inherits on down from java.lang.Object but if I look at the API docs (not thosein the link) for that I don't see any reference to com.sun.media.sound, etc. so what does com.sun.media.sound mean? Is this some third party, system dependent link class or what?

I'm not quite sure what you're asking. java.lang.Object can't have any reference to something sound-related - superclasses don't know anything about subclasses.

"com.sun.media.sound" is the package name, just like "java.lang" is a package name. The difference is that anything that starts with "com.sun" is not part of the official Java API (which is comprised of the classes in java.* and javax.*). It's not third-party, really - the "sun" in the name indicates where it originates :-)

There are a number of Java APIs where only the interface classes are part of the public API, but the implementation classes are in some obscure package that is not publicly accessible.

what is docjar anyway?

A useful web site that collects javadocs for all kinds of libraries.
Joanne Neal
Rancher

Joined: Aug 05, 2005
Posts: 3418
    
  12
Originally posted by Phil Hopgood:
...why can't I just accept that it returns an object instance that'll do the business!


By writing the code the way you have, it allows the designer of the MidiSystem class to change the type of the object instance that the getSequencer method returns. As long as the new object still implements the Sequencer interface it won't break your code.
It may be that the method returns different object types depending on certain system properties. On your current system it may return a com.sun.media.sound.RealTimeSequencer, but on another system it may return an object of a different class.

Google for factory pattern for a example of when this could be useful.


Joanne
Phil Hopgood
Ranch Hand

Joined: Jul 14, 2008
Posts: 47
Ulf,


I'm not quite sure what you're asking. java.lang.Object can't have any reference to something sound-related - superclasses don't know anything about subclasses.


I'm confused about what that the com.sun packages are and how they relate to the java API since the documentation on the Sun website for the API doesn't show any relationship to them or not that I've found. There clearly is a link as shown by the docjar website.

From the docjar link that I posted above it showed me the following:

"class: RealTimeSequencer
java.lang.Object
com.sun.media.sound.AbstractMidiDevice
com.sun.media.sound.RealTimeSequencer

All Implemented Interfaces:
Sequencer, AutoConnectSequencer, ReferenceCountingDevice, MidiDevice"

showing me that RealTimeSequencer ultimately inherits from java.lang.Object and also implements the Sequencer interface. Which supports what you said about getSequencer() returning an object instance -which implements the Sequencer interface. So far so good.

So I naively thought that if I looked at the API docs it would show me this hierarchy but it doesn't, or not that I can see.

Are you saying that the com.sun packages are buried in there somewhere but not part of the API and not directly accessible anyway? (I can see that RealTimeSequencer is protected) Are they part of the guts of how some of the java resources do their work under the covers and we don't need to know about that?

The reason that this confuses me so much is that unless the class of the object instance returned by getSequencer() implements the Sequencer interface then it wouldn't have compiled BUT there's nothing in the API documentation to tell me that magically, under the covers, it's returning an instance of com.sun.media.sound.RealTimeSequencer which does implement said interface so how could I have known?

or do I just have to trust that getSequencer() will return an object instance that implements the Sequencer interface with no means of verifying this?

Joanne,
I've been talking about com.sun.media.sound.RealTimeSequencer and I think I understand what you're saying, that what gets returned probably depends on what's installed on any given system and that this is why polymorphism's so great cos you can code it so that you don't care.

So thanks for that Joanne however you opened another can of worms. I don't know anything about "factory patterns". I'll go and research this later but if you do have a good link handy I'd appreciate it.

Thanks to you both so much for listening (as it were) and for all your help. I know it might seem that I'm asking obscure questions and that it's obvious to you but I just seem to have a mental block on this.

Regards,
Phil.

[ August 04, 2008: Message edited by: Phil Hopgood ]
[ August 04, 2008: Message edited by: Phil Hopgood ]
Ulf Dittmer
Marshal

Joined: Mar 22, 2005
Posts: 41052
    
  43
Are you saying that the com.sun packages are buried in there somewhere but not part of the API and not directly accessible anyway?

Yes

Are they part of the guts of how some of the java resources do their work under the covers and we don't need to know about that?

Yes

The reason that this confuses me so much is that unless the class of the object instance returned by getSequencer() implements the Sequencer interface then it wouldn't have compiled BUT there's nothing in the API documentation to tell me that magically, under the covers, it's returning an instance of com.sun.media.sound.RealTimeSequencer which does implement said interface so how could I have known?

You wouldn't know, nor would you need to know. All you (and the Java compiler) need to care about is that the object does in fact implement the Sequencer interface.

To take this a step further, as I mentioned above, there are APIs (notably JDBC) where the JDK does not contain classes that implement the interfaces (like Connection and ResultSet). Those classes are expected to be provided by the database vendors. In that case you could have several classes implementing those interfaces - one for Oracle, one for SQLServer, etc.

or do I just have to trust that getSequencer() will return an object instance that implements the Sequencer interface with no means of verifying this?

You can trust that the call will return an object of a particular type if the javadoc says it does. Anything else would be a major bug, and fixed quickly.
But, actually, you can verify it. If X is the object returned by the call to getSequencer, "X instanceof Sequencer" will tell you whether X implements Sequencer.
[ August 04, 2008: Message edited by: Ulf Dittmer ]
fred rosenberger
lowercase baba
Bartender

Joined: Oct 02, 2003
Posts: 11152
    
  16

Originally posted by Phil Hopgood:
or do I just have to trust that getSequencer() will return an object instance that implements the Sequencer interface with no means of verifying this?

I would say "Yes - that is the whole point." You don't WANT to know the specific object type. if you know exactly what the type is, you may start writing code that DEPENDS on it being that type. If they change the underlying object type, your code is broken.

If you rely solely upon the interface, it won't matter.


There are only two hard things in computer science: cache invalidation, naming things, and off-by-one errors
Rob Spoor
Sheriff

Joined: Oct 27, 2005
Posts: 19649
    
  18

Originally posted by fred rosenberger:

I would say "Yes - that is the whole point." You don't WANT to know the specific object type. if you know exactly what the type is, you may start writing code that DEPENDS on it being that type. If they change the underlying object type, your code is broken.

And believe me, those undocumented classes do tend to change. I know one application that works only with Java 1.4.2_08 - even 1.4.2_10 is not good enough. I read the stack trace and guess what - one of those Sun classes was missing.

This also happens in the API packages. For instance, non-public classes java.io.Win32FileSystem and java.io.WinNTFileSystem have disappeared all of a sudden from Java 5.0 to Java 6. Fortunately, that doesn't matter - they were accessed through java.io.FileSystem#getFileSystem() only anyway, and that returns java.io.FileSystem (in a technique very similar to your first problem in this thread).


Therefore, never ever ever use any class that is not part of the public or protected API. Those will never change, in signature or behaviour (unless they have bugs). For anything else (package visible, private), who knows when it will change or disappear.


SCJP 1.4 - SCJP 6 - SCWCD 5 - OCEEJBD 6
How To Ask Questions How To Answer Questions
Phil Hopgood
Ranch Hand

Joined: Jul 14, 2008
Posts: 47
Thanks to all of you for your responses and patience.

I think I get what you're saying. I totally get what you mean about the use of interfaces and how used in this way it means that you don't care or need to care about which actual class implemented the said interface and that this is what OO and polymorphism is all about.

However from a learner prospective when I saw a piece of code that "looked" like it was trying to instantiate an interface, which I'd just been told you can't do, I tried to find the class that should have been implementing the interface. It looked odd and I had to dig deeper to assure myself that I that I understood what was going on, after all that was the object of the exercise.

I think it was all summed up by Ulf early on in this discussion:
That's a bit of sloppy language. What it means -as Jesus pointed out- is "The returned object instance -which implements the Sequencer interface- ..."

it might have been helpful if they'd added that the class implementing the interface originates from some private internal package and therefore not accessible. I know that the API docs are reference docs and as such those referencing them should be experienced enough to realise what's inferred but when you're a newbie you don't stand a chance.

The trouble with me is that sometimes (not always) I do need to have a detailed understanding of what's going on, I don't like loose ends and worry away at them until I gain enough of an understanding to back off and say "yeah, I know what's happening there and I don't need to delve deeper".

Enough already.

Thanks and regards,
Phil.
Ulf Dittmer
Marshal

Joined: Mar 22, 2005
Posts: 41052
    
  43
Now that you're unconfused, lets' reconfuse you :-) This goes beyond beginner's stuff, by the way.

There's actually a way to create object instances that implement interfaces without having a specific class. The secret are anonymous inner classes, and they look even more like you could actually instantiate an interface (for simplicity's sake we'll use the Runnable interface, which has only a single method):

So the code provides the implementation of the interface right there in the spot. That's useful if you're certain that you don't need this method implementation anywhere else, so there's no point in making a proper class out of it.
Phil Hopgood
Ranch Hand

Joined: Jul 14, 2008
Posts: 47
Hey Ulf,

Yeah, thanks for that! I think I see what you mean, let me paraphrase and see if I've got it right.

You've instantiated an object run (which looks like you've instantiated and interface!) and implemented the one method that the interface Runnable specifies [run()] immediately afterward in the curly brackets. So to utilise the method you use run.run(); in the normal way is that right?

I'm not quite sure why it's called an anonymous inner class though. I can see that the implemented run() is not actually within a class but accessible through the instance run, so I guess that's it. No doubt this is another loose end that I'll need to chase up until my thirst is satisfied. I'm sure that it'll become clearer how this fits into my java armoury when I find an opportunity to use it in anger.

Thanks for gently goading me along the path of enlightenment Ulf, that's just what I need sometimes.

Regards,
Phil
Ulf Dittmer
Marshal

Joined: Mar 22, 2005
Posts: 41052
    
  43
It's anonymous because the class doesn't have a name, and it's an inner class because it's a class defined within another class.

It's also possible to define inner classes that are non-anonymous - because they do have a proper class name, something like this (in which case the inner class would be named "A.B"):
Phil Hopgood
Ranch Hand

Joined: Jul 14, 2008
Posts: 47
I got it at last Ulf, thanks.
 
 
subject: I didn't think you could instantiate an Interface
 
Similar Threads
Need help
What class does my object extend?
java sound using midi
My Midiplayer isn't looping
Application doesn't quit -- MiniMiniMusicApp sample from Head First Java