This might be a stupid question but I gotta know if there is a way to send the instance of a object to a method?
Like this:
public class TestClass
{
public TestClass()
{
//Initialize
}
}
public class AnotherClass
{
Instance!? mInstance;
public AnotherClass(Instance!? instance)
{
mInstance = instance;
}
public boolean isInstanceOfTestClass()
{
return mInstance == TestClass;
}
}
public class Main
{
public static void main(String[] args)
{
AnotherClass a = new AnotherClass(TestClass);
if(a.isInstanceOfTestClass)
System.out.println("lala");
}
}
(Tried to make it wrapped as codeblock)
There's no such thing as an "instance of an object". An object is an instance of a class - so "instance" and "object" refer to the same thing.
You can use the instanceof operator to test if an arbitrary object is an instance of a particular class:
if (a instanceof AnotherClass) {
// ...
}
There's also the class java.lang.Class, which represents the class of an object. You can get it by calling getClass() on an object:
Class<?> cls = a.getClass();
See the API documentation of java.lang.Class.
Well you can use Class.isAssignableFrom and construct with an instance of Class where T is the class you want to test for.
But if you are bothered about about enforcing typing and making non-type specific classes I suggest you read up on generics.
Related
What is the right / most popular way to utilize the Singleton Pattern.
Limit the no. of calls to getInstance(), preferably call it only once, and pass the object around to other classes during their instantiation?
class SingletonClass {
// Implementataion
}
class MainClass {
private SingletonClass singletonClassObject;
public MainClass() {
singletonClassObject = SingletonClass.getInstance();
new SomeClass(singletonClassObject).doSomething();
new SomeOtherClass(singletonClassObject).doSomethingElse();
}
}
class SomeClass {
private SingletonClass singletonClassObject;
public SomeClass(SingletonClass singletonClassObject) {
this.singletonClassObject = singletonClassObject;
}
public void doSomething() {
System.out.println(singletonClassObject.getStuff());
}
}
class SomeOtherClass {
private SingletonClass singletonClassObject;
public SomeOtherClass(SingletonClass singletonClassObject) {
this.singletonClassObject = singletonClassObject;
}
public void doSomethingElse() {
System.out.println(singletonClassObject.getStuff());
}
}
Don't pass the singleton object around. Rather call get the object reference in each class and save the reference as an instance variable and use it wherever required.
class SingletonClass {
// Implementataion
}
class MainClass {
public MainClass() {
new SomeClass().doSomething();
new SomeOtherClass().doSomethingElse();
}
}
class SomeClass {
private SingletonClass singletonClassObject;
public SomeClass() {
singletonClassObject = SingletonClass.getInstance();
}
public void doSomething() {
System.out.println(singletonClassObject.getStuff());
}
}
class SomeOtherClass {
private SingletonClass singletonClassObject;
public SomeOtherClass() {
singletonClassObject = SingletonClass.getInstance();
}
public void doSomethingElse() {
System.out.println(singletonClassObject.getStuff());
}
}
Don't even save the reference as an instance variable, rather use SingletonClass.getInstance() everywhere you need the object.
class SingletonClass {
// Implementataion
}
class MainClass {
public MainClass() {
new SomeClass().doSomething();
new SomeOtherClass().doSomethingElse();
}
}
class SomeClass {
public SomeClass() {
}
public void doSomething() {
System.out.println(SingletonClass.getInstance().getStuff());
}
}
class SomeOtherClass {
public SomeOtherClass() {
}
public void doSomethingElse() {
System.out.println(SingletonClass.getInstance().getStuff());
}
}
How do these approaches compare with each other w.r.t. better design, testability etc? Which is better and why?
If we assume for a moment that SingletonClass is not a singleton and we do not get an instance by calling static method we face another problem, how to link these classes together. This problem is solved by Dependency Injection and this concept is well described here:
Inversion of Control Containers and the Dependency Injection pattern
Unit Testing 101: Inversion Of Control
After reading above it should be easy to choose option .1 where all classes get in constructor references to required dependencies. You can even create an interface for a behaviour you need and implement it in SingletonClass. Now you see, that a fact that class implements Singleton pattern does not make it special and we should inject them like other classes. All benefits from using DI you can apply to your class.
Just compare it with .3 and you need to write a test where you need mock something. It would be more unpleasant task then in case of .1.
Look at it this way: you're questioning the compiler's ability to recognize that a static final reference can be compiled as an inline reference.
I would guess the compiler converts the getInstance() to an inline reference. I would be less confident that the compiler would recognize that you're intentionally creating extra work for yourself when you pass a reference by value, and that it would create an extra reference on the stack when you passed it around.
My guess is that getInstance() would be more efficient.
Im very new to programming and want to know if I can somehow get the object from a class where I already used new MyClass(); to use it in another class and that I don't need to use new MyClass(); again. Hope you get the point.
Some very simple example:
class MyFirstClass
{
Something st = new Something();
}
class Something()
{
// some code
}
class MySecondClass
{
// This is where I want to use the object from class Something()
// like
getObjectFromClass()
}
You can use Singleton pattern to achieve this
This is kickoff example of such object. It has a private constructor and public class method getInstance:
static methods, which have the static modifier in their declarations,
should be invoked with the class name, without the need for creating
an instance of the class
When we make a call to getInstance it checks if an object has been created already and will return an instance of already created objected, if it wasn't created it will create a new object and return it.
public class SingletonObject {
private static int instantiationCounter = 0; //we use this class variable to count how many times this object was instantiated
private static volatile SingletonObject instance;
private SingletonObject() {
instantiationCounter++;
}
public static SingletonObject getInstance() {
if (instance == null ) {
instance = new SingletonObject();
}
return instance;
}
public int getInstantiationCounter(){
return instantiationCounter;
}
}
To check how does this work you can use the following code:
public static void main(String[] args) {
SingletonObject object = SingletonObject.getInstance();
System.out.println("Object was instantiated: " + object.getInstantiationCounter() + " times.");
object = SingletonObject.getInstance();
System.out.println("Object was instantiated: " + object.getInstantiationCounter() + " times.");
object = SingletonObject.getInstance();
System.out.println("Object was instantiated: " + object.getInstantiationCounter() + " times.");
}
Since you have just started coding won't give you a term like reflection and all.. here is one of the simple way is have a public getter() method.
Consider this simple example
class Something {
private int a=10;
public int getA() {
return a;
}
}
Here is the First which has a public method which return the object that i created in this class for the Something Class
class MyFirstClass {
private Something st;
public MyFirstClass() {
this.st = new Something();
}
public Something getSt() {
return st;
}
}
Accessing it from another Class
class MySecondClass {
public static void main(String...strings ){
MyFirstClass my =new MyFirstClass();
System.out.println(my.getSt().getA());
}
}
Output: 10
If You wan't to verify
Inject this function in MyFirstClass
public void printHashcode(){
System.out.println(st);
}
and then print the hash codes from both methods in MySecondClass
class MySecondClass {
public static void main(String...strings ){
MyFirstClass my =new MyFirstClass();
System.out.println(my.getSt());
my.printHashcode();
}
}
You will see that indeed you are using the Object created in MyFirstClass in MySecondClass.
Because this will give you same hashcode output.
Output On my machine.
Something#2677622b
Something#2677622b
Instead of using the Singleton pattern, a better pattern to use is dependency injection. Essentially, you instantiate the class you want to share, and pass it in the constructor of every class that needs it.
public class MainClass {
public static void main(String[] args) {
SharedClass sharedClass = new SharedClass();
ClassA classA = new ClassA(sharedClass);
ClassB classB = new ClassB(sharedClass);
}
}
public class ClassA {
private SharedClass sharedClass;
public ClassA(SharedClass sharedClass) {
this.sharedClass = sharedClass;
}
}
public class ClassB {
private SharedClass sharedClass;
public ClassB(SharedClass sharedClass) {
this.sharedClass = sharedClass;
}
}
Singleton pattern lets you have single instance which is 'globally' accessible by other classes. This pattern will 'guarantee' that you have only one instance in memory. There are exceptions to one instance benefit, such as when deserializaing from file unless care is taken and readResolve is implemented.
Note that class Something right now has no state(fields), only behavior so it is safe to share between multiple threads. If Something had state, you would need to provide some kind of synchronization mechanism in multi thread environment.
Given such stateless Singleton, it would be better to replace it with class that contains only static methods. That is, unless you are implementing pattern such as Strategy which requires interface implementation, then it would be good idea to cache instance like bellow with Singleton pattern.
You should rework your Something class like this to achieve singleton:
public class Something {
private static final Something INSTANCE = new Something ();
private Something () {
// exists to defeat instantiation
}
public Something getInstance() {
return INSTANCE;
}
public void service() {
//...
}
public void anotherService() {
//..
}
}
If FirstClass and SecondClass are somehow related, you can extract that common object you're using to a super class, and that's the only scope in which you're planning to use this object.
public class SuperClass{
Something st = new Something();
public Something getObjectFromClass(){
return st;
}
}
public class MyFirstClass extends SuperClass{
getObjectFromClass();
}
public class MySecondClass extends SuperClass{
getObjectFromClass();
}
Otherwise, if you plan to use that instance somewhere else you should use a
Singleton object. The easiest way of doing this is:
enum Singleton
{
INSTANCE;
private final Something obj;
Singleton()
{
obj = new Something();
}
public Something getObject()
{
return obj;
}
}
You use it:
Singleton.INSTANCE.getObject();
Okay firstly you can use inheritance e.g.
class MyFirstClass
{
Something st = new Something();
}
class Something()
{
// some code
}
class MySecondClass extends myFirstClass
{
// This is where I want to use the object from class Something()
// like
MySecondClass obj = new MySecondClass();
obj.method(); //Method from myfirstclass accessible from second class object
}
Or if you dont want any objects and just the method you can implement interfaces e.g.
public interface MyFirstClass
{
//example method
public abstract void saying(); //no body required
Something st = new Something();
}
class Something()
{
// some code
}
class MySecondClass implements MyFirstClass //Have to implement methods
{
public void saying(){ //Method implemented from firstClass no obj
System.out.println("Hello World");
}
getObjectFromClass()
}
Is there anyway, when calling a method through an object (instance) for that method to know which instance (object) called it?
Here's an example (pseudo code) of what I mean:
Pseudo code example
public class CustomClass{
public void myMethod(){
if (calling method is object1){
//Do something here
}
else {
//Do something else
}
}//End of method
}//End of class
And then in another class:
public SomeOtherClass{
CustomClass = object1;
public void someOtherMethod(){
object1 = new CustomClass();
object1.myMethod(); //This will call the 1st condition as the calling object is object1, if it were some other object name, it would call the 2nd condition.
}//End of method
}//End of class
Possible work-around
The only way I've found to do this is to get the method to take another argument, say an 'int' and then check the value of that int and perform whichever part of the 'if else' statement relates to it (or 'switch' statement if definitely using an 'int' value) but that just seems a really messy way of doing it.
What you need is the Strategy Pattern
public abstract class CustomClass {
public abstract void MyMethod();
}
public class Impl1 extends CustomClass {
#Override
public void MyMethod() {
// Do something
}
}
public class Impl2 extends CustomClass {
#Override
public void MyMethod() {
// Do something else
}
}
Use it this way
public static void main(String[] args) {
CustomClass myObject = new Impl1();
// or CustomClass myObject = new Impl2();
}
As your comment says what you really need is perhaps the Template method Pattern
public abstract class CustomClass {
public void myMethod(){ // this is the template method
// The common things
theDifferentThings();
}
public abstract void theDifferentThings();
}
public class Impl1 extends CustomClass {
#Override
public void theDifferentThings() {
// Do something
}
}
public class Impl2 extends CustomClass {
#Override
public void theDifferentThings() {
// Do something else
}
}
You can know the name of current class by calling getClass().getName(). However you cannot know the name of object, moreover this does not have any meaning:
MyClass myObject1 = new MyClass();
MyClass myObject2 = myObject1;
myObject1.foo();
myObject2.foo();
Do you wutant foo() to know that it was invoked using myObject1 or myObject1? But both references refer to the same object!
OK, there are extremely complicated ways to know this. You can use byte code engineering using one of popular libraries like javassist, ASM, CGLib and inject missing information about the "object name" into byte code and then read this information. But IMHO this is not what you need.
You can define a new attribute inside CustomClass which will store the identifier of the instance. If there will be only a few instances of CustomClass then you can use an enum type.
Replace:
object1 = new CustomClass();
with:
object1 = new CustomClass(1);
Add a new constructor and an attribute to CustomClass:
private int id;
public CustomClass(int id) {
this.id = id;
}
Then you can replace:
if (calling method is object1){
with:
if (id == 1){
However, please keep in mind that this is a bad design.
You should not have if conditions differing logic depending on the instance which called this method. You should should use polymorphism for such purpose.
I can solve this problem using singleton pattern. But problem is I don't have control on other application which is going to call new MyClass(). Is there any way I can do in implicit constructor of MyClass?. Something like this.
class ClassName {
public ClassName() {
if( object exist for ClassName)
return that
else
create New ClassName object
}
}
Thanks in advance.
You can use a enum:
public enum ClassName {
INSTANCE;
}
Now, you have one instance and you don't have to worry about others instantiating your class.
Is there any way I can do in implicit constructor of MyClass?.
No, that can't be done in a constructor.
If you want to control construction, put in an explicit constructor and declare it private. You can call it from a static factory method, in the class.
This is probably what you want:
public class MySingletonClass {
private static MySingletonClass instance = null;
private MySingletonClass() { }
public static MySingletonClass getInstance() {
if (instance == null) {
instance = new MySingletonClass();
}
return instance;
}
// add your methods here.
}
This way nobody can call new MySingletonClass();. To get the one and only instance of the object you have to write:
MySingletonClass msc = MySingletonClass.getInstance();
or use it somehow like this for void methods:
MySingletonClass.getInstance().yourMethod();
or like this for Methods with a return type:
VariableType foo = MySingletonClass.getInstance().yourMethod(); // Must return VariableType
You would need something like this:
class ClassName {
private static ClassName INSTANCE;
private ClassName() {
//create ClassName object
}
public static ClassName getInstance(){
if (INSTANCE == null){
INSTANCE = new ClassName();
}
return INSTANCE;
}
}
Which is just a basic implementation of the singleton pattern.
If the class that constructs the object HAS to construct it using new, then you are kind of screwed. There is really no way to implement a singleton pattern in Java using only a public constructor.
Edit: You might be able to do something like this:
class ClassNameWrapper extends ClassName {
private final ClassName className;
public ClassNameWrapper(){
className = ClassName.getInstance();
}
//overload methods from ClassName
}
This way, every call to new ClassNameWrapper() will be using the same instance of ClassName.
Create a static variable in your class and hold your object instance there. Expose you class object through a getter method as below:
class ClassName {
private static ClassName myClass= null;
public ClassName getClassName() {
if(myClass == null){
ClassName.myClass = new ClassName();
}
return ClassName.myClass;
}
}
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.)