reflecting: Creating a new object of a reflected class via code
Hello. I am trying to input the name of a class that I have imported already, and can instantiate regularly, such as 'myClass inst = new myClass('foo');' and create a new instance-object of that class. The code below illustrates my question more specifically:
import java.lang.reflect.*;
import java.io.*;
public class reflecting1
{
public reflecting1()
{
BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
System.out.print("Input the name? \n");
try
{
typed = reader.readLine();
} catch (Exception e) {}
try
{
Constructor con = (typed.class).getConstructor(String.class);
Object obj = con.newInstance("Hello World!");
Method methd = (typed.class).getMethod("hashCode");
System.out.println(obj);
int hash = methd.invoke(obj);
System.out.println(hash + "");
} catch (Exception ee) {
System.err.println("Class not created.");
}
}
}
When the input of the above program is: 'String'
Why is the output not:
"
Hello World!
-969099747
"
and I tried:
import java.lang.reflect.*;
import java.io.*;
public class reflecting2
{
public reflecting2()
{
BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
System.out.print("Input the name? \n");
try
{
typed = reader.readLine();
} catch (Exception e) {}
try
{
Class newC = Class.nameOf(typed);
Constructor con = (typed.class).getConstructor(String.class);
Object obj = con.newInstance("Hello World!");
Method methd = (typed.class).getMethod("hashCode");
System.out.println(obj);
int hash = methd.invoke(obj);
System.out.println(hash + "");
} catch (Exception ee) {
System.err.println("Class not created.");
}
}
}
but still didn't work.. does anyone know how to make this work?
FALL3N
Junior Poster in Training
84 posts since May 2010
Reputation Points: 10
Solved Threads: 2
Can you show what the printed output from when you executed the code?
What .class files were in the directory when you executed the code?
does anyone know how to make this work?
Neither of the posted code compiles.
Fix the compilation errors.
NormR1
Posting Expert
6,677 posts since Jun 2010
Reputation Points: 1,138
Solved Threads: 656
JamesCherrill
Posting Genius
6,373 posts since Apr 2008
Reputation Points: 2,130
Solved Threads: 1,073
... or lust have a look at this:
class MyClass {
private String name;
public MyClass() {
name = "no name";
}
public MyClass(String name) {
this.name = name;
}
@Override
public String toString() {
return "An instance of MyClass " + name;
}
}
public class Demo {
public static void main(String[] args) {
Class<?> theClass;
java.lang.reflect.Constructor<?> constructor;
Object newObject;
try {
theClass = Class.forName("MyClass");
constructor = theClass.getConstructor(); // default constructor
newObject = constructor.newInstance();
System.out.println(newObject);
constructor = theClass.getConstructor(String.class);
newObject = constructor.newInstance("one-arg constructor");
System.out.println(newObject);
} catch (Exception e) {
e.printStackTrace();
}
}
}
JamesCherrill
Posting Genius
6,373 posts since Apr 2008
Reputation Points: 2,130
Solved Threads: 1,073
NormR1 :
• The output was a runtime error for both programs.
• Reflecting1 was in a package 'myJava', and String was just a built-in class in java.lang
JamesCherrill :
That is what I was looking for, but I am trying to understand how it works, and so I have a few questions. Below is your code, with a few minor changes:
// package myjava;
import java.lang.reflect.*;
public class Demo
{
public static void main(String[] args)
{
Class<?> theClass;
java.lang.reflect.Constructor<?> constructor;
Object newObject;
try {
theClass = Class.forName("MyClass");
constructor = theClass.getConstructor(); // default constructor
newObject = constructor.newInstance();
System.out.println(newObject);
constructor = theClass.getConstructor(String.class);
newObject = constructor.newInstance("one-arg constructor");
System.out.println(newObject);
} catch (Exception e) {
e.printStackTrace();
}
}
}
class MyClass {
private String name;
public MyClass() {
name = "foobar";
}
public MyClass(String name) {
this.name = name;
}
@Override
public String toString() {
return "An instance of MyClass " + name;
}
}
1. Why can I not add a package statement to the beginning?
2. You used:
' Class<?> theClass;
java.lang.reflect.Constructor<?> constructor'
why can you not just import java.lang.reflect and use
' Class<?> theClass;
Constructor<?> constructor; '
3. class MyClass is written at the end of 'Demo.java', and that works fine. However, when I try to move MyClass to a new file, 'MyClass.java' (in the same directory as 'Demo.java') and make it a public class, it does not work.. what am I doing wrong?
FALL3N
Junior Poster in Training
84 posts since May 2010
Reputation Points: 10
Solved Threads: 2
Answers:
1. You can, if you want. Just make sure your files are in a directory structure that matches the package structure.
2. No particular reason, you can do it either way. I tend to use import for multiple references, but a fully qualified name if I use it just once.
3. I don't know what you're doing wrong there. It should work just the same with a public class in another file. Maybe something to do with your use of packages???
JamesCherrill
Posting Genius
6,373 posts since Apr 2008
Reputation Points: 2,130
Solved Threads: 1,073
A quick after-thought...
if the class you want to instantiate is in a package you need the fully-qualified name of the class in your Class.forName(...), eg Class.forName("javax.swing.JLabel"). import won't help because the name is resolved at runtime.
JamesCherrill
Posting Genius
6,373 posts since Apr 2008
Reputation Points: 2,130
Solved Threads: 1,073
import java.io.*;
import java.util.*;
import java.lang.reflect.*;
public class myProgram
{
public myProgram()
{
// print greeting statement
System.out.println("Hello " + System.getProperty("user.name") + ".");
String command = getInput();
execute(command);
System.out.println(""); // a blank line as a spacer
}
public String getInput()
{
String input = "";
System.out.print("> ");
BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
try
{
input = reader.readLine();
} catch (Exception e) {}
return input;
}
private void execute(String input)
{
String arg = input;
Class<?> theClass;
Constructor<?> constructor;
Object newObject;
try {
theClass = Class.forName(arg);
constructor = theClass.getConstructor();
newObject = constructor.newInstance();
} catch (Exception e) {
e.printStackTrace();
}
}
public static void main(String[] Args)
{
new myProgram();
}
}
class Exit
{
public Exit()
{
System.out.println("Hello World!");
}
}
input:
Exit
output:
Hello World!
ok, this works. (yay) but, a few questions..
1. if I have the default class "Exit" implementing any interfaces, they do not work.. why? Can I implement an interface?
2. If I try to write 'Exit' as a public rather than default class in it's own file and then just import it, this does not work... how what directory structure or other thing(s) will fix this?
3. (I think the answer to this question will answer all of the questions) In your 'afterthought' you said that I was having some problems because of my use of packages... I currently have 'myProgram' and 'Exit' in a folder that I added to my classpath... is that not how to do this?
FALL3N
Junior Poster in Training
84 posts since May 2010
Reputation Points: 10
Solved Threads: 2
this does not work...
Please post the errors and the code that causes them.
NormR1
Posting Expert
6,677 posts since Jun 2010
Reputation Points: 1,138
Solved Threads: 656
those were more broad questions, they do not have specific errors that they cause.
But here is a new question:
When I write
package repository.myProgram
in the beginning of the above code, (which does work in like, any other case) I get the following error:
java.lang.ClassNotFoundException
at edu.rice.cs.plt.reflect.PathClassLoader.findClass(PathClassLoader.java:148)
at java.lang.ClassLoader.loadClass(ClassLoader.java:306)
at java.lang.ClassLoader.loadClass(ClassLoader.java:247)
and a lot more of the same kind of message... what is happening to cause this? '~/repository' is on my classpath, and I havent had a problem with it before.. help?
FALL3N
Junior Poster in Training
84 posts since May 2010
Reputation Points: 10
Solved Threads: 2
ava.lang.ClassNotFoundException
What is the full name of the class not found? That should be printed out so you can see it easily.
Where is the class file and what package is it in and where is the classpath pointing when the program is executed?
NormR1
Posting Expert
6,677 posts since Jun 2010
Reputation Points: 1,138
Solved Threads: 656
Folder structure must match complete package name, so
package repository.myProgram
public class MyClass
means the classpath must contain
repository/myProgram/MyClass.class
JamesCherrill
Posting Genius
6,373 posts since Apr 2008
Reputation Points: 2,130
Solved Threads: 1,073
No updates for 2 days... is this "Solved" now?
JamesCherrill
Posting Genius
6,373 posts since Apr 2008
Reputation Points: 2,130
Solved Threads: 1,073
no, not solved sry, my computer crashed X/
anyway, I start with the lines:
package repository.myProgram;
import repository.myProgram.commands.*;
also, the CLASSPATH does contain ~/repository
and ~/repository contains ~/repository/myProgram/myClass
Should I have ~/repository/myProgram/commands on the PATH (and/or the CLASSPATH) to make the classes contained be reflectable?
FALL3N
Junior Poster in Training
84 posts since May 2010
Reputation Points: 10
Solved Threads: 2
The PATH is used by the OS to find commands like javac and java. You only set this once when the location of a command changes and the OS needs to find it.
The CLASSPATH is used by javac and java to find the definitions for classes. This needs to be set every time you execute java or javac so they can find class definitions.
NormR1
Posting Expert
6,677 posts since Jun 2010
Reputation Points: 1,138
Solved Threads: 656