I'm trying to understand Java anonymous classes.
Looking here:
https://docs.oracle.com/javase/tutorial/java/javaOO/anonymousclasses.html
And here:
http://docstore.mik.ua/orelly/java-ent/jnut/ch03_12.htm
I understand the basic syntax, but the examples are non-minimal.
What are the absolute minimal requirements to define a anonymous class in Java?
Edit>>>
Essentially this:
public class MyClass {
InnerClass instance = new InnerClass();
public class InnerClass{
public void print(){
System.out.println("First Call");
}
};
public void redefineInstance(){
instance = new InnerClass(){
public void print(){
System.out.println("Second Call");
}
};
}
public static void main(String[] args) throws Exception{
MyClass myobject = new MyClass();
myobject.instance.print();
myobject.redefineInstance();
myobject.instance.print();
}
}
The most minimal example:
interface Foo {}
public static void main (String[] args)
{
Foo foo = new Foo() {};
}
Literally a declaration of an interface, and then usage as an anonymous class with no additional declarations.
Practically speaking, it does nothing. However, as we add bits in:
interface Foo {
public void bar();
}
public static void main (String[] args) throws java.lang.Exception
{
Foo foo = new Foo() {
public void bar() {
System.out.println("Hello");
}
};
}
It becomes a full-fledged helper class for our method.
The most common use for early/mid level programming would be overriding Listeners to do specific actions. We know the Listener is listening for something, and we want it to do something as a result of the Listener, so we craft the Listener and say "Do this when you are triggered."
Here's the example of a really complex ActionListener tutorial: https://docs.oracle.com/javase/tutorial/uiswing/events/actionlistener.html
But typically, if it's something that's mundane like "run a method on click", you'll use an anonymous in-line declaration that just calls a method for you.
I suppose the "absolute minimal requirement" to create an anonymous class is to have a place in your code that requires an instance of a non-final class or interface of some kind.
Meaning, if I have a method in MyClass:
public static void gimmeMyObject(MyObject c)
I can define an anonymous class that extends MyObject as long as MyObject is not final:
//Somewhere in a method
MyClass.gimmeMyObject(new MyObject() {
public String myMethod() {
return "I'm anonymous";
}
});
That anonymous class will be passed in as a MyObject.
However, I could not do this if the method required a String or Integer, for example, because those are final classes.
For the above example, the non-anonymous class would translate to:
public class MyAnonObject extends MyObject { //In actuality, an anonymous class doesn't have a name, though.
public String myMethod() {
return "I'm anonymous";
}
}
As Compass has already said, the absolute minimum is not useful.
Following is an example of a 'useful' inner class:
JButton ok = new JButton();
ok.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
System.out.println("abc");
}
});
So instead of having to define an inner class or a helper class for an ActionListener you only use once, you can just have it as an inline or anonymous class to remove clutter and increase readability.
How about this example?
//interface
interface Message{
String greet();
}
Message is a anonymous class in this example,
greet() is the only method inside this anonymous class.
//Passing an anonymous inner class as an argument
obj.displayMessage(new Message(){
public String greet(){
return "Hello";
}
});
You can think of an anonymous class as just basically the instantiation part of creating a new instance of an object. You essentially just don't declare it and give it a name. This is normally passed into method parameters as shown below.
Object someObj; is an object declaration.
someObj = new Objct(parm a,...) is the instantiation of the object.
//example of anonymous classes:
public void foo(Bar barObj){// takes a Bar object parameter
//does stuff
}
//you can call the foo method in this way
Bar barObject= new Bar();
foo(barObject){}
// or you can call the Bar anonymously
foo(new Bar()){}
In the anonymous example you instantiate a new Bar inside the method parameter. You can do this when you just need something local and don't need it to be used anywhere but in that method call. it also then gives you access to the accessible methods that are inside of the anonymous class. so you could do something like
foo(new Bar().barMethod){}. It just kind of depends what you are working with.
Related
I have a class called "Design", and I am writing the following code to extend the class to include a new function called sayHello(). However it doesnt seem to be working. Am I only allowed to ovveride existing functions in that way?
Design design1 = new Design() {
public void sayHello() {
System.out.println("hello");
}
};
design1.sayHello(); // this gives an error "function not found"
So that is logical.
You are overriding a super class and assigning it to the instance variable of super class.
As the instance variable is of super class type, you can access only those methods which are available in super class.
You can do that if your "Design" class is an interface. You could create an anonymous inner class.
Example:
public interface Design{
public void sayHello();
}
public class Test
{
public static void main(String args[])
{
Design d = new Design(){
#Override
public void sayHello(){
return "Hello World!";
}
};
System.out.println(d.sayHello());
}
}
interface A
{
public void printValue();
}
public class Test
{
public static void main (String[] args)
{
A a1 = new A() {
public void printValue()
{
System.out.println("A");
}
};
a1.printValue();
}
}
We cannot create an instance of an interface, but what is new A() doing in this code? I have seen this type of code used mostly with Comparators. Please explain.
new A() {} is an instantiation of an anonymous class that implements interface A.
It is a short-cut that can be useful if you need an instance of a class that implements an interface only in one place, so you don't want to define a normal class. This way you define the class at the same place it is being used.
In your code sample, it doesn't seem very useful, but usually it is used by passing the anonymous class instance to some method that accepts a parameter of the type of the interface.
new A() in below is where you are instantiating a concrete class (which we say anonymous) which implements the interface A
A a1 = new A() {
public void printValue(){
System.out.println("A");
}
};
In your code, interface A is used as an Anonymous class. You can use them if you need to use a local class only once. it's more over same as lambda expressions.
Read more: http://docs.oracle.com/javase/tutorial/java/javaOO/anonymousclasses.html
Read about lambda expression: http://docs.oracle.com/javase/tutorial/java/javaOO/lambdaexpressions.html
I've some class with these methods:
public class TestClass
{
public void method1()
{
// this method will be used for consuming MyClass1
}
public void method2()
{
// this method will be used for consuming MyClass2
}
}
and classes:
public class MyClass1
{
}
public class MyClass2
{
}
and I want HashMap<Class<?>, "question"> where I would store (key: class, value: method) pairs like this ( class "type" is associated with method )
hashmp.add(Myclass1.class, "question");
and I want to know how to add method references to HashMap (replace "question").
p.s. I've come from C# where I simply write Dictionary<Type, Action> :)
Now that Java 8 is out I thought I'd update this question with how to do this in Java 8.
package com.sandbox;
import java.util.HashMap;
import java.util.Map;
public class Sandbox {
public static void main(String[] args) {
Map<Class, Runnable> dict = new HashMap<>();
MyClass1 myClass1 = new MyClass1();
dict.put(MyClass1.class, myClass1::sideEffects);
MyClass2 myClass2 = new MyClass2();
dict.put(MyClass2.class, myClass2::sideEffects);
for (Map.Entry<Class, Runnable> classRunnableEntry : dict.entrySet()) {
System.out.println("Running a method from " + classRunnableEntry.getKey().getName());
classRunnableEntry.getValue().run();
}
}
public static class MyClass1 {
public void sideEffects() {
System.out.println("MyClass1");
}
}
public static class MyClass2 {
public void sideEffects() {
System.out.println("MyClass2");
}
}
}
This is feature which is likely to be Java 8. For now the simplest way to do this is to use reflection.
public class TestClass {
public void method(MyClass1 o) {
// this method will be used for consuming MyClass1
}
public void method(MyClass2 o) {
// this method will be used for consuming MyClass2
}
}
and call it using
Method m = TestClass.class.getMethod("method", type);
Method method = TestClass.class.getMethod("method name", type)
Use interfaces instead of function pointers. So define an interface which defines the function you want to call and then call the interface as in example above. To implement the interface you can use anonymous inner class.
void DoSomething(IQuestion param) {
// ...
param.question();
}
You mention in the code comment that each method consumes an object of a certain type. Since this is a common operation, Java already provides you with a functional interface called Consumer that acts as a way to take an object of a certain type as input and do some action on it (two words so far that you already mentioned in the question: "consume" and "action").
The map can therefore hold entries where the key is a class such as MyClass1 and MyClass2, and the value is a consumer of objects of that class:
Map<Class<T>, Consumer<T>> consumersMap = new HashMap<>();
Since a Consumer is a functional interface, i.e. an interface with only one abstract method, it can be defined using a lambda expression:
Consumer<T> consumer = t -> testClass.methodForTypeT(t);
where testClass is an instance of TestClass.
Since this lambda does nothing but call an existing method methodForTypeT, you can use a method reference directly:
Consumer<T> consumer = testClass::methodForTypeT;
Then, if you change the signatures of the methods of TestClass to be method1(MyClass1 obj) and method2(MyClass2 obj), you would be able to add these method references to the map:
consumersMap.put(MyClass1.class, testClass::method1);
consumersMap.put(MyClass2.class, testClass::method2);
While you can store java.lang.reflect.Method objects in your map, I would advise against this: you still need to pass the object that is used as the this reference upon invocation, and using raw strings for method names may pose problems in refactoring.
The cannonical way of doing this is to extract an interface (or use an existing one) and use anonymous classes for storing:
map.add(MyClass1.class, new Runnable() {
public void run() {
MyClass1.staticMethod();
}
});
I must admit that this is much more verbose than the C#-variant, but it is Java's common practice - e.g. when doing event handling with Listeners. However, other languages that build upon the JVM usually have shorthand notations for such handlers. By using the interface-approach, your code is compatible with Groovy, Jython, or JRuby and it is still typesafe.
To answer your direct question regarding using a Map, your proposed classes would be:
interface Question {} // marker interface, not needed but illustrative
public class MyClass1 implements Question {}
public class MyClass2 implements Question {}
public class TestClass {
public void method1(MyClass1 obj) {
System.out.println("You called the method for MyClass1!");
}
public void method2(MyClass2 obj) {
System.out.println("You called the method for MyClass2!");
}
}
Then your Map would be:
Map<Class<? extends Question>, Consumer<Question>> map = new HashMap<>();
and populated like this:
TestClass tester = new TestClass();
map.put(MyClass1.class, o -> tester.method1((MyClass1)o)); // cast needed - see below
map.put(MyClass2.class, o -> tester.method2((MyClass2)o));
and used like this:
Question question = new MyClass1();
map.get(question.getClass()).accept(question); // calls method1
The above works OK, but the problem is that there's no way to connect the type of the key of the map with the type of its value, ie you can't use generics to properly type the value of the consumer and so use a method reference:
map.put(MyClass1.class, tester::method1); // compile error
that's why you need to cast the object in the lambda to bind to the correct method.
There's also another problem. If someone creates a new Question class, you don't know until runtime that there isn't an entry in the Map for that class, and you have to write code like if (!map.containsKey(question.getClass())) { // explode } to handle that eventuality.
But there is an alternative...
There is another pattern that does give you compile time safety, and means you don't need to write any code to handle "missing entries". The pattern is called Double Dispatch (which is part of the Visitor pattern).
It looks like this:
interface Tester {
void consume(MyClass1 obj);
void consume(MyClass2 obj);
}
interface Question {
void accept(Tester tester);
}
public class TestClass implements Tester {
public void consume(MyClass1 obj) {
System.out.println("You called the method for MyClass1!");
}
public void consume(MyClass2 obj) {
System.out.println("You called the method for MyClass2!");
}
}
public class MyClass1 implements Question {
// other fields and methods
public void accept(Tester tester) {
tester.consume(this);
}
}
public class MyClass2 implements Question {
// other fields and methods
public void accept(Tester tester) {
tester.consume(this);
}
}
And to use it:
Tester tester = new TestClass();
Question question = new MyClass1();
question.accept(tester);
or for many questions:
List<Question> questions = Arrays.asList(new MyClass1(), new MyClass2());
questions.forEach(q -> q.accept(tester));
This pattern works by putting a callback into the target class, which can bind to the correct method for handling that class for the this object.
The benefit of this pattern is if another Question class is created, it is required to implement the accept(Tester) method, so the Question implementer will not forget to implement the callback to the Tester, and automatically checks that Testers can handle the new implementation, eg
public class MyClass3 implements Question {
public void accept(Tester tester) { // Questions must implement this method
tester.consume(this); // compile error if Tester can't handle MyClass3 objects
}
}
Also note how the two classes don't reference each other - they only reference the interface, so there's total decoupling between Tester and Question implementations (which makes unit testing/mocking easier too).
Have you tried Method object? refer:
http://docs.oracle.com/javase/1.5.0/docs/api/java/lang/reflect/Method.html
http://docs.oracle.com/javase/1.5.0/docs/api/java/lang/Class.html#getMethod%28java.lang.String,%20java.lang.Class...%29
Your question
Given your classes with some methods:
public class MyClass1 {
public void boo() {
System.err.println("Boo!");
}
}
and
public class MyClass2 {
public void yay(final String param) {
System.err.println("Yay, "+param);
}
}
Then you can get the methods via reflection:
Method method=MyClass1.class.getMethod("boo")
When calling a method, you need to pass a class instance:
final MyClass1 instance1=new MyClass1();
method.invoke(instance1);
To put it together:
public class Main {
public static void main(final String[] args) throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
final Map<Class<?>,Method> methods=new HashMap<Class<?>,Method>();
methods.put(MyClass1.class,MyClass1.class.getMethod("boo"));
methods.put(MyClass2.class,MyClass2.class.getMethod("yay",String.class));
final MyClass1 instance1=new MyClass1();
methods.get(MyClass1.class).invoke(instance1);
final MyClass2 instance2=new MyClass2();
methods.get(MyClass2.class).invoke(instance2,"example param");
}
}
Gives:
Boo!
Yay, example param
Watch out for the following gotchas:
hardcoded method name as a string - this is very hard to avoid
it is reflection, so accessing to the metadata of the class in runtime. Prone to a lot of exceptions (not handled in the example)
you need to tell not only the method name, but the parameter types as well to access to one method. This is because method overloading is standard, and this is the only way to pick the right overloaded method.
watch out when calling a method with parameters: there is no compile time parameter type check.
An alternative answer
I guess what you're looking for is a simple listener: i.e. a way to call a method from another class indirectly.
public class MyClass1 implements ActionListener {
#Override
public void actionPerformed(final ActionEvent e) {
System.err.println("Boo!");
}
}
and
public class MyClass2 implements ActionListener {
#Override
public void actionPerformed(final ActionEvent e) {
System.err.println("Yay");
}
}
using as:
public class Main {
public static void main(final String[] args) {
final MyClass1 instance1=new MyClass1();
final MyClass2 instance2=new MyClass2();
final Map<Class<?>,ActionListener> methods=new HashMap<Class<?>,ActionListener>();
methods.put(MyClass1.class,instance1);
methods.put(MyClass2.class,instance2);
methods.get(MyClass1.class).actionPerformed(null);
methods.get(MyClass2.class).actionPerformed(null);
}
}
This is called the listener pattern. I dared to reuse the ActionListener from Java Swing, but in fact you can very easily make your own listeners by declaring an interface with a method. MyClass1, MyClass2 will implement the method, and then you can call it just like a... method.
No reflection, no hardcoded strings, no mess. (The ActionListener allows passing one parameter, which is tuned for GUI apps. In my example I just pass null.)
class XYZ{
public static void show(){
System.out.println("inside XYZ");
}
}
public class StaticTest extends XYZ {
public static void show() {
System.out.println("inside statictest");
}
public static void main(String args[]){
StaticTest st =new StaticTest();
StaticTest.show();
}
}
though we know static methods cant be overridden. Then what actually is happening?
Static methods belong to the class. They can't be overridden. However, if a method of the same signature as a parent class static method is defined in a child class, it hides the parent class method. StaticTest.show() is hiding the XYZ.show() method and so StaticTest.show() is the method that gets executed in the main method in the code.
Its not overriding they are two different method in two different class with same signature. but method from XYZ isn't available in child class through inheritance .
It will call method from StaticTest
It's not overriden properly said... Static methods are 'tied' to the class so
StaticTest.show();
and
XYZ.show();
are two totally different things. Note you can't invoke super.show()
To see the difference you have to use more powerful example:
class Super {
public static void hidden(Super superObject) {
System.out.println("Super-hidden");
superObject.overriden();
}
public void overriden() {
System.out.println("Super-overriden");
}
}
class Sub extends Super {
public static void hidden(Super superObject) {
System.out.println("Sub-hidden");
superObject.overriden();
}
public void overriden() {
System.out.println("Sub-overriden");
}
}
public class Test {
public static void main(String[] args) {
Super superObject = new Sub();
superObject.hidden(superObject);
}
}
As Samit G. already have written static methods with same signature in both base and derived classes hide the implementation and this is no-overriding. You can play a bit with the example by changing the one or the another of the static methods to non-static or changing them both to non-static to see what are the compile-errors which the java compiler rises.
It's not an override, but a separate method that hides the method in XYZ.
So as I know, any static member (method or state) is an attribute of a class, and would not be associated with any instance of a class. So in your example, XYZ is a class, and so is StaticTest (as you know). So by calling the constructor two things first happen. An Object of type Class is created. It has a member on it call showed(). Class, XYZ.class, extends from Object so has all those Object methods on it plus show(). Same with the StaticClass, the class object has show() on it as well. They both extend java.lang.Object though. An instance of StaticClass would also be an instance of XYZ. However now the more interesting question would be what happens when you call show() on st?
StaticClass st = new StaticClass();
st.show();
XYZ xyz = st;
xyz.show();
What happens there? My guess is that it is StaticClass.show() the first time and XYZ.show() the second.
Static methods are tied to classes and not instances (objects).
Hence the invocations are always ClassName.staticMethod();
When such a case of same static method in a subclass appears, its called as refining (redefining) the static method and not overriding.
// Java allows a static method to be called from an Instance/Object reference
// which is not the case in other pure OOP languages like C# Dot net.
// which causes this confusion.
// Technically, A static method is always tied to a Class and not instance.
// In other words, the binding is at compile-time for static functions. - Early Binding
//
// eg.
class BaseClass
{
public static void f1()
{
System.out.println("BaseClass::f1()...");
} // End of f1().
}
public class SubClass extends BaseClass
{
public static void f1()
{
System.out.println("SubClass::f1()...");
// super.f1(); // non-static variable super cannot be referenced from a static context
} // End of f1().
public static void main(String[] args)
{
f1();
SubClass obj1 = new SubClass();
obj1.f1();
BaseClass b1 = obj1;
b1.f1();
} // End of main().
} // End of class.
// Output:
// SubClass::f1()...
// SubClass::f1()...
// BaseClass::f1()...
//
//
// So even though in this case, called with an instance b1 which is actually referring to
// an object of type SuperClass, it calls the BaseClass:f1 method.
//
I am trying to wrap my mind around something in java. When I pass an object to another class' method, can I not just call any methods inherent to that object class?
What is the reason code such as the example below does not compile?
Thank you,
class a {
public static void myMethod(Object myObj) {
myObj.testing();
}
}
class b {
public void testing() {
System.out.println ("TESTING!!!");
}
}
class c {
public static void main (String[] args) {
b myB = new b();
a.myMethod(myB);
}
}
Edit: The reason I have left the parameter in myMethod as type Object, is because I would like to be able to pass in a variety of object types, each having a testing() method.
If you would like to pass in a variety of objects with testing() methods, have each object implement a Testable interface:
public interface Testable
{
public void testing()
}
Then have myMethod() take a Testable.
public static void myMethod(Testable testable)
{
testable.testing();
}
Edit: To clarify, implementing an interface means that the class is guaranteed to have the method, but the method can do whatever it wants. So I could have two classes whose testing() methods do different things.
public class AClass implements Testable
{
public void testing()
{
System.out.println("Hello world");
}
}
public class BClass implements Testable
{
public void testing()
{
System.out.println("Hello underworld");
}
}
The problem is that myMethod can't know it's getting a b object until it actually runs. You could pass a String in, for all it knows.
Change it to
public static void myMethod(b myObj) {
myObj.testing();
}
and it should work.
Update of the question:
Edit: The reason I have left the parameter in myMethod as type Object, is because I would like to be able to pass in a variety of object types, each having a testing() method.
As Amanda S and several others have said, this is a perfect case for an interface. The way to do this is to create an interface which defines the testing() method and change myMethod to take objects implementing that interface.
An alternative solution (without interfaces) would be to reflectively discover if the object has a testing() method and call it, but this is not recommended and not needed for a such a simple case.
What you are talking about is duck typing. Java doesn't have duck typing.
Therefore you need to define an interface that all the classes with a testing() method implement.
e.g:
public interface Testable
{
public void testing()
}
class B implements Testable
{
public void testing() {
System.out.println ("TESTING!!!");
}
}
class A {
public static void myMethod(Testable myObj) {
myObj.testing();
}
}
Your issue is a classic argument in favor of an interface. You want as generic as possible, yet you want every object you pass to have a testing() method. I suggest something along the lines of the following:
public interface Testable
{
public void testing();
}
public class A
{
public static void myMethod(Testable myObj)
{
myObj.testing();
}
}
public class B implements Testable
{
public void testing()
{
System.out.println("This is class B");
}
}
public class C implements Testable
{
public void testing()
{
System.out.println("This is class C");
}
}
public class Test
{
public static void main (String[] args)
{
B myB = new B();
C myC = new C();
A.myMethod(myB); // "This is class B"
A.myMethod(myC); // "This is class C"
}
}
Because you're passing in an Object (b inherit from Object). Object doesn't have testing, b does.
You can either pass in b or cast the object to b before calling the method.
EDIT
To pass in a generic class that implements that method: you'll want to make an interface that has the method signature and pass in the interface type instead of Object. All objects that you pass in must implement the interface.
You can only access the members that are visible for the type of reference you have to the object.
In the case of myMethod(Object myObj) that means only the members defined in Object, so in class a the members of class b will not be visible.
If you changed the definition of a.myMethod to be public static void myMethod(b myObj) you would then be able to see the testing method on the instance of b while in myMethod.
update based on clarification:
In that case defining an interface for all of them to implement is likely what you want.
public interface Testable {
public void testing();
}
public class a {
public static void myMethod(Testable myObj) {
myObj.testing();
}
}
public class b implements Testable {
public void testing () {
System.out.println("TESTING!!!");
}
}
Why can’t java find my method?
Because of the way Java was designed.
Java is "statically typed" that means objects types are checked during compilation.
In Java you can invoke a method only if that method belongs to that type.
Since this verification is made during compilation and the Object type does not have the "testing()" method, the compilation fails ( even though if at runtime the objects do have that method". This is primarily for safety.
The workaround as described by others will require you to create a new type, where you can tell the compiler
"Hey, the instances of this type will respond the the testing method"
If you want to pass a variety of objects and keep it very generic, one way is having those objects to implement and interface.
public interface Testable {
public void testing();
}
class A implements Testable { // here this class commits to respond to "testing" message
public void testing() {
}
}
class B implements Testable { // B "is" testable
public void testing() {
System.out.println("Testing from b");
}
}
class C implements Testable { // C is... etc.
public void testing() {
//....
}
}
Later somewhere else
public void doTest( Testable object ) {
object.testing();
}
doTest( new A() );
doTest( new B() );
doTest( new C() );
The "OTHER" way to do this, in java is invoking the methods reflectively, but I'm not sure if that's what you need, for the code is much more abstract when you do it that way, but that's how automated testing frameworks (and a lot of other frameworks such as Hibernate) do actually work.
I hope this help you to clarify the reason.
If you REALLY, REALLY want to keep the parameter as abstract as possible, you should consider reflection API. That way, you can pass whatever object you want and dynamically execute the method you want. You can take a look at some examples.
It's not the only way, but it might be a valid alternative depending on your problem.
Keep in mind that reflection is way slower than calling your methods directly. You might consider using an interface as well, such as the one on Amanda's post.