Constructor.newInstance with Object[] argument - java

I have been programming java a long time and for some reason I am unable to figure out why this gives me an argument type mismatch. I created a very simple JUnit test anyone can run. Just copy and paste the code below. Any help would be much appreciated. Thanks!
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import org.junit.Test;
public class TestObjectArrayConstructor {
#Test
public void testLabelValueObjectArrayConstructor(){
Constructor constructor = null;
try {
constructor = LabelValue.class.getConstructor(
new Class[]{Object[].class});
} catch (NoSuchMethodException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (SecurityException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
Object[] array = new Object[]{"Doll"};
Object labelValue = null;
try {
labelValue = constructor.newInstance(array);
} catch (InstantiationException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalArgumentException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InvocationTargetException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("don");
}
}
public class LabelValue {
private String label;
private String value;
public LabelValue(){
}
public LabelValue(Object[] array)
{
if(array != null && array.length > 0)
{
this.label = (String)array[0];
this.value = (String)array[0];
}
}
public String getLabel() {
return label;
}
public void setLabel(String label) {
this.label = label;
}
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
}

try this (not tested) :
constructor.newInstance(new Object[]{array});
because newInstance expects an array of Object (the different args), and your case is ambiguous, as your param is an array of Object.

When you want to create a newInstance from a constructorthen you need to pass your actual parameters, in your case a single argument array as new Object[]:
replace
labelValue = constructor.newInstance(array);
with
labelValue = constructor.newInstance(new Object[]{array});

Related

Overwrite Object properties with properties of other Object using reflection

Im trying to do something that might seem a bit unorthodox, however this is due to some limitations in a framework that im using.
Basically my case is this:
1: I have an object that has several fields, all with default values.
2: I have an other object that is initialized and has all values that I want to have, in the new object.
Im trying to do this with reflection, so looping over all public setMethods, finding all getMethods that seem to be matching from the other object, invoking them and invoke the other setMethod with the value over the invoked setMethod.
This is what I came up with so far:
java.lang.reflect.Method[] publicMethods1 = newlabels.getClass().getMethods();
for(int i=0; i<publicMethods1.length; i++){
if (publicMethods1[i].getName().startsWith("set")){
String setname = publicMethods1[i].getName();
String getname = "get"+setname.substring(3, setname.length());
try {
java.lang.reflect.Method getMethod = labels.getClass().getMethod(getname, null);
publicMethods1[i].invoke(newlabels, getMethod.invoke(labels, null));
} catch (NoSuchMethodException e1) {
//System.out.println("Couldnot find a method with name: "+getname);
} catch (SecurityException e1) {
//System.out.println("Security exception occured");
} catch (IllegalAccessException e1) {
//System.out.println("IllegalAccessException");
} catch (IllegalArgumentException e1) {
//System.out.println("IllegalArgumentException");
} catch (InvocationTargetException e1) {
//System.out.println("InvocationTargetException");
}
}
}
This unfortunately isn't working, its not giving errors either (unless a getter wasnt found, but ill take that).
I looked around on the internet and found somewhat similar in this method:
/**
* Only works for methods with equally named getters and setters
*
* 1. Get all declared methods of obj1 and find all setters
* 2. Get all declared methods of obj2 and find all getters
* 3. Find which setter belongs to which getter
* 4. Set the value of obj1.setter with obj2.getter
*
* #param obj1
* #param obj2
*/
public static void runAllSettersWithGetters(Object obj1, Object obj2) {
ArrayList<Method> setters = findSetters(obj1);
ArrayList<Method> getters = findGetters(obj2);
for(int s=0; s<setters.size(); s++){
String setmethodname = setters.get(s).getName();
String whattoset = setmethodname.substring(3);
for(int g=0; g<getters.size(); g++){
boolean isboolean = false;
boolean match = false;
if(getters.get(g).getReturnType().equals(Boolean.TYPE)){
isboolean = true;
}
String getmethodname = getters.get(g).getName();
String whattoget = getmethodname.substring(3);
if(whattoset.equalsIgnoreCase(whattoget)){
match = true;
}else{
//might start with is instead of get
whattoget = getmethodname.substring(2);
if(whattoset.equalsIgnoreCase(whattoget)){
match = true;
}
}
if(match){
try {
setters.get(s).invoke(obj1, getters.get(g).invoke(obj2));
} catch (IllegalAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalArgumentException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InvocationTargetException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
}
So I tried it, because it seems better, however in the end it gives the same not working solution.
Can anyone help me with this?

Calling a function from the value of a string Java [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
How do I invoke a java method when given the method name as a string?
**I have looked at this : Call a function from a string array (Java or Groovy) and it didn't work for me, perhaps it is my scenario*
I have a String array with some values, and I want to be able to call a method which is one of those values, of course this can change, and I could potentially have 100's of values, so it's not feasible to use a if/else if construct, or a switch statement.
Is there any way I can call the method, as I would like, as displayed in the code below?
private String[] = {"Hit","Slap","Blop"};
private String et = "Slap";
public void Action(){
for(int i = 0; i < arr.length;i++){
if(et.equals(arr[i])){
//Call method of that name ( Slap(); )
}
}
}
public void Run(){
///
}
public void Slap(){
///
}
public void Blop(){
///
}
EDIT: My attempt to integrate reflection:
for(int i = 0; i < arr.length;i++){
if(et.equals(arr[i])){
//Call method of that name
try {
method = this.getClass().getMethod(arr[i]);
} catch (NoSuchMethodException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (SecurityException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
try {
return (String) method.invoke(this);
} catch (IllegalAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalArgumentException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InvocationTargetException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
return "FAIL";
You will have to use reflection. Something like this:
getClass().getMethod(arr[i]).invoke(this);
You can use the ReflectionAPI to achieve this. Just get the method with this name from your desired class (if available ) and invoke it with your args, in this case null.
BUT it's a bad design and you should rethink your application flow!
here is an example:
public class HelloWorld {
public static void main(String[] args) {
HelloWorld hello = new HelloWorld();
String[] calls = { "def", "abc", "ghi" };
try {
for (String call : calls) {
Method method = HelloWorld.class.getMethod(call, null);
method.invoke(hello, null);
}
} catch (Exception e) {
// TODO: handle exception
}
}
public void abc() {
System.out.println("abc");
}
public void def() {
System.out.println("def");
}
public void ghi() {
System.out.println("ghi");
}
}

Why these errors while invoking main through reflection

Here is a custom executor that executes an application by searching for its main in the loaded classes loaded by a custom loader. There is a problem when I try to execute a program using my executor.
The source code of the program being executed can be located on the following link
http://agile.csc.ncsu.edu/SEMaterials/realestate/code/RealEstate.zip
package executorOfLoaderClasses;
import java.io.File;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import customClassLoader.ClassLoaderOfExtClass;
/**
* #author Sanyam
*
* sanyamgoyal007#gmail.com
*/
public class ClassExecutor{
private ClassLoaderOfExtClass classLoader;
private byte[][] ArrayOfClasses;
private String[] ArrayOfBinaryNames;
#SuppressWarnings("rawtypes")
private ArrayList<Class> loadedClasses;
private ArrayList<String> loadedClasesNames;
private Object[] parameters;
#SuppressWarnings("rawtypes")
public ClassExecutor() {
classLoader = new ClassLoaderOfExtClass();
new ArrayList<Class>();
loadedClasses = new ArrayList<Class>();
loadedClasesNames = new ArrayList<String>();
}
#SuppressWarnings("unchecked")
public void execute(File[] file, String[] binaryPaths) {
Object[] actuals = { new String[] { "" } };
Method m = null;
try {
Field classesx=ClassLoaderOfExtClass.class.getDeclaredField("classes");
classesx.setAccessible(true);
} catch (SecurityException e1) {
e1.printStackTrace();
} catch (NoSuchFieldException e1) {
e1.printStackTrace();
}
/*for (int i = 0; i < file.length; i++) {
for (int j = 0; j < file.length; j++) {
try {
#SuppressWarnings("rawtypes")
Class c = classLoader.loadClassCustom(file[i], binaryPaths[i]);
//Fied classex=classLoader.getResource("classes");
}catch(Exception e){
}
}
}
Class<?>[]classesxx= getLoadedClasses(classLoader);
System.out.println("Loaded classes have size "+ classesxx.length);*/
for (int i = 0; i < file.length; i++) {
try {
#SuppressWarnings("rawtypes")
Class c = classLoader.loadClassCustom(file[i], binaryPaths[i]);
try {
if (c.getMethod("main", new Class[] { String[].class }) != null) {
m = c.getMethod("main", new Class[] { String[].class });
} else {
System.out.println("This class does not contain main");
continue;
}
} catch (NoSuchMethodException e) {
// System.out.println("Main not found!!!");
// System.out.println("M here");
// e.printStackTrace(); // not printing stack trace
} catch (SecurityException e) {
e.printStackTrace();
}
} catch (ClassNotFoundException e) {
System.out.println("No such class definition exist!!");
// TODO Auto-generated catch block
// e.printStackTrace();
}
}
try {
m.invoke(null, actuals);
// CallStack.print();
} catch (IllegalArgumentException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InvocationTargetException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
#SuppressWarnings({ })
public void execute(ArrayList<byte[]> stuffedFiles,
ArrayList<String> binaryPaths) {
convertToArray(stuffedFiles, binaryPaths);
loadAllClasses(ArrayOfClasses, ArrayOfBinaryNames);
Thread myThread = new MyThread();
myThread.start();
/*Object[] actuals = { new String[] { "" } };
Method m = null;
* Method[] m1= new Method[10]; for (Class c : loadedClasses) {
* m1=c.getMethods(); } for(Method m2: m1){
* System.out.println(m2.getName()); }
System.out.println(loadedClasses.size());
for (Class c : loadedClasses) {
* System.out.println(c.toString());
* System.out.println(c.getConstructors());
// for (int i = 1; i < file.size(); i++) {
* for(Method meth : c.getMethods()){ meth.setAccessible(true);
*
* }
try {
if (c.getMethod("main", new Class[] { String[].class }) != null) {
m = c.getMethod("main", new Class[] { String[].class });
break;
} else {
// System.out.println("This class does not contain main");
continue;
}
} catch (NoSuchMethodException e) {
System.out.println("Program does not contain main");
} catch (SecurityException e) {
e.printStackTrace();
}
}
try {
if(parameters==null){
m.invoke(null, actuals);
}
else{
try {
System.out.println("It Fails Here");
m.invoke(null, parameters);
} catch (Exception e) {
System.out.println("Illegal arguments");
}
}
// CallStack.print();
} catch (IllegalArgumentException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InvocationTargetException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}*/
// remove till here
/*TraceParser pr = new TraceParser();
pr.traceCollector();
pr.traceStruct();
ArrayList<SingleTraceStructure> parsedExpressions = pr
.getTracedObjects();
AllStackTraceValidator validator = new AllStackTraceValidator(
parsedExpressions);
finalObjects = validator.getTraceObjects();
for(SingleTraceStructure ob : finalObjects){
validatedTraceObjects.add(ob);
}
TraceObjectsMinimizer tracerObj = new TraceObjectsMinimizer();
tracerObj.sortObjects(finalObjects);*/
/*
* for(SingleTraceStructure obj : finalObjects){
* System.out.println(obj.getCalledBy());
* System.out.println(obj.getClassName()+":"+obj.getMethodName()+":"+
* obj.getCallSequenceNumbr()+obj.getCalledBy()); }
*/
}
private void convertToArray(ArrayList<byte[]> classes,
ArrayList<String> binaryPaths) {
/* = new byte[classes.size()][]; */
ArrayOfClasses = new byte[classes.size()][];
ArrayOfBinaryNames = new String[binaryPaths.size()];
int i = 0;
for (byte[] tempClass : classes) {
ArrayOfClasses[i] = tempClass;
i++;
}
int j = 0;
for (String name : binaryPaths) {
ArrayOfBinaryNames[j] = name;
j++;
}
}
#SuppressWarnings("rawtypes")
public void loadAllClasses(byte[][] classes, String[] names) {
for (int i = 0; i < classes.length; i++) {
System.out.println("Round ----->" + i);
Class c = null;
for (int j = 0; j < classes.length; j++) {
if (classes[j] != null) {
try {
c = classLoader.loadClassCustom(classes[j], names[j]);
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
System.out.println("unsucessful");
e.printStackTrace();
}
if (c != null) {
System.out.println("loading successfull");
loadedClasses.add(c);
loadedClasesNames.add(names[j]);
classes[j] = null;
names[j] = null;
} else {
// move on
}
} else {
// do nothing
}
}
}
}
#SuppressWarnings("rawtypes")
public ArrayList<Class> getLoadedClasses() {
return loadedClasses;
}
public void parametersToMain(ArrayList<String> strs){
if(strs!=null){
String[] obj = new String[strs.size()];
int i=0;
for(String str : strs){
obj[i]= (String)str;
i++;
}
parameters=obj;
}
else{
parameters=null;
}
}
// return loaded classes of a loader
public static Class<?>[] getLoadedClasses(final ClassLoader loader){
final Class<?>[] classes = getLoadedClasses(loader);
return classes;
}
public class MyThread extends Thread{
Object[] actuals = { new String[] { "" }};
public void run(){
Method m = null;
/*
* Method[] m1= new Method[10]; for (Class c : loadedClasses) {
* m1=c.getMethods(); } for(Method m2: m1){
* System.out.println(m2.getName()); }
*/
/* System.out.println(loadedClasses.size()); */
for (Class<?> c : loadedClasses) {
/*
* System.out.println(c.toString());
* System.out.println(c.getConstructors());
*/
// for (int i = 1; i < file.size(); i++) {
/*
* for(Method meth : c.getMethods()){ meth.setAccessible(true);
*
* }
*/
try {
if (c.getMethod("main", new Class[] { String[].class }) != null) {
m = c.getMethod("main", new Class[] { String[].class });
break;
} else {
// System.out.println("This class does not contain main");
continue;
}
} catch (NoSuchMethodException e) {
System.out.println("Program does not contain main");
} catch (SecurityException e) {
e.printStackTrace();
}
}
try {
if(parameters==null){
//System.out.println("Invoker of" + actuals[1]);
m.invoke(null, actuals);
}
else{
try {
System.out.println("It Fails Here");
m.invoke(null, parameters);
} catch (Exception e) {
System.out.println("Illegal arguments");
}
}
// CallStack.print();
} catch (IllegalArgumentException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InvocationTargetException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
The problem with my executor is while executing the realestate program genetraes the following error
java.lang.reflect.InvocationTargetException
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at executorOfLoaderClasses.ClassExecutor$MyThread.run(ClassExecutor.java:365)
Caused by: java.lang.ArrayIndexOutOfBoundsException: 1
at edu.ncsu.realestate.gui.Main.main(Main.java:39)
... 5 more
I realized that while invoking the main I am passing a parameter to the main which is an object of string "" however realestate program does not take any arguments by default ,so for the time being I changed the argument passed to the method to null just to check whether it works fine now.
and again an error was generated as shown below
java.lang.IllegalArgumentException: wrong number of arguments
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at executorOfLoaderClasses.ClassExecutor$MyThread.run(ClassExecutor.java:366)
Why is this happening the realestate program as mentioned in the http link does not take any arguments by default.
Is this way of execution buggy to other possible input programs ??
The realestate program I mentioned is working absolutely fine when run in eclipse as a Java application
The actual bug in the code from the question
The Main method you invoke expects either zero or two arguments, but you pass one.
public static void main(String[] args) {
GameMaster master = GameMaster.instance();
MainWindow window = new MainWindow();
GameBoard gameBoard = null;
if(args.length > 0) {
if(args[0].equals("test")) {
master.setTestMode(true);
}
try {
Class c = Class.forName(args[1]); // <-- this is l. 39
gameBoard = (GameBoard)c.newInstance();
}
You should write
Object[] actuals = { new String[] { }};
or
Object[] actuals = { new String[0] };
in order to pass not a single empty argument, but no argument at all.
General information about argument types
If main is the startup method of a Java application, it always has signature
public static void main(String[] args)
For this reason, from the java perspective it will always be a method expecting a single argument, which is an array of strings. So on the command line, you use a variable number of arguments, but within the Java application, it is always a single array. Some developers might declare the arguments as String... args, which means that you might pass a variable number of strings in the Java application, but that is only syntactic sugar which the compiler will translate into an array creation. For reflection, you will always have to pass the array yourself, as there is no automatic array creation for variadic methods there. So always pass a single argument of type String[] via reflection.
Method.invoke takes an Object... for the arguments, so you can either pass an Object[] containing all the Java arguments, or you can pass each argument separately and have the compiler construct an Object[] from those. So it is up to you whether you pass the String[] array directly to invoke or wrap it in an Object[] as you did with your actuals.

Private member in-accessible?

So i have a java class, with 3 private fields
public class Parcel {
private String guid;
private List<String> files;
private String zipFileName;
public Parcel (List<String> files, String zipFilePath){
UUID uuid = UUID.randomUUID();
guid = uuid.toString();
zipFileName = zipFilePath + File.separator + guid + File.separator + ".zip";
if ((files != null) && (!files.isEmpty())){
this.files = files;
}
}
}
Now, I am writing JUnit test to test these private fields
public class ParcelTest {
#Test
public void parcelObject() {
String zipFilePath = "/path/to/folder";
List<String> files = new ArrayList<String>();
files.add("/path/to/folder/test1");
files.add("/path/to/folder/test2");
Parcel parcel = new Parcel(files, zipFilePath);
Class<? extends Parcel> parcelClass = parcel.getClass();
try {
Field guid = parcelClass.getDeclaredField("guid");
guid.setAccessible(true);
System.out.println(guid.get(parcel));
} catch (IllegalArgumentException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (SecurityException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (NoSuchFieldException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
I am getting error when trying to access private guid field. I have tried this even after creating zero argument constructor. how should i access private members here?
EDIT
I figured it out and i have updated my response if someone else needed it.
P.S:
How can i close this question>
You are much better off testing the externally visible behaviour (behaviour, not getters and setters). If your code doesn't change behaviour, you should delete it.
(Also you might want to copy your list before stashing it in a field (and before checking validity).)
Why don't you have a public getter or setter instead of dealing with reflection?

Creating an instance from String in Java

If I have 2 classes, "A" and "B", how can I create a generic factory so I will only need to pass the class name as a string to receive an instance?
Example:
public static void factory(String name) {
// An example of an implmentation I would need, this obviously doesn't work
return new name.CreateClass();
}
Thanks!
Joel
Class c= Class.forName(className);
return c.getDeclaredConstructor().newInstance();//assuming you aren't worried about constructor .
javadoc
For invoking constructor with argument
public static Object createObject(Constructor constructor,
Object[] arguments) {
System.out.println("Constructor: " + constructor.toString());
Object object = null;
try {
object = constructor.newInstance(arguments);
System.out.println("Object: " + object.toString());
return object;
} catch (InstantiationException e) {
//handle it
} catch (IllegalAccessException e) {
//handle it
} catch (IllegalArgumentException e) {
//handle it
} catch (InvocationTargetException e) {
//handle it
}
return object;
}
}
have a look
You may take a look at Reflection:
import java.awt.Rectangle;
public class SampleNoArg {
public static void main(String[] args) {
Rectangle r = (Rectangle) createObject("java.awt.Rectangle");
System.out.println(r.toString());
}
static Object createObject(String className) {
Object object = null;
try {
Class classDefinition = Class.forName(className);
object = classDefinition.newInstance();
} catch (InstantiationException e) {
System.out.println(e);
} catch (IllegalAccessException e) {
System.out.println(e);
} catch (ClassNotFoundException e) {
System.out.println(e);
}
return object;
}
}

Categories