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.)
Related
Consider the following scenario:
Say that you created an interface Foo:
public interface Foo {
public void bar();
}
And say that there is an old class SomeOldClass in a certain library that you want to use. It already has the bar() method, but does not explicitly implement Foo.
You have written the following code for all classed that implement Foo:
public <T extends Foo> T callBarOnThird(List<T> fooList){
return fooList.get(2).bar();
}
And now you want it to also work for SomeOldClass. You dont have access to the source code of this class, so you can't modify it.
Is there a way to declare Foo or something similar as some sort of "soft" interface, (as in where any class that implements all the required methods would be accepted as an implicit implementation of the soft interface)? If not, how would you solve this with code that is as clean as possible?
No, it does not.
You have to provide an adapter instance (there are several methods and tools to help with that, but Java does not do it "implicitly").
Java is statically typed and dynamically bind.
Dynamically bind: This means that the linking between a method signature and its implementation happens at runtime. For example.
For example
public interface MyInterface {
void doStuff();
}
public class MyFirstImpl implements MyInterface {
#Override
public void doStuff() {
// do some stuff here
}
}
public class MySecondImpl implements MyInterface {
#Override
public void doStuff() {
// do some stuff here
}
}
So if you would have the next snippet
MyInterface test; // pointing to either MyFirstImpl or MySecondImpl
test.doStuff();
The JVM will determine at runtime weather to call the doStuff method from MyFirstImpl or MySecondImpl based on the runtime type of the object.
Statically typed: This means that the JVM will check at compile time weather a there is a method to call regardless of the implementation.
For example:
public interface MyInterface {
void doStuff();
}
public class MyFirstImpl implements MyInterface {
// no override here
public void doStuff() {
// do some stuff here
}
}
public class MySecondImpl implements MyInterface {
// no override here
public void doStuff() {
// do some stuff here
}
}
So if you would have the next snippet
MyInterface test; // pointing to either MyFirstImpl or MySecondImpl
test.doStuff();
The compiler will complain because it can't ensure at compile time that regardless of the implementation of MyInterface there is a doStuff method to call (although in this case, both implementations of MyInterface define a doStuff method).
This ensures that you won't get a NoSuchMethodException at runtime, if you would pass, for example, the next implementation.
public class MySecondImpl implements MyInterface {
// no override here
// no doStuff method
}
This adds some type safety to the language at the cost of some rigidity (since you are able to determine the issue earlier than at runtime and therefore you have a shorter feedback loop, at the cost of the scenario in which all the implementations actually expose the method not working out of the box).
How you should refactor your code:
Create a wrapper over the third party library and expose the interface from the wrapper.
public interface Foo {
void bar();
}
public class ThirdPartyFooWrapper implements Foo {
private SomeOldClass oldClass;
public ThordPartyFooWrapper (SomeOldClass oldClass){
this.oldClass = oldClass;
}
#Override
public void bar() {
this.oldClass.bar();
}
}
Then, in your code use ThirdPartyFooWrapper instead of SomeOldClass.
Hope this answers your question!
Extension to Thilos answer.
You can also use the decorator to handle this
public <T extends Foo> T callBarOnThird(List<T> fooList){
return new BarDecorator(fooList.get(2)).bar();
}
Inside the decorator, you can check if given Object is the instance of Foo or not then do operations accordingly.
I have the following generic interface:
public interface I<T> {
void method(T key);
}
which it is implemented by two different classes (A y B).
public class A implements I<Integer> {
#Override
void method(Integer key) {
//do smth
}
public class B implements I<String> {
#Override
void method(String key) {
//do smth
}
Futhermore, there is a Java class MyClass where a new instance of A or B is created depending on the T param.
public class MyClass<T> {
public void f() {
I<T> object = //here is the problem
}
}
My question is the following:
Is it possible to achieve it without passing the object of T class?
Pass a Supplier.
class MyClass<T> {
public void f(Supplier<I<T>> supplier) {
I<T> object = supplier.get();
}
}
new MyClass<String>().f(B::new);
new MyClass<Integer>().f(A::new);
no. you have to have something concrete to disambiguate the instantiation. remember, at runtime the generic bindings are gone (they are only syntactic sugar). if you doubt this, compile the same code with and without the generic hints. the output classes will be bytewise identical.
you basically have to have "some concrete reference to a type", either as presented by Igor above, or something else (Class.forName( "ClassName" ), ClassName.class, etc.) or dynamically build a class via java.lang.reflect.Proxy.
Igor's example just creates an anonymous factory as a lambda, but in the end, he's still passing the reference to a class, wrapped in a factory method, and bound as a lambda.
now something you "could" do, if you want to pass the Class, you could change your binding to or something similar, and pass a Class reference to use for instantiation. then you can do something like
_pass_in_ref.newInstance();
_pass_in_ref::new
etc.
caveat emptory
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.
I have a basic question about generics in Java.
I have a class X which is instantiated by another class T. In every class T which will be used has a method called as methodOfT(). However, Java gives me compiler time error since it does not know obj and methodOfT().
public class X<T>
{
T obj;
public void methodOfX()
{
obj.methodOfT();
}
}
In order to avoid this problem, what I did is I defined another class XSuper. And every class now which wants to instantiate X will extend this XSuper class. This removes the compile time error and allows me to achieve what I want.
public abstract class XSuper
{
public abstract void methodOfT();
}
public class UserOfX extends XSuper
{
X<UserOfX> objX = new X<UserOfX>();
public void methodOfT()
{
}
}
However, I want to know the cleaner way of doing this thing. Since I want to derive class UserOfX from another Class. Another Problem is that I want to define methodOfT() method as -
public methodOfT(T objOfT)
{
}
In this case, the above solution fails. Could someone help.
public class X<T>
{
T obj;
public void methodOfX()
{
obj.methodOfT();
}
}
The compiler doesn't know what T is so it is evaluated as Object. Object does not have a methodOfT method, so compilation fails. Here's how to solve that:
public interface SomeInterface{
void methodOfT();
}
public class X<T extends SomeInterface>
{
T obj;
public void methodOfX()
{
obj.methodOfT();
}
}
In this case, the compiler knows that the supplied T will implement the interface SomeInterface and hence have the method methodOfT. (You can also use classes instead of interfaces, but that's less elegant)
Given your additional requirements, we're going t have to change this code some more:
public interface SomeInterface<X>{
void methodOfT(X object);
}
public class X<T1, T2 extends SomeInterface<T1>>
{
T1 obj1;
T2 obj2;
public void methodOfX()
{
obj2.methodOfT(obj1);
}
}
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.