I have a class called A and I need to create a new object of that class without calling its constructor. I want to set all its attributes through reflection.
Can I redefine the constructor of class A using reflection?
Or is there any way other way to do this?
In the Sun/Oracle JVm you can use Unsafe.allocateInstance(Class). Otherwise you have to generate byte code to create the instance without calling a constructor. You could use ASM for this. You cannot create an instance without a constructor using Reflection alone.
BTW: You can define a new method using byte code manipulation, but to add a constructor, you have to change the class before it is loaded. (This is tricky to do)
Invoke the object with the constructor that takes the least amount of arguments; using dummy arguments. Then proceed to manipulate the object however you like.
Related
In Java, does the constructor of a class create an instance of that class? And if it does, does it also initialize the variables of that class?
Constructor doesn’t create the instance of the Class.
Instance creation is done using either:
1.Using Class.forName()
2.ClassLoader loadClass()
3.Using clone()
4.Deserialization
5.Using reflection
6.new keyword
Constructor in java is a special type of method that is used to initialize the object.
Java constructor is invoked at the time of object creation. It constructs the values i.e. provides data for the object that is why it is known as constructor.
Rules for creating java constructor
There are basically two rules defined for the constructor.
1.Constructor name must be same as its class name
2.Constructor must have no explicit return type
Types of java constructors
There are two types of constructors:
1.Default constructor (no-arg constructor)
2.Parameterized constructor
Constructors don't create objects. They merely initialize objects(and their data members) once they are created using parameters(when provided) or to default values.
When you create an instance of the class using new operator, the constructor of the class is called so as to initialize the instance variables.
If the constructor defined is default, then instance variables have to be assigned to the newly created object explicitly.
However when you override a constructor using fields, then the instance variables for that newly created object are assigned during object creation.
I would love to explain this in a very simple language. In the real-world to build something, we need two things first is its prototype/model, and the second is someone who can create it based on that prototype.
A very relevant simple example is to build a house, you first need its blueprint(map), then a constructor who can build it based on that blueprint. So, similarly in the programming language
Object: A real-world entity for which we create a class.
Class: A class describes the "blueprint" of the objects that are made out of it (are instances of it).
For software development, we first have to think about the objects(any real-world entity), then we create a class (blueprint) for it, which contains its attributes.
After creating a class when we need to create one or more objects based on it, for this, we need a constructor to build it.
Whenever we create a new object, we have to use new keyword, and it tells the constructor to create the object.
When you are initialing variables in a class they are just part of the blueprint, based on that, the object will be created. So, without a constructor, you cannot create new objects, but there are some exceptional cases and tricks where you can create them without calling constructors.
I have a set of similar classes that all implement a function of the form
public static ClassA convertToClassA(Obj A)
public static ClassB convertToClassB(Obj B)
I want to loop through a list of classes and call this function that takes one argument of Obj in each class. How do I do this given each function is named differently?
Thanks for the help.
Class cls = Class.forName("ClassA");
String methodName = "convertTo" + cls.getSimpleName();
Method method = cls.getDeclaredMethod(methodName, new Class[]{Obj.class});
// If the underlying method is static, then the first parameter is ignored. It may be null as illustrated below.
method.invoke(null, your_object);
Create common interface with your method signature and let your invokable classes implement it, later on you can iterate over your objects as over instances of interface and call methods from it so no problem.
HOWEVER I am starting to think you want to call method without knowing it's name AT ALL - the only knowlage of target method is the number and type of arguments. Well that indeed IS impossible via reflection BUT, it will be innacurate if similar methods signatures will be present. Anyway, don't know what are you trying to do, but your project is badly designed from the ground (no interfaces, poor inharitance I guess etc.)
take a look at the reflection package. it provide methods to get back all the methods an instance has provide.
The apache common's BeanUtil (http://commons.apache.org/beanutils) also provide some util method doing similar things.
I am fairly new to java development and wounder how I can modify an existing Android class. I would like to change some of the methods in Notification.Builder class in Android (https://github.com/android/platform_frameworks_base/blob/master/core/java/android/app/Notification.java).
Specifically do I want to change getNotification(), but in the new implementation I need access to the private fields (e.g., mWhen, mSmallIcon).
I have tried to extend the class, but then I don't have access to the private fields of the superclass (i.e., mWhen, mSmallIcon).
What is the best practice to change the method, is it to copy the source code and modify it?
Update:
To be more precise: how can I change a single method in an existing class and still have access to the private fields of the existing class?
Thanks for all responses!
You could simply call super.getNotification() in your overriden method and modify the resulting object before returning it.
A private (inner) class, method or field are only referenced from within the class in which it is declared.
But you also can declare your own variables and work with it as you wish
The best practice is not to override methods (from third-party classes which were not designed to be overridden), but to create a new class/method which wraps the third-party class. Google for these: "fragile base class problem", "composition over inheritance".
I have tried to extend the class, but then I don't have access to the private fields of the superclass (i.e., mWhen, mSmallIcon).
In the particular class you're extending there are a limited number of methods that set the values of these fields. You can override those methods to hold onto copies of the values in new fields in your subclass which you can then use in your override of getNotification().
This is something of a hack, and wouldn't be workable with a more complex class.
Another hack is to use reflection and invoke setAccessible(true) on the field objects. This also may not be workable depending on security constraints.
If you say exactly the change you're trying to make, there might be a better way.
I have a util class that is supposed to call a method on a given Class object using reflection.
Right now it creates a new instances using .newInstance() and then calls the method I want to test.
The problem is that the zero-arguement constructor of some of my classes throws an Exception due to missing dependencies and such and keeps me from calling the method I actually want to test.
Is it possible to call the default-constructor of Java to create the instance instead of the custom zero-argument constructor?
You only have a default constructor, if the class has no constructors defined.
The no-arg constructor should only take the dependencies you give it (i.e. none) and it appears you believe you can still use the class without additional dependencies.
In Sun/Oracle JVM you can use Unsafe.allocateInstance(Class) which creates an instance without calling a constructor, but I would try to fix your class design first.
A default constructor is only created, when you don't provide a constructor yourself.
So, as soon as your class has at least one constructor, that default constructor isn't being created.
I am storing a list of classes through (Classname.class) and would like to instantiate one? Is this possible?
newInstance seems to the method I am after but it doesn't support a constructor?
You can use Class.getConstructors (or Class.getConstructor) to get a list of available constructors, and invoke any of them with Constructor.newInstance, which does accept parameters.
Just to add one point I see missing:
You can invoke newInstance directly on the Class object if it has a public null constructor. (Null constructor is the constructor with no arguments.)
Otherwise, you can find constructors via Class.getConstructors() as others have said.
The Java tutorial on reflection covers this well. But yeah, basically Class.getConstructors, then Constructor.newInstance is where it's at.
Java is designed so you can never "trick" it as long as you use the java.lang/java. classes or other standard libraries. One of the most important things of OOP is that objects should be in a defined state, thus you can be safe that the constructor is always run. Even if you're using some strange-looking reflection libraries to get your work done.
So, using Class.forName("me.Test").newInstance(); (or similar) will under-the-hood invoke the Test() constructor for you.
If you want to invoke another constructor the code is something like:
Test test = (Test)Class.forName("Test").getConstructor(String.class).newInstance("Hello World");
Here the getConstructor asks what the constructor looks like (it wants a string) and then you call it with a string.
You cannot construct new classes this way.
If you have the name of a class you can use Class.forName(className) to load/reference a class.
If you have the byte code for a class you want to create you can have a class loader load the byte code and give you the class. This is likely to be more advanced than you intended.
If you have a list of Class objects obtained through class literals, you might as well statically reference the constructors rather than slipping into reflection evilness.