call getter of property after getting value from variable - java

I am trying to call getter method on object but which getter to call depends on the value in a variable.
public void met1(String var) {
MyClass m = new MyClass();
if(var.equals("A"))
m.getA();
if(var.equals("B"))
m.getB();
if(var.equals("C"))
m.getC();
}
This is one way. Another could be using switch but I don't want to hardcode values as they may change. Is there any better way of doing this?

String is a class not a primitive type, you can't compare instances of String class like var using == this will not work!!!
You need to use method equals like: if(var.equals("A")) then ... .
Apart form that this way is fine.
Another way would be using reflection without if-statement:
Class<?> c = Class.forName("MyClass");
Object my_object = c.newInstance();
Method setNameMethod = my_object.getClass().getMethod("get"+var,String.class);
setNameMethod.invoke(my_object, var);

Related

difference between 'Class<?>' and 'Object' as argument of method

Assume i want to have a method that get an object of any type in my application to validate all fields it has (each object has different fields with different types) and wrap it to a message. so the method input argument would be instance of any object
Now my question is :
what's the difference between having this input argument as an Object or Class<?> ?
as i know ? means 'any type or class' and 'Object' is a super type in java .
i appreciate if Someone could explain me in which cases better to use this :
public validateAndConvertAnyObject(Object obj) {
// compute and return a message
}
and when it's better to use this ?
public validateAndConvertAnyObject(Class<?> obj) {
// compute and return a message
}
First you don't specify a return type in your method.
It is not valid.
Second, these two parameters are totally different.
public validateAndConvertAnyObject(Object obj)
can accept any object.
While public validateAndConvertAnyObject(Class<?> obj)
can accept any class.
The equivalent of
public validateAndConvertAnyObject(Object obj)
with generic would be :
public <T> void validateAndConvertAnyObject(T obj){
After compilation and type erasure, these provide the same compiled class.
So in this example, using Object makes more sense as more explicit.
To convert an instance to another class with reflection, generally, you pass the target class :
public <T> T validateAndConvertAnyObject(Object obj, Class<T> targetClass){
...//processing on obj
}
And you could use it :
MyObject myObject = ...;
MyOtherClass myOtherClass = validateAndConvertAnyObject(myObject, MyOtherClass.class);
The first method can be called with any object as an argument, eg "foo", 42 or Integer.class. The second one will only accept class objects, eg "foo".getClass() or String.class
What is the difference between Class<?> and Object
Object
This takes the instance as a parameter
Class<?>
This takes a class as a parameter
Example
Object could be equal to String, and for a similar result you could have Class<?> equal to java.lang.String.
Confusion
Technically, you could pass an instance of Class<?> as an Object, which adds confusion, which is a good reason to use Class<?> instead, as it prevents mixing up the instance and it's class.
Object actually represents an instance of a created object like:
String text = "Hello World!";
Object textAsObj = (Object) text;
Whereas Class only represents the class of objects, it has no connection to an actual instance of this class:
Class<?> textClass = Class.forName("java.util.String");
So you should probably use the Object variant if you want to access specific values of an instance. You can, at anytime, retrieve the class from an Object using the getClass method:
String text = "Hello World!";
Class<String> textClass = text.getClass();
And here is an example how you could use that to access a field of a given Object:
Person person = new Person("John Doe");
Class<Person> personClass = person.getClass();
Field nameField = personClass.getDeclaredField("name");
String name = (String) nameField.get(person);

How to get access to existing objects with string input (Convert string input to objectname)

I am creating a lot of objects called: Obj1, Obj2.... ObjX
Object Obj1 = new Object();
Object Obj2 = new Object();
Object ObjX = new Object();
Now I am having a function where I want to get access to one of this objects.
public void useObject(int objectNumber) {
String objectName = "Obj" + objectNumber;
objectName.doAnythingWithThisObject();
}
Is something like that possible in C# or Java? I don't want to use something like:
switch(objectNumber) {
case 1:
Obj1.doThis();
break;
case 2:
Obj2.doThis();
break;
If I would use switch/if-else then I have to repeat a lot of code which make this thing less readable, because I have to call the same function with different objects.
The actual answer is: you shouldn't, generally speaking, access your variables, using strings at runtime. Cases where this is actually appropriate are few and far between and your example, simplified though it may be for illustration purposes, is not a good match for it.
Instead, why don't you simply use a collection or an array to store your objects? #T.R.Rohith gives an example in their answer.
Still, the direct answer to your question, as it applies to Java, is given below. While the code would be different for C#, the language feature, which can be used for this purpose, namely, reflection, is available in C# as well.
If Obj1, Obj2 etc. are declared as static or instance fields in a class, you can get their values by their names using reflection (see relevant docs for Java). If they are local to a method, there is no simple way to do so (see these questions: for Java, for C#).
Static fields
class Something {
static Object obj1 = new Object();
static Object obj2 = new Object();
// etc.
}
(I've taken the liberty of starting field names with lowercase letters, as it the accepted practice in Java.)
In this case you can get the value of the variable by its name using the following code (you need to import java.lang.reflect.Field):
// Get field, named obj1, from class Something.
Field f = Something.class.getDeclaredField("obj1");
// This line allows you access the value of an inaccessible (non-public) field.
f.setAccessible(true);
// Assigning the value of the field, named obj1, to obj.
// You may want to cast to a more concrete type, if you know exactly what is stored in obj1.
// The parameter for get() is ignored for static fields, so simply pass null.
Object obj = f.get(null);
// Now you can do whatever you want with obj,
// which refers to the same object as static field obj1 of Something.
System.out.println(obj);
Instance fields
class Something {
Object obj1 = new Object();
Object obj2 = new Object();
// etc.
}
You can do it in almost exactly the same way for instance fields, you just need an instance of the class to pass to f.get(). So, for the sake of example, let's assume we have an instance of class Something, called sth.
// Let's say this is an instance of our class
Something sth = new Something();
// ...
// Get field, named obj1, from class Something.
Field f = Something.class.getDeclaredField("obj1");
// This line allows you access the value of an inaccessible (non-public) field.
f.setAccessible(true);
// Assigning the value of the field, named obj1, to obj.
// You may want to cast to a more concrete type, if you know exactly what is stored in obj1.
// The parameter for get() is the instance of Something,
// for which you want to retrieve the value of an instance field, named obj1.
Object obj = f.get(sth);
// Now you can do whatever you want with obj,
// which refers to the same object as instance field obj1 of sth.
System.out.println(obj);
Local variables
You are probably out of luck in this case. Again, see the following links: Java, C#.
This sounds like a classic Strategy pattern problem Strategy Design Pattern
Here's the code:
//Declare this in the class so that it can be called by any method
static Object[] array = new Object[4];
public static void main()
{
//Use this to initialize it
Object[] array = new Object[4];
for(int i=0;i<4;i++)
{
array[i] = new Object();
}
//You can now easily call it
useObject(0);
useObject(1);
useObject(2);
useObject(3);
}
//Your numbers may be off by 1 because we are using an array but that is easily adjusted
public static void useObject(int objectNumber)
{
array[objectNumber].doAnythingWithThisObject();
}
The answer is... don't. Use an array instead. This is exactly what they're for.
ObjectType[] objectArray = new ObjectType[10]; // Or as many as required.
for (int i = 0; i < objectArray.length; i++) {
objectArray[i] = new ObjectType(); // Or whatever constructor you need.
}
// Then access an individual object like this...
ObjectType obj = objectArray[4];
// Or...
objectArray[5].someMethod();

Define a variable type another variable in Java

I have some classes and for some reason I need a procedure that create some variables of that class dinamically...
Let's assume I have this code:
for (int i = 0 ; i < 5 ; i++)
{
....
POP tmp = new POP();
tmp = (POP) ast.convert(aso, POP.class);
}
I want that the POP class is set dinamically... I almost achieved what I want except for the casting from object to class, I do not know how to write it...
String className = "POP";
Class cl = Class.forName(className);
Class cl2 = POP.class;
cl = (??????) ast.convert(aso, cl2);
How can I solve it?
In your second code snippet, cl will actually be Class<POP> but cl2 is Class<String>, which I guess is not what you expect. Assuming you are coding in Java 5 or newer, you should not use the raw types (Class instead of Class<?>), this will make your code safer and easier to read.
Also note that you have to use the fully qualified class name, and not just the simple name of your classes. For example
Class.forName("String"); // Won't work
Class.forName("java.lang.String"); // Is what you need.
When you have a Class instance you can use reflection to create new instances dynamically:
Class<?> cl2 = ... ;
// If the class has a no-arg visible constructor
Object foo = cl2.newInstance();
// Or using an explicit constructor (here with an integer and a String as arguments)
Constructor<Class<?>> cons = cl2.getConstructor(Integer.class, String.class);
Object bar = cons.newInstance(1, "baz");
But maybe what you are trying to achieve could be done using the Abstract Factory pattern ? You provide an object that is able to create instances of the type that you want, and you can choose the factory to use based on the class name.
http://c2.com/cgi/wiki/wiki?AbstractFactoryPattern

Dynamically create and cast objects at runtime

Let's say we have 2 classes A and B
public class A{
private int member1;
A() {
member1 = 10;
}
public getMember(){
return member1;
}
}
Class B is also on the same lines except that its member variable is named member2 and gets intitialized to say 20 inside the constructor.
My Requirement :
At runtime , I get a string which contains a className ( could be A or B). I want to dynamically create an object of this class along with invoking the constructor. How can I achieve this . I don't want to use interfaces for common functionality of above classes Morever, later on I set the properties of this raw object using Propery Builder Bean Util class based on a list of columns .
Class clazz = Class.forName("className");
Obj obj = clazz.newInstance();
How I can dynamically convert that obj to className object.
How can I achieve this . I don't want to use interfaces for common functionality of above classes
Then the answer is very simple and you won’t like it: you can’t. You want to modify the static type of the variables which is, by definition, determined at compile time. Changing it at runtime is not possible.
What do you mean with "dynamically convert"? It IS an object of type "className", stored in a variable of type Object. If you want to use it as an object of type A, you have to cast it, and for example store it in a variable of type A.
Class Class has a cast method which at first sight seems to be doing just what you want. So you could try
... = clazz.cast(obj);
but what would be the return type??? It should be either A or B, but you can't declare a variable dynamically...
So I see no other way than the ugly, but tried and true
if (obj instanceof A) {
A a = (A) obj;
...
} else if (obj instanceof B) {
B b = (B) obj;
...
}
Note that if with bean introspection, you can always see the actual dynamic type and internals of the object, so I see not much point trying to get a static reference of the right type to it.

See if an object is an instance of a class passed through a string

I imagine that there has to be some way to use reflection to do what I want to do.
I need to be able to take a string at runtime that is of a certain class, for example:
string s = "mypackage.MySuperClass"
Then I may have an object of some type. It could be one of the following:
mypackage.MySuperClass obj = new mypackage.MySuperClass();
or
mypackage.MySubClass obj2 = new mypackage.MySubClass();
or
someotherpackage.SomeOtherClass obj3 = new someotherpackage.SomeOtherClass();
What I need to do is see if an object (which its type is determined at runtime), is equal to the string s (which is also determined at runtime via completely different means).
In the cases above I would want obj and obj2 to be the same type as s (since MySubClass is a subclass of MySuperClass), and obj3 would not.
Is there an easy way to do this in java? Possibly something using instanceOf?
Sounds like you want something like this:
boolean isInstance(Object o, String className) {
try {
Class clazz = Class.forName(className);
return clazz.isInstance(o);
} catch (ClassNotFoundException ex) {
return false;
}
}
Or you could do it the other way round - take o's class (o.getClass()), find all ancestor classes and compare their names to className.
You can use Class.forName(String className) to get the Class based on the string value passed in.
If all you're concerned with is whether it is an instance of a particular class, you can then call isInstance(Object o) on the Class to test whether a the parameter is an instance of the class.
If you actually need an object of the class, you can call newInstance() on the Class. You can then test the resulting object with instanceOf against another object.

Categories