While learning TTS on Android, I came across the following code snippet:
speakBtn.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View view) {
mTts.speak(words.getText().toString(), TextToSpeech.QUEUE_ADD, null);
}});
I am really new to Java, so my level of confidence in identifying the various constructs isn't that great. I think that I see above is an Anonymous Inner Class but the 'new OnClickListener()' is confusing to me. So please confirm and/or correct any of the following understanding:
The inner class is defined right
after new OnClickListener().
OnClickListener is a super class
from which the inner class is
derived.
The (anonymous) inner class has only
one member function: OnClick().
What is #Override inside the
definition of the inner class? If
this is an annotation, then I am
confused as this answer states
that anonymous inner classes cannot
be annotated.
Lastly, is there a way to write the above snippet in a way that is easier to decipher for a n00b like me?
Yes; it's defined between the braces.
Yes, except that it's an interface, not a class.
Yes.
You cannot add class-level annotations.
#Override is a method-level annotation, which works fine.
Well, basically this snippet of code creates a class which name is mangled by the compiler for your convinience so that you need'nt care about naming it yourself. That class will implement the interface OnClickListener, and contain implementation for the method onClick(View), as the interface requires.
As such, your snippet could be writter some way like this:
class OnClickListenerThingy01 implements OnClickListener { // name is invented from the top of my head and corresponds actual name manging in no way
#Override
public void onClick(View view) {
mTts.speak(words.getText().toString(), TextToSpeech.QUEUE_ADD, null);
}
}
speakBtn.setOnClickListener(new OnClickListenerThingy01());
The #Override annotation is not placed on the class itself - which has no declaration in your code the annotation could be added, being compiler-generated - but on the method.
The #Override annotation is used to mark overrides (how surprising) and method implementations. Its main use is to generate a compiler error if the signature of the overridden method changes, but you fail to update the overriding declaration accordingly, so that you won't get really surprised when you overrides fail to work, because, say, what was overridden was renamed.
In case on an interface implementation, if you forget to implement an interface fully, the compiler will generate an error anyways, so #Override may seem a bit redundant, but it is not. In fact, it is a rather nice thing to have so that unneccessary methods (when for example, a method declaration is removed from an interface) won't stay in your code.
Although it must be noted that an IDE like Eclipse will most probably make these concerns void, as the provided refactoring tools are more than enough to avoid such situtation. Anyways, #Override is quite nice to have on you methods when it may be used.
Here's a way to rewrite your snippet that makes it much clearer "to a noob" :)
class MyOuterClass {
private class MyOnClickListener implements OnClickListener {
#Override
public void onClick(View view) {
mTts.speak(words.getText().toString(), TextToSpeech.QUEUE_ADD, null);
}
}
// later (inside some method)...
speakBtn.setOnClickListener(new MyOnClickListener());
}
The inner class is defined right after new OnClickListener().
Think of the code there as describing an unnamed subclass of OnClickListener(). The class definition is within the brackets, just as you thought.
OnClickListener is a super class from which the inner class is derived.
Yes
The (anonymous) inner class has only one member function: OnClick().
It does, but that does not have to be the case. It could have more member functions.
What is #Override inside the definition of the inner class? If this is an annotation, then I am confused as this answer states that anonymous inner classes cannot be annotated.
#Override is used for compile-time error-checking on methods. You can use method-level annotations on an anonymous inner class.
OnClickListener is a super class from
which the inner class is derived
Not really : OnClickListener is not a class.
This syntaxis is used to create an instance of a new (anonymous) class which implements the interface OnClickListener. So you have only one method to implement : onClick().
Related
View.setOnClickListener( new View.OnClickListener(){
#override
public void onClick(View view){
//Some code implementing this method
}
});
Here OnClickListener is a static Interface declared inside View. Since it is static, it won't be categorized as an Inner class (correct me if I'm wrong here).
Then how can we use an anonymous class to inline implement this static nested interface?
Since, as I know they are only used to inline implement inner classes which are nested types without the static keyword for enclosed type.
First of all: inner interfaces are "static" by default. It is not possible to have an "inner" interface that wouldn't be static! See here for some more thoughts on that aspect.
From that point of view, interfaces are just that: interfaces. Doesn't matter if they are a top level interface sitting in their own .java file, or if the interface sits within some class or so.
And any interface can be implemented using an anonymous inner class.
That is really all there is to this.
To answer to the comment:
so the inline implementation ie the anonymous class itself becomes an inner class of the interface it implements?
No, an anonymous inner class is an inner class of the class that wraps around it. It happens to implement some interface. It is not an inner class of the interface. Inner is really meant in a "physical" sense, as in lines of code sitting inside other blocks of code.
class Outer {
class/interface Inner {
Inner is called an inner class/interface because it lives inside Outer.
When I declare the 'abstract public void show();' in the abstract class Test does that create a brand new show() method or just refer to the show() method declared in the interface Inter? Please clarify.
interface Inter
{
void show();
}
abstract class Test implements Inter
{
abstract public void show(); //What does this line signify?
}
As you might have tested out already, removing the declaration in the abstract class produces no error. It can be safely removed.
If I were to speculate the reasons for this redundant line of code, one reason would be making it easier for subclasses of Test to implement the methods required.
Imagine you are trying to write a Test subclass and the line in question were not there. You go to the definition of Test to find what methods to implement, but you find nothing. You'd have to fo to Inter to see what methods you need to implement. Now imagine the chain of inheritance going much deeper. Do you see how many layers of classes you have to look through to see what methods to implement?
However, these kind of problems can be avoided by using a modern IDE like IntelliJ. It tells you what methods you need to implement automatically.
When I declare the 'abstract public void show();' in the abstract class Test does that create a brand new show() method or just refer to the show() method declared in the interface Inter? Please clarify.
That does not create a new method (no hiding). It overrides the method declared in Inter. Here's a screenshot of IntelliJ:
The little "O" with an upwards arrow indicates overriding.
Explicitly placing an abstract show method in the class has no functional effect - any concrete class that extends this abstract class will have to implement show() anyway, as it's defined in an interface the class implements.
Some coding conventions encourage listing such methods to make their existence more obvious, but it's a matter of taste mostly.
What is the difference between these two piece of code
btn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
}
});
is that inner interface of View class, if so we know that interface can not be instantiated
And here
soInterface.getAnswers().enqueue(new Callback<SOAnswersResponse>() {
#Override
public void onResponse(Call<SOAnswersResponse> call, retrofit2.Response<SOAnswersResponse> response) {
}
#Override
public void onFailure(Call<SOAnswersResponse> call, Throwable t) {
}
});
its callback that it required in the enqueue method, what this syntax define, is it interface "CallBack<>" defined some where and we are calling it here as inline interface, but again interface can not be instantiated like callback syntax says "new CallBack(){}"
What is the difference between these two piece of code
Both are 2 different interface
View.OnClickListener - this interface helps you to listen to the View click action
Callback<SOAnswersResponse> - Try to get the response from the server
Both of them are interfaces:
CallBack is represents that the response(Callback) of Retrofit and when it is present you go into the onResponse or it failed to comeback (in the 10s time frame), be read(wrong parsing), or other reasons then onFailure will be executed.
While onClickListener will be listening to button click.
you can implement an interface of onClick listener in the Activity or Fragment and use button.setOnClickListener(this) same for Retrofit.
Both classes in this case are interfaces with a callback. The anonymous class implements View.OnClickListener which has a callback on onClick. Same goes for the anonymous class implementing Callback<SOAnswersResponse>(). This time it has a typed parameter and two callbacks for onResponse and onFailure.
The statement that interfaces can not be instantiated is true, but you can create an anonymous class of it. See Can we create an instance of an interface in Java?
Both View.OnClickListener and Callback are interfaces.
OnClickListener is nested inside View class. Retrofit Callback is not nested.
This is the Callback interface doc: https://square.github.io/retrofit/2.x/retrofit/retrofit2/Callback.html
interface can not be instantiated
We instantiate an anonymous class here. i.e. We implement the interface as an anonymous class and instantiate that anonymous class on the fly.
From the Java doc:
They [Anonymous class] enable you to declare and instantiate a class
at the same time. They are like local classes except that they do not
have a name. Use them if you need to use a local class only once.
You're correct, it is not possible to instantiate an interface. An interface is the definition of a set of methods that must be implemented by a concrete class.
What your code is using, in both cases, is an anonymous inner class. The Java syntax allows you to specify that you would like a new instance of 'something' that implements the specified interface but you don't want to write all the code to do that. Your code only provides the implementations of the abstract methods defined by that interface.
If you look at the class files for your application you will see something like MyClass$1.class, which is a class file generated synthetically by the compiler. The compiler creates a class called MyClass$1 that implements the interface you've specified with the methods you've defined. The compiler will then make your code look something like this before compiling it:
btn.setOnClickListener(new MyClass$1());
The same applies to the second example but with a different interface, etc.
What's the difference between using interface inside class, inside nested class and outside class.
As I was reading about the class DataStructure.java in Questions and Exercises: Nested Classes at Oracle (pasting here fragment of the example):
public class DataStructure {
//some code
interface DataStructureIterator extends java.util.Iterator<Integer> { }
// Inner class implements the DataStructureIterator interface,
// which extends the Iterator<Integer> interface
private class EvenIterator implements DataStructureIterator {
//rest code
So as the code about shows there is no any body in interface. Couldn't I just extends EvenIterator class with java.util.Iterator<Integer> instead of creating this interface and implements it?
Is there any other difference (aside from code readability) between declaring interference outside/inside class?
What will happen when the outer class gonna be extended by a interface. Will it impact in any way on nested class?
Just want to be sure about these things to know how to use them properly, thanks for your time.
So as the code about shows there is no any body in interface. Couldn't I just extends EvenIterator class with
java.util.Iterator instead of creating this interface and
implements it?
Yes, you could. But this way it may be more readable and extendable. Even if there are no members now, they may be added later.
Is there any other difference (aside from code readability) between declaring interference outside/inside class?
A nested interface is implicitly static, so the only effect is that a nested interface is a part of the enclosing class namespace-wise.
Because members of a class may be declared as protected or private, that applies to nested interfaces as well. It rarely makes sense to use private interfaces, though, because they can only be implemented in the same class, so why bother with interfaces in the first place? However, protected interfaces may be useful. For example, you may have an abstract factory method that is used by the subclasses to provide instances to the parent class. Here's a contrived example:
public abstract class Enclosing {
protected interface JobHandler {
void handle(Job job) throws JobException;
}
protected abstract JobHandler createJobHandler();
// public methods omitted
private void doTheJob(Job job) {
createJobHandler().handle(job);
}
}
If the interface is declared package-private, it might as well just be at the package level. The only reason you may want to cram it inside a class is because it's very tightly coupled to the class itself. Perhaps it's some sort of helper interface that is used strictly in unit testing that particular class.
If the interface is public, then it's usually a bad idea to make it nested. Because by doing that, you increase coupling between the interface and the enclosing class. And interfaces are one of the best ways to reduce coupling! So why waste their potential?
Suppose you have a mylib-buttons library that have a Button class. One day having a Button.ClickListener seems to be a nice idea. Then you want to reuse this interface in another class, and possibly even in another library. But you can't do it without introducing a (probably unnecessary) dependency on the library that contains the Button class. On the other hand, if it's a top-level interface, then you just extract the interfaces into another library, say, mylib-core, leaving the messy buttons alone in the mylib-buttons.
Nested interfaces inside interfaces is a bit different story. They can be a part of the same design and intended to be used together. #cricket_007 in one of the comments gives a good example of that: Map.Entry.
What will happen when the outer class gonna be extended by a interface. Will it impact in any way on nested class?
This is not exactly clear. How can a class be extended by an interface? Nevertheless, whatever you meant here, you can probably answer it yourself if you consider the aforementioned fact: the nested interface is just a part of the class' namespace scope, and that's it. There are no other impacts whatsoever.
It's been a few years since I've been heavily into Java. Coming back to it I'm seeing this pattern all over the place:
ratingBar.setOnRatingBarChangeListener(new OnRatingBarChangeListener() {
public void onRatingChanged(RatingBar ratingBar, float rating, boolean fromUser) {
// do work
}
});
This looks more like Functional programming to me. It's a nice pattern but how is it possible to pass a method like this? In the old days a class was a class, and once compiled there was little you could do to it.
My questions are:
Can anyone let me know what this pattern is called?
How can I write a class that can be instantiated in this way.
Are there any other useful examples of functional patterns that have made their way into Java?
What do I need to Google to read more about this?
Thanks.
This passes an anonymous class, not a method.
This is a typical pattern, not just in Swing programming, but anywhere you need (hopefully) short, "throw-away" implementations of an interface or class that doesn't need to be re-used, instead of creating a full-blown implementation.
Any class/interface can be instantiated like this, there's nothing special about it:
public interface Foo {
String foo();
}
...
public class Main {
public static void main(String[] args) {
System.out.println(new Foo() {
public String foo() {
return "plugh";
}
});
}
}
Anonymous inner classes get their own class files, too, even though their source is embedded.
In this example, a Main$1.class file will be generated for the anonymous inner class, in addition to the expected Main.class file.
The statement: new OnRatingBarChangeListener() creates a new instance of a class. The following part inside the curly braces is the definition of the class.
In this case that class in an anonymous class that implements the named interface.
Anonymous classes are classes, that are declared without a name, and thus, can not be used like regular named classes.
This pattern is very common when using listeners, that often contain only a single to a few methods that do an almost trivial task.
This is the Listener pattern. Rating bar takes an implementation of OnRatingBarChangeListener and calls its onRatingChanged method on the appropriate event.
You can use instance of any class which implements OnRatingBarChangeListener. So you can use either a named class of your own or you can pass it an anonymous class like in the example. The anonymous class in the example is effectively a unnamed class which extends Object and implements OnRatingBarChangeListener. Since the class isn't named it cannot be referenced and so the instance passed is the only instance existing.
This is called "Observer pattern". A good example for this is adding action listeners for java button or other component. For example,
myButton.addActionListener(
new java.awt.event.ActionListener()
{
public void actionPerformed(ActionEvent e)
{
//Work here
}
});
In here "myButton" is the subject and ActionListener is the observer.