Let MyClass be the class represented by this java code:
public MyClass
{
private String foo;
private Integer bar;
public MyClass(byte[] contents) { ... }
}
Let myConstructor be the following Constructor instance:
Constructor myConstructor = MyClass.class.getDeclaredConstructor(byte[].class);
My question is the following
Does this code use reflection?
byte[] contents = new byte[]{0,1,2};
MyClass myInstance = myConstructor.newInstance(contents);
or is equivalent, once that myConstructor is instantiated, to the following code?
byte[] contents = new byte[]{0,1,2};
MyClass myInstance = new MyClass(contents);
The equivalence relation I'm thinking about is that .newInstance(byte[] contents) access directly to the constructor in the same way as the new and the only reflection operation is finding the constructor.
Kind regards
Related
Is there a way to create an instance of a particular class given the class name (dynamic) and pass parameters to its constructor.
Something like:
Object object = createInstance("mypackage.MyClass","MyAttributeValue");
Where "MyAttributeValue" is an argument to the constructor of MyClass.
Yes, something like:
Class<?> clazz = Class.forName(className);
Constructor<?> ctor = clazz.getConstructor(String.class);
Object object = ctor.newInstance(new Object[] { ctorArgument });
That will only work for a single string parameter of course, but you can modify it pretty easily.
Note that the class name has to be a fully-qualified one, i.e. including the namespace. For nested classes, you need to use a dollar (as that's what the compiler uses). For example:
package foo;
public class Outer
{
public static class Nested {}
}
To obtain the Class object for that, you'd need Class.forName("foo.Outer$Nested").
You can use Class.forName() to get a Class object of the desired class.
Then use getConstructor() to find the desired Constructor object.
Finally, call newInstance() on that object to get your new instance.
Class<?> c = Class.forName("mypackage.MyClass");
Constructor<?> cons = c.getConstructor(String.class);
Object object = cons.newInstance("MyAttributeValue");
You can use reflections
return Class.forName(className).getConstructor(String.class).newInstance(arg);
If class has only one empty constructor (like Activity or Fragment etc, android classes):
Class<?> myClass = Class.forName("com.example.MyClass");
Constructor<?> constructor = myClass.getConstructors()[0];
when using (i.e.) getConstructor(String.lang) the constructor has to be declared public.
Otherwise a NoSuchMethodException is thrown.
if you want to access a non-public constructor you have to use instead (i.e.) getDeclaredConstructor(String.lang).
If anyone is looking for a way to create an instance of a class despite the class following the Singleton Pattern, here is a way to do it.
// Get Class instance
Class<?> clazz = Class.forName("myPackage.MyClass");
// Get the private constructor.
Constructor<?> cons = clazz.getDeclaredConstructor();
// Since it is private, make it accessible.
cons.setAccessible(true);
// Create new object.
Object obj = cons.newInstance();
This only works for classes that implement singleton pattern using a private constructor.
Another helpful answer. How do I use getConstructor(params).newInstance(args)?
return Class.forName(**complete classname**)
.getConstructor(**here pass parameters passed in constructor**)
.newInstance(**here pass arguments**);
In my case, my class's constructor takes Webdriver as parameter, so used below code:
return Class.forName("com.page.BillablePage")
.getConstructor(WebDriver.class)
.newInstance(this.driver);
You want to be using java.lang.reflect.Constructor.newInstance(Object...)
Very Simple way to create an object in Java using Class<?> with constructor argument(s) passing:
Case 1:-
Here, is a small code in this Main class:
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
public class Main {
public static void main(String args[]) throws ClassNotFoundException, NoSuchMethodException, SecurityException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
// Get class name as string.
String myClassName = Base.class.getName();
// Create class of type Base.
Class<?> myClass = Class.forName(myClassName);
// Create constructor call with argument types.
Constructor<?> ctr = myClass.getConstructor(String.class);
// Finally create object of type Base and pass data to constructor.
String arg1 = "My User Data";
Object object = ctr.newInstance(new Object[] { arg1 });
// Type-cast and access the data from class Base.
Base base = (Base)object;
System.out.println(base.data);
}
}
And, here is the Base class structure:
public class Base {
public String data = null;
public Base()
{
data = "default";
System.out.println("Base()");
}
public Base(String arg1) {
data = arg1;
System.out.println("Base("+arg1+")");
}
}
Case 2:- You, can code similarly for constructor with multiple argument and copy constructor. For example, passing 3 arguments as parameter to the Base constructor will need the constructor to be created in class and a code change in above as:
Constructor<?> ctr = myClass.getConstructor(String.class, String.class, String.class);
Object object = ctr.newInstance(new Object[] { "Arg1", "Arg2", "Arg3" });
And here the Base class should somehow look like:
public class Base {
public Base(String a, String b, String c){
// This constructor need to be created in this case.
}
}
Note:- Don't forget to handle the various exceptions which need to be handled in the code.
You can also invoke methods inside the created object.
You can create object instant by invoking the first constractor and then invoke the first method in the created object.
Class<?> c = Class.forName("mypackage.MyClass");
Constructor<?> ctor = c.getConstructors()[0];
Object object=ctor.newInstance(new Object[]{"ContstractorArgs"});
c.getDeclaredMethods()[0].invoke(object,Object... MethodArgs);
When I try to get the constructor to create an int it throws a: java.lang.NoSuchMethodException: int.<init>(int)
A very simplified version of what I'm trying to do is below:
Class myClass = int.class;
Constructor ctor = myClass.getConstructor(int.class);
I've tried the following as well:
Constructor ctor = myClass.getConstructor(Integer.TYPE);
Constructor ctor = myClass.getConstructor(Integer.class);
to end up with the same exception. What could be causing this?
EDIT:
Thanks for all the replies. I'm including the extended example below.
I'm trying to do the above while trying to invoke an unknown setter of an object, where I only have the value to pass to the setter as a String.
EDIT AFTER RESOLUTION
Please note that below code is only for clarity/context, and edited for brevity.
Thanks for the replies. What I really eventually needed was if there was a way to create a primitive (e.g. int) with methods related to reflection. The chosen answer provides a way using the corresponding wrapper class.
public class MyClass {
int field;
public void setField(int field) {
this.field = field;
}
}
public class Test {
public static void main(String... args) {
String value = "3"; // String of the the int value I want to pass to my setter as an argument when I invoke it via reflection
MyClass myObject = new MyClass();
Class objClass = myObject.getClass();
Method method = ... // Resolve the setter method using objClass.getMethods(); omitted here for brevity
Class[] paramTypes = method.getParameterTypes();
Class paramType = paramTypes[0]; // My setter method takes only one argument; so pick the first one
if (paramType.getName().equals("int")) {
Constructor ctor = paramType.getConstructor(int.class); // CAUSES EXCEPTION
Object instance = ctor.newInstance(value);
method.invoke(myObj, instance);
}
}
}
int is a primitive type and unlikely has the same kind of initialisation as reference types do (with a constructor). I don't think it has either int.<init>(int) or int.<int>() declared and available via Reflection API.
That said, you can do the trick with its wrapper class Integer because it has a constructor Integer(int) defined.
Constructor<Integer> constructor = Integer.class.getConstructor(int.class);
Integer integer = constructor.newInstance(3);
System.out.println(integer); // prints out 3
Using Eclipse
For any Class we can automatically
Generate Setters an Getters
Generate Delegate Methods
Generate hashCode() and equals()
Generate toString()
Generate Constructor using Fields
Generate Constructor From Superclass
Like that
Any way to generate
Fully initialized Constructor
(Constructor without any parameters that initialized all non-primitive fields)
For example
If my class as that
public class MyClass {
private String id;
private String code;
private MyClass1 myClass1;
private MyClass2 myClass2;
}
Generated Fully initialized Constructor will be
public class MyClass {
private String id;
private String code;
private MyClass1 myClass1;
private MyClass2 myClass2;
// Fully initialized Constructor
public FlightScheduleRequest() {
this.myClass1 = new MyClass1();
this.myClass2 = new MyClass2();
}
}
Its invalid requirement
Thanks to #Jayan note
If MyClass1 or MyClass2 does not have the default constructor,
but takes arguments for its constructor
So the initialization of them will be invalid
this.myClass1 = new MyClass1(); // The constructor MyClass1() is undefined
this.myClass2 = new MyClass2(); // The constructor MyClass2() is undefined
There is an option there to generate constructor using fields.
Select the fields which you want the initialization for and you are done.
This question already has answers here:
Java: recommended solution for deep cloning/copying an instance
(10 answers)
Closed yesterday.
I want to create a list/array of object with the same parent class which then I will use it for reference. but i dont know how to clone those object to make a new object.
here is the example
BigFoo a;
SmallFoo b;
ChickenFoo c;
List<Foo> foos;
foos.add(a);
foos.add(b);
foos.add(c);
Foo foo = foos.get(1).clone();
but in Java i found no clone function in the default function. I wonder how this is accomplished?
The general suggestion: use a copy constructor. In fact, only a class itself knows how to create a clone of itself. No class can clone an instance of another class. The idea goes like this:
public class Foo {
public List<Bar> bars = new ArrayList<Bar>();
private String secret;
// Copy constructor
public Foo(Foo that) {
// new List
this.bars = new ArrayList<Bar>();
// add a clone of each bar (as an example, if you need "deep cloning")
for (Bar bar:that.bars) {
this.bars.add(new Bar(bar));
}
// clone the secret value
this.secret = new String(that.secret);
}
// ...
}
So if we want to clone a foo, we simply create a new one based on foo:
Foo clonedFoo = new Foo(foo);
That's the recommended way to clone an instance.
copy constructor works well with inheritance. Consider a subclass
public ChildFoo extends Foo {
private int key;
public ChildFoo(ChildFoo that) {
super(that);
this.key = that.key;
}
}
Foo has a copy constructor and ChildFoo simply calls it from it's own copy constructor.
Your example is possible but not advisable. What will happen:
Foo a = new Foo();
ChildFoo b = new ChildFoo(a);
This would require a constructor on ChildFoo like:
public ChildFoo(Foo that) {
// call the copy constructor of Foo -> no problem
super(that);
// but how to initialize this.key? A Foo instance has no key value!
// Maybe use a default value?
this.key = 0;
}
Technically not a challenge but b is not a clone of a because the objects don't have the same type. So this (your example) is not cloning.
One easy way would be to use a json mapper (Jackson or Gson) and write out the object as a string and then creating the clone object by using the string.
Is there a way to create a new class from a String variable in Java?
String className = "Class1";
//pseudocode follows
Object xyz = new className(param1, param2);
Also, if possible does the resulting object have to be of type Object?
There may be a better way, but I want to be able to retrieve values from an XML file, then instantiate the classes named after those strings. Each of these classes implement the same interface and are derived from the same parent class, so I would then be able to call a particular method in that class.
This is what you want to do:
String className = "Class1";
Object xyz = Class.forName(className).newInstance();
Note that the newInstance method does not allow a parametrized constructor to be used. (See Class.newInstance documentation)
If you do need to use a parametrized constructor, this is what you need to do:
import java.lang.reflect.*;
Param1Type param1;
Param2Type param2;
String className = "Class1";
Class cl = Class.forName(className);
Constructor con = cl.getConstructor(Param1Type.class, Param2Type.class);
Object xyz = con.newInstance(param1, param2);
See Constructor.newInstance documentation
Yes, you can load a class on your classpath given the String name using reflection, using Class.forName(name), grabbing the constructor and invoking it. I'll do you an example.
Consider I have a class:
com.crossedstreams.thingy.Foo
Which has a constructor with signature:
Foo(String a, String b);
I would instantiate the class based on these two facts as follows:
// Load the Class. Must use fully qualified name here!
Class clazz = Class.forName("com.crossedstreams.thingy.Foo");
// I need an array as follows to describe the signature
Class[] parameters = new Class[] {String.class, String.class};
// Now I can get a reference to the right constructor
Constructor constructor = clazz.getConstructor(parameters);
// And I can use that Constructor to instantiate the class
Object o = constructor.newInstance(new Object[] {"one", "two"});
// To prove it's really there...
System.out.println(o);
Output:
com.crossedstreams.thingy.Foo#20cf2c80
There's plenty of resources out there which go into more detail about this, and you should be aware that you're introducing a dependency that the compiler can't check for you - if you misspell the class name or anything, it will fail at runtime.
Also, there's quite a few different types of Exception that might be throws during this process. It's a very powerful technique though.
This should work:
import java.lang.reflect.*;
FirstArgType arg1;
SecondArgType arg2;
Class cl = Class.forName("TheClassName");
Constructor con = cl.getConstructor(FirstArgType.class, SecondArgType.class);
Object obj = con.newInstance(arg1, arg2);
From there you can cast to a known type.
This worked a little more cleanly for me in JDK7, while the answers above made things a bit more difficult than they needed to be from a newbie perspective: (assumes you've declared 'className' as a String variable passed as a method parameter or earlier in the method using this code):
Class<?> panel = Class.forName( className );
JPanel newScreen = (JPanel) panel.newInstance();
From this point you can use properties / methods from your dynamically-named class exactly as you would expect to be able to use them:
JFrame frame = new JFrame(); // <<< Just so no-one gets lost here
frame.getContentPane().removeAll();
frame.getContentPane().add( newScreen );
frame.validate();
frame.repaint();
The examples in other answers above resulted in errors when I tried to .add() the new 'Object' type object to the frame. The technique shown here gave me a usable object with just those 2 lines of code above.
Not exactly certain why that was - I'm a Java newbie myself.
Another one:
import java.lang.reflect.Constructor;
public class Test {
public Test(String name) {
this.name = name;
}
public String getName() {
return name;
}
public String toString() {
return this.name;
}
private String name;
public static void main(String[] args) throws Exception {
String className = "Test";
Class clazz = Class.forName(className);
Constructor tc = clazz.getConstructor(String.class);
Object t = tc.newInstance("John");
System.out.println(t);
}
}
A Sample Program to Get Instance of a class using String Object.
public class GetStudentObjectFromString
{
public static void main (String[] args) throws java.lang.Exception
{
String className = "Student"; //Passed the Class Name in String Object.
//A Object of Student will made by Invoking its Default Constructor.
Object o = Class.forName(className).newInstance();
if(o instanceof Student) // Verify Your Instance that Is it Student Type or not?
System.out.println("Hurrey You Got The Instance of " + className);
}
}
class Student{
public Student(){
System.out.println("Constructor Invoked");
}
}
Output :-
Constructor Invoked
Hurrey You Got The Instance of Student