Java reflections - get level by the class name string - java

I've been looking into Java reflections. This is an example from Wikipedia http://en.wikipedia.org/wiki/Reflection_(computer_programming):
// Without reflection
new Foo().hello();
// With reflection
Class<?> cls = Class.forName("Foo");
cls.getMethod("hello").invoke(cls.newInstance());
I find this a bit counter-intuitive because the method is called before creating an instance.
Reflections of course could be useful to call game leves, especially if there are hundreds of them.
EDIT - SOME SOLUTIONS:
Here is a simple example of reflection which works on Android:
try {
Class<?> clazz = Class.forName("com.test.Foo");
clazz.newInstance();
} catch (Exception e) {
throw new IllegalStateException(e);
}
and the class file
public class Foo {
Foo(){
hello();
}
private void hello() {
Log.e("FOO", "Hello!");
}
}
Suppose one wants to call an Activity by reflection:
Activity activity;
try {
Class<?> clazz = Class.forName("com.test.MyLevelActivity");
activity = (Activity) clazz.newInstance();
} catch (Exception e) {
throw new IllegalStateException(e);
}
startActivity(new Intent(this,activity.getClass()));
Suppose a level which contains data and methods should be 'loaded' by reflection:
Level currentLevel;
try {
Class<?> clazz = Class.forName("com.test.Level_1_1");
currentLevel = (Level) clazz.newInstance();
} catch (Exception e) {
throw new IllegalStateException(e);
}
String levelName = currentLevel.getLevelName();
String result = Integer.toString(currentLevel.processData(3, 7));
Toast.makeText(this, levelName + " result= " + result, Toast.LENGTH_LONG).show();
Here are the classes:
public abstract class Level {
public abstract String getLevelName();
public abstract int processData(int a, int b);
}
public class Level_1_1 extends Level{
private String levelName = "level 1.1";
public String getLevelName(){
return levelName;
}
public int processData(int a, int b) {
return a * b;
}
}

I find this a bit counter-intuitive because the method is called before creating an instance
Sorry, don't think so. The method arguments are first evaluated before being passed to "invoke" and hence you end up passing a "new" instance of the Foo class to the "invoke" method of the Method class. Also, in case you are wondering why call "invoke" on method object, it's because for a given class, you'd create the Method objects only once and all subsequent invocations would rather depend on the "state" of the object rather than the "method" being invoked.

here
foo.hello();
can't work, foo is just an object that does not have a method hello().
Things that are unfamiliar may seem counter-intuitive, but eventually new idioms become natural. Just go with the standard approach.
To understand it, consider that the method definition is not part of the object, you write the method once for the class, it "lives" independently of any given object. Hence it's quite reasonable for the class to say "hey method, apply yourself in the context of this object, he's one of us"

It's not really clear what you mean, but does this help?
Class<?> cls = Class.forName("Foo");
Method method = cls.getMethod("hello");
Object instance = cls.newInstance();
method.invoke(instance);

you are not calling the method first. you are just definig the method and then invoking it. also, the instance of cls is created before we actually enter invoke. I find the reflections to be a very useful API in java and it is used by almost all the framworks that work on java like struts, log4j, etc. In reflection you always define the method you wanna call and only then work on the actual object you wanna operate on.
Hope this helps!

Related

How to return an object from different classes in Java?

I'm beginner in Java and I need help. I have several classes.
public class A{
private String name = "A";
public String getClassName(){
return "A";
}
public void editClassName(String name){
this.name = name;
}
}
public class B{
private String name = "B";
private int counter = 0;
public String showClassName(){
return "B";
}
public int getCount(){
return counter;
}
}
Such classes could be more. I also need to have some class witch can return an instance of asked class.
public class ClassSelector{
public static ??? getClassByName(String nameOfClass){
if(nameOfClass == "A"){ return new A();}
if(nameOfClass == "B"){ return new B();}
}
}
And here is a code that I want to use to get access to appropriate class:
ClassSelector.getClassByName("A").getClassName();
ClassSelector.getClassByName("B").showClassName();
I need to have an access to the instance of the class, and each instance can show it's unit methods that class has.
In this situation I don't get which return type I should use in the 'getClassByName' method.
I will very appreciate for help.
I would very much like to offer an alternative architecture if possible! It's not much different to what you have.
Firstly, we'll define some interface.
public interface Named {
String getName();
}
Now, this means you can have lots of concrete classes but provided they implement this interface, you'll know (and the Java compiler will know) that they have the getName method available to you.
Next, let's update your class to implement this interface.
public class A implements Named {
public String getName() {
return "A";
}
}
You could do this for classes B, C... and so on.
Now your method return type can be set to Named, that is:
public class ClassSelector{
public static Named getClassByName(String nameOfClass){
if(nameOfClass.equals("A")){ return new A();}
if(nameOfClass.equals("B")){ return new B();}
}
}
And you can access the response like so:
Named response = ClassSelector.getClassByName("A").getName();
As Eran suggested, it can be only of type Object, because they don't have a common superclass other than Object. If you don't want to work with Object class, you can create a body-less interface and implement it in both(or multiple classes) and that can be your return type.
After the call of the method, you can find the specific type of the returned object with instanceof;
What you are trying to do is called the Factory Pattern.
Assuming you are crating Widgets I suggest;
Introduce a Widget interface and have A and B implement Widget as per Christopher’s answer
Rename ClassSelector to WidgetFactory
Rename the method getClassByName to create, make it non-static and return Widget instances
This is more aligned with common Java name conventions and thus makes your code readily understandable by most developers.
If you want to keep your factory static it is of course possible but it may make your code less testable as it cannot be switched out for another factory in your tests. This is problematic if A and B are heavy weight objects that carries a lot of external dependencies that you may want to exclude.
If testability is a concern you may even consider making the factory implement a WidgetFactory interface...
First of all, please note that for string comparison you have not to use "==" (the problem is in nameOfClass == "A" and so on, I say it only for completeness).
I want suggest a solution based on reflection, that maybe could be more concise:
public interface IClass {
}
public class A implements IClass {
private String name = "A";
}
public class B implements IClass {
private String name = "B";
}
public class ClassSelector {
public static void main(String[] args) {
IClass obj = null;
try {
Class c = Class.forName("A");
obj = (IClass) c.newInstance();
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException e) {
e.printStackTrace();
}
System.out.println("Create object of type " + obj.getClass());
}
}
Thanks to all guys, who have answered my. Forgive me, when I create the first post, I made one mistake, which leads to misunderstanding what I mean. Now the code in the first post is better to show what I'm looking for.

Call method of unknown object

I have two ArrayLists - ArrayList1 and ArrayList2. Each of them is filled with objects - Object1 and Object2, respectively.
Both of these objects have method 'getText'.
Object1:
public String getText() { return "1";}
Object2:
public String getText() { return "2";}
At certain point I would like to loop through each of these lists using the same method (just with different parameter).
loopThroughList(1)
loopThroughList(2)
What is the syntax if I want to call a method, but I don't know which object it is going to be? This is the code I have so far:
for (Object o : lists.getList(listNumber)) {
System.out.println(o.getText());
}
It says Cannot resolve method getText. I googled around and found another solution:
for (Object o : lists.getList(listNumber)) {
System.out.println(o.getClass().getMethod("getText"));
}
But this gives me NoSuchMethodException error. Even though the 'getText' method is public.
EDIT: To get the correct list, I am calling the method 'getList' of a different object (lists) that returns either ArrayList1 or ArrayList2 (depending on the provided parameter).
class Lists
public getList(list) {
if (list == 1) {
return ArrayList1;
}
else if (list == 2) {
return ArrayList2;
}
}
Define an interface for the getText method
public interface YourInterface {
String getText();
}
Implement the interface on the respective classes
public class Object1 implements YourInterface {
#Override
public String getText() {
return "1";
}
}
public class Object2 implements YourInterface {
#Override
public String getText() {
return "2";
}
}
Modify your getList method to return List<YourInterface>
public static List<YourInterface> getList(int list){
List<YourInterface> result = new ArrayList<>();
if(list == 1){
// your initial type
List<Object1> firstList = new ArrayList<>();
result.addAll(firstList);
} else {
// your initial type
List<Object2> secondList = new ArrayList<>();
result.addAll(secondList);
}
return result;
}
Declaration for loopThroughList
public static void loopThroughList(List<YourInterface> list){
list.forEach(yourInterface -> System.out.println(yourInterface.getText()));
}
Sample usage.
public static void main(String[] args) {
loopThroughList(getList(1));
loopThroughList(getList(2));
}
Interfaces work great here, but there a couple of other options if you're dealing with legacy code and cannot use interfaces.
First would be to cast the list items into their respective types:
for (Object o : lists.getList(listNumber)) {
if(o instanceof Object1) {
Object1 o1 = (Object1)o;
System.out.println(o1.getText());
}
else if(o instanceof Object2) {
Object1 o2 = (Object2)o;
System.out.println(o2.getText());
}
else {
System.out.println("Unknown class");
}
}
You can also use reflection to see if the object has a getText method and then invoke it:
for (Object o : lists.getList(listNumber)) {
try {
System.out.println(o.getClass().getDeclaredMethod("getName").invoke(o));
}
catch(Exception e) {
System.out.println("Object doesn't have getText method");
}
}
This is awful. Can you elaborate on what specifically you are trying to do? Java is strong typed by design, and you are trying to get around it. Why? Instead of Object, use the specific class, or interface as previously suggested. If that's not possible, and you must use lists of Objects, use instanceof and casting eg:
for (Object o : lists.getList(listNumber)) {
if (o instanceof Object1) {
Object1 o1 = (Object1) o;
System.out.println(o1.getText());
} else if (o instanceof Object2) {
Object2 o2 = (Object2) o;
System.out.println(o2.getText());
}
}
This is where interfaces come in.
interface HasText {
public String getText();
}
class Object1 implements HasText {
#Override
public String getText() {
return "1";
}
}
class Object2 implements HasText {
#Override
public String getText() {
return "2";
}
}
private void test() {
List<HasText> list = Arrays.asList(new Object1(), new Object2());
for (HasText ht : list) {
System.out.println(ht);
}
}
If one of your objects is not in your control you can use a Wrapper class.
class Object3DoesNotImplementHasText {
public String getText() {
return "3";
}
}
class Object3Wrapper implements HasText{
final Object3DoesNotImplementHasText it;
public Object3Wrapper(Object3DoesNotImplementHasText it) {
this.it = it;
}
#Override
public String getText() {
return it.getText();
}
}
private void test() {
List<HasText> list = Arrays.asList(new Object1(), new Object2(), new Object3Wrapper(new Object3DoesNotImplementHasText()));
for (HasText ht : list) {
System.out.println(ht);
}
}
Just to add more to this answer and give you some more to think on this (Will try to do it in a simple, non-formal way). Using interfaces is the proper way of doing such operation. However, I want to stand on the "bad idea":
for (Object o : lists.getList(listNumber)) {
System.out.println(o.getClass().getMethod("getText"));
}
What you are doing here, is using a mechanism called Reflection:
Reflection is a feature in the Java programming language. It allows an
executing Java program to examine or "introspect" upon itself, and
manipulate internal properties of the program. For example, it's
possible for a Java class to obtain the names of all its members and
display them.
What you actually attempted, is using that mechanism, to retrieve the method through a Class reflection object instance of your Class (sounds weird, isn't it?).
From that perspective, you need to think that, if you want to invoke your method, you now have, in a sense, a meta-Class instance to manipulate your objects. Think of it like an Object that is one step above your Objects (Similarly to a dream inside a dream, in Inception). In that sense, you need to retrieve the method, and then invoke it in a different (meta-like) way:
java.lang.reflect.Method m = o.getClass().getMethod("getText");
m.invoke(o);
Using that logic, you could possibly iterate through the object list, check if method exists, then invoke your method.
This is though a bad, BAD idea.
Why? Well, the answer relies on reflection itself: reflection is directly associated with runtime - i.e. when the program executes, practically doing all things at runtime, bypassing the compilation world.
In other words, by doing this, you are bypassing the compilation error mechanism of Java, allowing such errors happen in runtime. This can lead to unstable behavior of the program while executing - apart from the performance overhead using Reflection, which will not analyze here.
Side note: While using reflection will require the usage of Checked Exception handling, it still is not a good idea of doing this - as you practically try to duck tape a bad solution.
On the other hand, you can follow the Inheritance mechanism of Java through Classes and Interfaces - define an interface with your method (let's call it Textable), make sure that your classes implement it, and then use it as your base object in your list declaration (#alexrolea has implemented this in his answer, as also #OldCurmudgeon has).
This way, your program will still make the method call decision making at Runtime (via a mechanism called late binding), but you will not bypass the compilation error mechanism of Java. Think about it: what would happen if you define a Textable implementation without providing the class - a compile error! And what if you set a non-Textable object into the list of Textables? Guess what! A compile error again. And the list goes on....
In general, avoid using Reflection when you are able to do so. Reflection is useful in some cases that you need to handle your program in such a meta-way and there is no other way of making such things. This is not the case though.
UPDATE: As suggested by some answers, you can use instanceof to check if you have a specific Class object instance that contains your method, then invoke respectively. While this seems a simple solution, it is bad in terms of scaling: what if you have 1000 different classes that implement the same method you want to call?
your objects have to implement a common interface.
interface GetTextable {
String getText();
}
class One implements GetTextable {
private final String text;
public One(final String text) {
this.text = text;
}
public String getText() {
return this.text;
}
}
class Two implements GetTextable {
private final String text;
public Two(final String text) {
this.text = text;
}
public String getText() {
return this.text;
}
}
#Test
public void shouldIterate() throws Exception {
List<GetTextable> toIterate = Arrays.asList(new One("oneText"), new Two("twoText"));
for(GetTextable obj: toIterate) {
System.out.println(obj.getText());
}
}

Is there a way to instantiate a child class with parent object in java?

I have a base class say
class A {
private String name;
private String age;
//setters and getters for same
}
and a child class say
class B extends A {
private String phone;
private String address;
//setters and getters for same
}
now I've an instance of A and besides this I have to set the fields in B as well, so code would be like,
A instanceOfA = gotAFromSomewhere();
B instanceOfB = constructBFrom(instanceOfA);
instanceOfB.setPhone(getPhoneFromSomewhere());
instanceOfB.setAddress(getAddressFromSomewhere());
can I instantiate B with given A, but I don't want to do this way,
B constructBFrom(A instanceOfA) {
final B instanceOfB = new B();
instanceOfB.setName(instanceOfA.getName());
instanceOfB.setPhone(instanceOfA.getAge());
return B;
}
rather what I'd love to have some utility with function which is generic enough to construct object as in,
public class SomeUtility {
public static <T1, T2> T2 constructFrom(T1 instanceOfT1, Class<T2> className) {
T2 instatnceOfT2 = null;
try {
instatnceOfT2 = className.newInstance();
/*
* Identifies the fields in instanceOfT1 which has same name in T2
* and sets only these fields and leaves the other fields as it is.
*/
} catch (InstantiationException | IllegalAccessException e) {
// handle exception
}
return instatnceOfT2;
}
}
so that I can use it as,
B constructBFrom(A instanceOfA) {
return SomeUtility.constructFrom(instanceOfA, B.class);
}
Moreover, use case will not be only limited to parent-child classes, rather this utility function can be used for adapter use cases.
PS- A and B are third party classes I've to use these classes only so I can't do any modifications
in A and B.
The good practice is to have a factory class which "produces" the instances of B.
public class BFactory {
public B createBFromA(A a) { ... }
}
You have to write the code of the factory method as there is no standard way of creating a child class based on its parent class. It's always specific and depends on the logic of your classes.
However, consider if it is really what you need. There are not many smart use cases for instantiating a class based on the instance of its parent. One good example is ArrayList(Collection c) - constructs a specific list ("child") containing the elements of the generic collection ("base").
Actually, for many situation there is a pattern to avoid such strange constructs. I am aware it's probably not applicable to your specific case as you wrote that your Base and Child are 3rd party classes. However your question title was generic enough so I think you may find the following useful.
Create an interface IBase
Let the class Base implement the interface
Use composition instead of inheritance - let Child use Base instead of inheriting it
Let Child implement IBase and delegate all the methods from IBase to the instance of Base
Your code will look like this:
public interface IBase {
String getName();
int getAge();
}
public class Base implements IBase {
private String name;
private int age;
// getters implementing IBase
}
public class Child implements IBase {
// composition:
final private IBase base;
public Child(IBase base) {
this.base = base;
}
// delegation:
public String getName() {
return base.getName();
}
public int getAge() {
return base.getAge();
}
}
After you edited your question, I doubt even stronger that what you want is good. Your question looks more like an attempt of a hack, of violating (or not understanding) the principles of class-based object oriented concept. Sounds to me like someone coming from the JavaScript word and trying to keep the JavaScript programming style and just use a different syntax of Java, instead of adopting a different language philosophy.
Fun-fact: Instantiating a child object with parent object is possible in prototype-based languages, see the example in JavaScript 1.8.5:
var base = {one: 1, two: 2};
var child = Object.create(base);
child.three = 3;
child.one; // 1
child.two; // 2
child.three; // 3
In my opinion the way you want to avoid is very appropriate. There must be a piece of such code somewhere.
If you can't put that method in the target class just put it somewhere else (some factory). You should additionaly make your method static.
Take a look at Factory method pattern.
2nd option would be extending B and place this method as factory static method in that new class. But this solution seems to be more complicated for me. Then you could call NewB.fromA(A). You should be able then use your NewB instead of B then.
You could do it via reflection:
public static void copyFields(Object source, Object target) {
Field[] fieldsSource = source.getClass().getFields();
Field[] fieldsTarget = target.getClass().getFields();
for (Field fieldTarget : fieldsTarget)
{
for (Field fieldSource : fieldsSource)
{
if (fieldTarget.getName().equals(fieldSource.getName()))
{
try
{
fieldTarget.set(target, fieldSource.get(source));
}
catch (SecurityException e)
{
}
catch (IllegalArgumentException e)
{
}
catch (IllegalAccessException e)
{
}
break;
}
}
}
}
*Above code copied from online tutorial

How to Avoid Constructor calling During Object Creation?

I want to avoid the constructor calling during object creation in java (either default constructor or user defined constructor) . Is it possible to avoid constructor calling during object creation???
Thanks in advance......
Simply extract the intialization logic that you want to avoid into another method called init. You can not avoid calling exactly one constructor.
No matter what pattern or strategy you use, at some point your will need to call a constructor if you want to create an object.
Actually, its possible under some circumstances by using classes from the JVM implementation (which do not belong to the JRE API and are implemenation specific).
One example here http://www.javaspecialists.eu/archive/Issue175.html
It should also be possible using sun.misc.Unsafe.allocateInstance() (Java7)
Also, the constructor is apparently bypassed when using the clone()-method to create a copy of an object (and the class doesn't override clone to implement it different from the Object.clone() method).
All of these possibilities come with strings attached and should be used carefully, if at all.
You can mock the constructors of a class. They will still be called, but not executed. For example, the following JUnit+JMockit test does that:
static class CodeUnderTest
{
private final SomeDependency someDep = new SomeDependency(123, "abc");
int doSomething(String s)
{
someDep.doSomethingElse(s);
return someDep.getValue();
}
}
static final class SomeDependency
{
SomeDependency(int i, String s) { throw new RuntimeException("won't run"); }
int getValue() { return -1; }
}
#Test
public void mockEntireClassIncludingItsConstructors()
{
new NonStrictExpectations() {
#Mocked SomeDependency mockDep;
{ mockDep.getValue(); result = 123; }
};
int result = new CodeUnderTest().doSomething("testing");
assertEquals(123, result);
}

Error when using Reflections in Java

I'm having a casting issue in this code but have no idea how to correct it.
public void showFrame(String className, Object controller) throws Exception{
try {
Class c = Class.forName("com." + className);
// "(Object.class)" I want this to be of type held in className var
// this type will be same as one passed into "controller" at runtime
Constructor ctr = c.getConstructor(Object.class);
ctr.newInstance(controller);
} catch (ClassNotFoundException ex) {
JOptionPane.showMessageDialog(null, "Error" );
}
}
getConstructor selects from the possible existing constructors for the class in question.
If your class name looks like:
com.mycorp.SomeClass
and it doesn't have a
public SomeClass(Object object) {
...
}
constructor, then ctr will be null. If it does have such a constructor, then asking for a new instance without providing a value for the Object parameter is just asking for trouble.
In addition, you are only catching if the class doesn't exist, not of the constructor can't be found, or if the security manager denies new class creation, or if the constructor is getting called with the wrong number of parameters, etc.

Categories

Resources