i have a problem with a newInstance call using Reflection in Android.
My Interface:
public interface IGiver {
public int getNr();
}
My Class to call Reflection:
public class NrGiver implements IGiver {
int i = 10;
#Override
public int getNr() {
return i;
}
}
The way i try to call getNr:
String packageName = "de.package";
String className = "de.package.NrGiver";
String apkName = getPackageManager().getApplicationInfo(packageName, 0).sourceDir;
PathClassLoader myClassLoader =
new dalvik.system.PathClassLoader(
apkName,
ClassLoader.getSystemClassLoader());
Class c = Class.forName(className);
IGiver giver = (IGiver) c.newInstance();
The last line wont work it cause an Error and my App stops.
I know it fault of newInstance, but i want to work on the IGiver object.
Pls Help me.
My Solution:
Hey guys finally i got the chicken.
I found an other way. this time i also used newInstance, but this time its worked.
My solution:
Class c = Class.forName(className);
Method methode = c.getDeclaredMethod("getNr");
Object i = methode.invoke(c.newInstance(), new Object[]{});
And this what i wanted to do.
I have an NrGiver.class somewhere on my Phone. And it implements the Interface IGiver. So it can be loaded into my App dynamically. I need the Integer from the class NrGiver. So i can make my code generic. I tried to Cast the Object to my Interface, but it failed.
So i found an other way to invoke the method of a class.
Thx for help
String className = "de.package.NrGiver";//line 1
Class c = Class.forName(className);//line 2
IGiver giver = (IGiver) c.newInstance();//line3
in line 2 forName is trying to find a class but the String is representing a Interface, so the classLoader does not find the class and it throws an exception. adding on to it, in line 3 you are trying to get an Instance of Interface which does't exist in the java world.. i mean to say Interfaces cannot be instanciated and they do not have constructors..
not sure why is classloader used. if both IGiver and NrGiver are loaded:
Class k = NrGiver.class;
IGiver g = (IGiver)k.newInstance();
Related
I am making a program that lets the user call a class, like it takes a string input, then calls the run() method of that class, is there any way to do that? I was hoping something like:
String inp=new Scanner(System.in).nextLine();
Class cl=new Class(inp);
cl.run();
I know that the code isn't correct, but that is my main idea
Creating and using a class by name requires some preconditions:
Full name of the class must be used, including package name.
You need to know the parameters of the constructor. Usually the no-arguments constructor is used for a such use case.
(Optional) You need an interface this class must implement which declares the method "run" (or any other methods you want to use).
An example with a subclass of Runnable:
String className = "some.classname.comes.from.Client";
Class<Runnable> clazz = (Class<Runnable>) Class.forName(className);
Runnable instance = clazz.getConstructor().newInstance();
instance.run();
If you don't have a common interface, you can invoke the method using reflection:
Class<Object> clazz = (Class<Object>) Class.forName(className);
Object instance = clazz.getConstructor().newInstance();
clazz.getMethod("run").invoke(instance);
or using method with parameters:
Integer p1 = 1;
int p2 = 2;
clazz.getMethod("methodWithParams", Integer.class, Integer.TYPE).invoke(instance, p1, p2);
String Variable can't be a reference for the Class.
to to a something like changing the object depends on the input
you can use polymorphism and design patterns (Factory Pattern)
I was looking as the question : Instantiate a class from its string name which describes how to instantiate a class when having its name. Is there a way to do it in Java? I will have the package name and class name and I need to be able to create an object having that particular name.
Two ways:
Method 1 - only for classes having a no-arg constructor
If your class has a no-arg constructor, you can get a Class object using Class.forName() and use the newInstance() method to create an instance (though beware that this method is often considered evil because it can defeat Java's checked exceptions).
For example:
Class<?> clazz = Class.forName("java.util.Date");
Object date = clazz.newInstance();
Method 2
An alternative safer approach which also works if the class doesn't have any no-arg constructors is to query your class object to get its Constructor object and call a newInstance() method on this object:
Class<?> clazz = Class.forName("com.foo.MyClass");
Constructor<?> constructor = clazz.getConstructor(String.class, Integer.class);
Object instance = constructor.newInstance("stringparam", 42);
Both methods are known as reflection. You will typically have to catch the various exceptions which can occur, including things like:
the JVM can't find or can't load your class
the class you're trying to instantiate doesn't have the right sort of constructors
the constructor itself threw an exception
the constructor you're trying to invoke isn't public
a security manager has been installed and is preventing reflection from occurring
MyClass myInstance = (MyClass) Class.forName("MyClass").newInstance();
Using newInstance() directly is deprecated as of Java 8. You need to use Class.getDeclaredConstructor(...).newInstance(...) with the corresponding exceptions.
To make it easier to get the fully qualified name of a class in order to create an instance using Class.forName(...), one could use the Class.getName() method. Something like:
class ObjectMaker {
// Constructor, fields, initialization, etc...
public Object makeObject(Class<?> clazz) {
Object o = null;
try {
o = Class.forName(clazz.getName()).newInstance();
} catch (ClassNotFoundException e) {
// There may be other exceptions to throw here,
// but I'm writing this from memory.
e.printStackTrace();
}
return o;
}
}
Then you can cast the object you get back to whatever class you pass to makeObject(...):
Data d = (Data) objectMaker.makeObject(Data.class);
use Class.forName("String name of class").newInstance();
Class.forName("A").newInstance();
This will cause class named A initialized.
Use java reflection
Creating New Objects
There is no equivalent to method invocation for constructors, because invoking a constructor is equivalent to creating a new object (to be the most precise, creating a new object involves both memory allocation and object construction). So the nearest equivalent to the previous example is to say:
import java.lang.reflect.*;
public class constructor2 {
public constructor2()
{
}
public constructor2(int a, int b)
{
System.out.println(
"a = " + a + " b = " + b);
}
public static void main(String args[])
{
try {
Class cls = Class.forName("constructor2");
Class partypes[] = new Class[2];
partypes[0] = Integer.TYPE;
partypes[1] = Integer.TYPE;
Constructor ct
= cls.getConstructor(partypes);
Object arglist[] = new Object[2];
arglist[0] = new Integer(37);
arglist[1] = new Integer(47);
Object retobj = ct.newInstance(arglist);
}
catch (Throwable e) {
System.err.println(e);
}
}
}
which finds a constructor that handles the specified parameter types and invokes it, to create a new instance of the object. The value of this approach is that it's purely dynamic, with constructor lookup and invocation at execution time, rather than at compilation time.
Class.forName("ClassName") will solve your purpose.
Class class1 = Class.forName(ClassName);
Object object1 = class1.newInstance();
String str = (String)Class.forName("java.lang.String").newInstance();
something like this should work...
String name = "Test2";//Name of the class
Class myClass = Class.forName(name);
Object o = myClass.newInstance();
First off, sorry for the confusing title. It even confuses me so I don't wat to think about a better title any more.
Though, let's get to my problem. I have a class Classss. That class has some variables and a doSomething() void.
Now, that class has lots of classes extending that class, with different values of the variables and a different doSomething void. Now, I have the name of a class, something like "com.cool.cool.Cool".
So, I know that that class is a subclass of Classss and I have the name. Is there any way I can load that class by its name and be able to treat it as a Classss?
Thanks in advance.
It seems to me like this the classic case of polymorphism. Where you want to treat all subclasses the same way as the top class.
Basically, you can do this:
Classs c1 = new Cool(); // This works
Classs c2 = new SubClass(); // This works
c1.doSomething(); // Will call the Cool.doSomething() method;
c2.doSomething(); // Will call the SubClass.doSomething method;
You can also use List<Classs> and put subClass object in it...
Maybe something along the lines of:
static Bar getSubclass(String name) throws Exception{
Class<?> c = Class.forName(name);
Constructor<?> con = c.getConstructor();
return (Bar)con.newInstance();
}
This should work, provided name is the fully qualified name of a class that extends Bar and has a no-arg constructor.
class Bar{}
class Foo extends Bar{ public Foo(){} }
This is pretty prone to breaking.
Since your question mentions “load that class by its name” I assume you are using the Class.forName method.
java.lang.Class has an asSubclass method which I believe will do what you want:
Class<?> loadedClass = Class.forName(name);
Class<? extends Classss> type = loadedClass.asSubclass(Classss.class);
Your example name of “Classss” makes the above rather confusing, so I’ll repeat it using the name ExampleService:
Class<?> loadedClass = Class.forName(name);
Class<? extends ExampleService> type = loadedClass.asSubclass(ExampleService.class);
Alternatively, you may want to make use of the service provider facility, which is designed to dynamically search for “plugins,” that is, foreign implementations of an interface or abstract class:
for (ExampleService service : ServiceLoader.load(ExampleService.class)) {
System.out.println("Found subclass: " + service.getClass());
}
I'm trying to figure out Reflection with this Android class:
Class<?> c = Class.forName("com.android.internal.widget.LockPatternUtils");
Method method = c.getDeclaredMethod("getKeyguardStoredPasswordQuality");
method.setAccessible(true);
Object object = method.invoke(c); // Error with this line
result = object.toString());
The method getKeyguardStoredPasswordQuality is declared as (no parameters):
public int getKeyguardStoredPasswordQuality() {
// codes here
}
The error I got is:
Exception: java.lang.IllegalArgumentException: expected receiver of type com.android.internal.widget.LockPatternUtils, but got java.lang.Class<com.android.internal.widget.LockPatternUtils>
How do I declare com.android.internal.widget.LockPatternUtils as a receiver?
You are passing the class to #invoke() instead of an instance of LockPatternUtils.
You can create an instance using #newInstance().
Never mind, I've figured it out. I've adapted the codes below based on this tutorial.
In case anyone is interested in the solution, here it is:
Class<?> c = Class.forName("com.android.internal.widget.LockPatternUtils");
Constructor<?>[] constructors = c.getDeclaredConstructors();
Constructor<?> constructor = null;
for (int i = 0; i < constructors.length; i++) {
constructor = constructors[i];
if (constructor.getGenericParameterTypes().length == 0)
break;
}
constructor.setAccessible(true);
Object clazz = constructor.newInstance(context, true);
Method method = clazz.getClass().getDeclaredMethod("getKeyguardStoredPasswordQuality");
Object object = method.invoke(clazz);
result = object.toString();
The above solution requires that the public constructor of LockPatternUtils.java class to be defined as:
public LockPatternUtils(Context context) {...}
If the constructor changes in the future (after 2013), the solution will need to be amended.
Note: The above is an exercise for me to understand the usage of Reflection. However, using Reflection in Android production apps should be used sparingly and when absolutely needed.
Say if I have a class named Car I can use the following line of code in certain situations.
Car.class
My question is there a way I can make the same type of call if a user supplies a class name at run time. Have tried something similar to the below but no joy, is there a way i can do it.
String className = "Car";
Class.forName(className ).class;
Also I need to be able to cast dynamically, if the user specifies a list of objects I need to be able to dynamically cast.
e.g. instead of Car myCar = (Car) object
I need to be able to have to the user specify the name/type of class at run time so that I need to be able to do something along the lines of ClassName myObj = (ClassName) object.
Class.forName("Car") already returns the same as Car.class.
For casting, you can then use Class.forName("Car").cast(object), which would return a Car object. Take a look at the API, mostly the java.lang.Class part of it.
Also, since you're casting # runtime, there's no type safety, and you should check whether object extends or implements Car before doing it, otherwise you'll get an exception. A question I asked ~ a year ago and the answers there may be relevant to you as well.
Though, as others already said, this smells & you could probably redesign it in a better way, also note that this type of casting will typically be pretty slow because Java needs to examine the type hierarchy (it needs to throw a ClassCastException if it can't cast to Car).
Given the nature of the question, most of the answers to this are straight from the Reflection API documentation. I would suggest you take a look at this: http://docs.oracle.com/javase/tutorial/reflect/class/index.html. If this does not help and you need help with something specific, we can look at that.
What you are looking for is a feature called Reflection 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.
A Simple Example from http://java.sun.com
import java.lang.reflect.*;
public class DumpMethods {
public static void main(String args[])
{
try {
Class c = Class.forName(args[0]);
Method m[] = c.getDeclaredMethods();
for (int i = 0; i < m.length; i++)
System.out.println(m[i].toString());
}
catch (Throwable e) {
System.err.println(e);
}
}
}
For an invocation of:
java DumpMethods java.util.Stack
the output is:
public java.lang.Object java.util.Stack.push(
java.lang.Object)
public synchronized
java.lang.Object java.util.Stack.pop()
public synchronized
java.lang.Object java.util.Stack.peek()
public boolean java.util.Stack.empty()
public synchronized
int java.util.Stack.search(java.lang.Object)
Here is an example of creating objects at runtime:
import java.lang.reflect.*;
public class constructor2 {
public constructor2()
{
}
public constructor2(int a, int b)
{
System.out.println(
"a = " + a + " b = " + b);
}
public static void main(String args[])
{
try {
Class cls = Class.forName("constructor2");
Class partypes[] = new Class[2];
partypes[0] = Integer.TYPE;
partypes[1] = Integer.TYPE;
Constructor ct
= cls.getConstructor(partypes);
Object arglist[] = new Object[2];
arglist[0] = new Integer(37);
arglist[1] = new Integer(47);
Object retobj = ct.newInstance(arglist);
}
catch (Throwable e) {
System.err.println(e);
}
}
}
You can read more about it here and here - for indepth view
Also look here:
What is reflection and why is it useful?
You want to interact with myObj, so rather than going through these gymnastics, think about adding an interface that models the interactions you want to have with the objects, then use that interface in the code. The classes supplied by the user can then be validated to implement the necessary interface and errors raised appropriately.
The expression Car.class returns the java.lang.Class object for class Car.
A statement Class.forName("Car") will also return the java.lang.Class object for class Car (assuming that class Car is in the default package). Note: No need to append .class; that would give you the Class object of class Class itself, which is not what you want.
Class Class has methods to check if an object is an instance of the class that the Class instance represents (hope this is not too confusing...). Since you don't know the name of class Car at compile time, you're not going to have any kind of compile time type safety.
Lookup the API documentation of java.lang.Class.