I try to instantiate the inner class defined in the following Java code:
public class Mother {
public class Child {
public void doStuff() {
// ...
}
}
}
When I try to get an instance of Child like this
Class<?> clazz= Class.forName("com.mycompany.Mother$Child");
Child c = clazz.newInstance();
I get this exception:
java.lang.InstantiationException: com.mycompany.Mother$Child
at java.lang.Class.newInstance0(Class.java:340)
at java.lang.Class.newInstance(Class.java:308)
...
What am I missing ?
There's an extra "hidden" parameter, which is the instance of the enclosing class. You'll need to get at the constructor using Class.getDeclaredConstructor and then supply an instance of the enclosing class as an argument. For example:
// All exception handling omitted!
Class<?> enclosingClass = Class.forName("com.mycompany.Mother");
Object enclosingInstance = enclosingClass.newInstance();
Class<?> innerClass = Class.forName("com.mycompany.Mother$Child");
Constructor<?> ctor = innerClass.getDeclaredConstructor(enclosingClass);
Object innerInstance = ctor.newInstance(enclosingInstance);
Alternatively, if the nested class doesn't actually need to refer to an enclosing instance, make it a nested static class instead:
public class Mother {
public static class Child {
public void doStuff() {
// ...
}
}
}
This code create inner class instance.
Class childClass = Child.class;
String motherClassName = childClass.getCanonicalName().subSequence(0, childClass.getCanonicalName().length() - childClass.getSimpleName().length() - 1).toString();
Class motherClassType = Class.forName(motherClassName) ;
Mother mother = motherClassType.newInstance()
Child child = childClass.getConstructor(new Class[]{motherClassType}).newInstance(new Object[]{mother});
Related
I have a class Parent and a class Derived like
class Parent {
SomeClass obj = new SomeClass();
}
Now below class i want to generate using CodeModel
class Derived extends Parent {
String s = obj.invoke();
}
I tried below but not working
tryBlock.body().decl(codeModel.ref(String.class), "s",
(codeModel.ref(Parent.class)).staticRef("obj").invoke("invoke"));
How can I invoke obj rather than creating a new object as I am doing in Parent class?
You could give the Parent class a protected attribute of the type SomeClass and use it directly in the Derived class:
public class Parent {
protected SomeClass someObject;
public Parent() {
this.someObject = new SomeClass();
}
}
public class Derived extends Parent {
public void printInvoked() {
System.out.println(this.someObject.invoke());
}
}
public class SomeClass {
public String invoke() {
return "SomeClass invoked";
}
}
You can reference the field directly using JExpr.ref() and use it to initialize the field:
JDefinedClass derived = codeModel._class(JMod.PUBLIC, "Derived", ClassType.CLASS);
derived._extends(Parent.class);
derived.field(0, String.class, "s", JExpr.ref("obj").invoke("invoke"));
This generates the following:
public class Derived
extends Parent
{
String s = obj.invoke();
}
I'm using something similar to the following code in one of my Java classes:
public class SomeClass {
private int someValue;
void incrementValue() {
someValue++;
}
public abstract static class InnerClass {
private final SomeClass toRunOn;
public InnerClass(SomeClass obj) {
toRunOn = obj;
}
public abstract void execute();
// To allow us to call this on a given instance
final SomeClass getObj() {
return toRunOn;
}
}
public final InnerClass called = new InnerClass(this) {
public final void execute() {
incrementValue(); // This is what I thought should be throwing an error
}
};
}
However, while I would expect this to throw a compiler error in the called field defining execute() due to me not giving incrementValue() an object to work on (which is why I allowed for passing this to the inner class), it is completely fine with it. I'm uncertain why this is not giving me an error, and further confused as to what instance it would be calling on.
Am I misunderstanding some form of reference calling here, or is something more subtle going on?
called is assigned an instance of an anonymous sub-class of InnerClass. Since it's an instance member, it is initialized when an instance of SomeClass is created.
Since it is declared in the body of SomeClass, it is an inner class of SomeClass and has access to the instance methods and members of SomeClass. incrementValue() will be executed on the instance of SomeClass for which the called member was initialized.
Perhaps it would be easier to understand if you replace the anonymous class with an equivalent regular inner class :
public class SomeClass {
....
class SubInnerClass extends InnerClass {
public final void execute() {
incrementValue();
}
}
public final InnerClass called = new SubInnerClass(this);
....
}
If I have following Java code:
package a.b.c;
public class A{
static class B{
public B(){
}
}
}
I want to change class B's modifier to "public" at run-time via reflection, how can I do that? Thanks.
So the after effect will be like following:
package a.b.c;
public class A{
public static class B{
public B(){
}
}
}
With reflection you cannot change the class modifiers but you can create objects of the specified class and invoke its methods.
You can get instance the class from the enclosing class with the method getDeclaredClasses(), and then modify the contructor and instantiate the object:
Class a = A.class;
Class subs[] = a.getDeclaredClasses();
Object o = null;
for (Class cls: subs) {
if(cls.getCanonicalName().equals("A.B")){
for (Constructor ct: cls.getDeclaredConstructors()) {
ct.setAccessible(true);
o = ct.newInstance(new Inner());
// o is an instance of B
// you can get public and private method and invoke them
for (Method m: o.getClass().getDeclaredMethods())
if(m.getName().equals("....")){
m.setAccessible(true);
m.invoke(o, ....));
}
}
}
}
Instead of the for loop you could get methods by name and list of parameters.
So, here is the class with private Inner class declared inside and a private attribute.
I need to use Java reflection writing a test program in main function to execute this class.
public class Outter {
private Inner in;
public Outter(){
in = new Inner();
}
private class Inner{
private void test(){
System.out.println("test");
}
}
}
Here is test code:
my questions are listed following the statement.
public class Test
{
public static void main(String[] args) throws Exception
{
// 1. How do i create a Class type for Inner class since its modifier
// is private, if I am going to need .setAccessible() then how do i
// use it?
Class outter1 = Outter.class;
// 2. How do I pass parameters of type Inner to the Class object?
Constructor con = outter1.getConstructor(new Class[]{int.class});
// 3. Like this?
Field fields = outter1.getField("test");
fields.setAccessible(true);
// 4. Well I am lost what is the logic route for me to follow when
// using java reflection to execute a class like this!
Object temp = outter1.newInstance();
Outter outter = (Outter)temp;
System.out.println(fields.get(outter));
}
}
Here's a self-contained example of what you're trying to do.
Code you're running
try {
// gets the "in" field
Field f = Outer.class.getDeclaredField("in");
// sets it accessible as it's private
f.setAccessible(true);
// gets an instance of the Inner class by getting the instance of the
// "in" field from an instance of the Outer class - we know "in" is
// initialized in the no-args constructor
Object o = Object o = f.get(Outer.class.newInstance());
// gets the "execute" method
Method m = o.getClass().getDeclaredMethod("test", (Class<?>[])null);
// sets it accessible to this context
m.setAccessible(true);
// invokes the method
m.invoke(o, (Object[])null);
}
// TODO better handling
catch (Throwable t) {
t.printStackTrace();
}
Classes (inner/outer)...
public class Outer {
private Inner in;
public Outer() {
in = new Inner();
}
private class Inner {
private void test() {
System.out.println("test");
}
}
}
Output
test
I want to test a private method that existe inside a private inner class
public class MyBigClass {
private class MyInnerClass {
private void wantedMethod() {
}
}
}
I want to call the wantedMethod() to test it
Here is my code
Class[] classes = MyBigClass.class.getDeclaredClasses();
for (int i = 0; i < classes.length; i++) {
// this code print "MyInnerClass"
System.out.println(">> inner classes >> " + classes[i].getSimpleName());
if (classes[i].getSimpleName().equals("MyInnerClass")) {
Class clazz = classes[i];
// Constructor c=clazz.getConstructor();
Method[] methods = clazz.getDeclaredMethods();
// this code print "wantedMethod"
for (int j = 0; j < methods.length; j++) {
System.out.println("inner class methods >> " + methods[i].getName());
}
}
}
Problem : I cannot call wantedMethod()
If you want to invoke a non-static method you need to call it on instance of a class which has such method. In your case you want to call it on instance of private inner class MyInnerClass.
But since you don't have any instance of such class yet you need to create it. Since Java can't let inner class object be created without outer class object, you will need to have such outer object too (instance of MyBigClass).
So generally these are steps you need to take:
create outer class object (if you don't have one),
by using that outer class object create inner class object,
invoke method on inner class object.
You can do it like this:
(just remember that default constructors of class have same visibility as visibility of that class. So private class will have private default constructor, so we will need to make it accessible before we can use it)
try {
//creating outer class object
Object outer = new MyBigClass();
//creating inner class object
Class<?> innerClass = Class.forName("MyBigClass$MyInnerClass");
Constructor<?> constructor = innerClass.getDeclaredConstructor(MyBigClass.class);//constructors of inner classes require as first parameter instance of its outer class
constructor.setAccessible(true);//private inner class has private default constructor
Object child = constructor.newInstance(outer);//created inner object must know which outer object is used to create it
//TADA!!!
//invoking method on inner class object
Method method = innerClass.getDeclaredMethod("wantedMethod",new Class<?>[]{});
method.setAccessible(true);//since method is private
method.invoke(child,new Object[]{});
} catch (ClassNotFoundException | NoSuchMethodException | SecurityException | InstantiationException | IllegalAccessException | IllegalArgumentException | InvocationTargetException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
You can find more info about creating inner class object via reflection in this question
This is because your class isn't named CodeCircuit. Remove that if condition and it will work.
Also remove the line Constructor c=clazz.getConstructor(); as it throws an exception.
After making these changes, your own code prints
>> inner classes >> MyInnerClass
inner class methods >> wantedMethod
EDIT
Use this code to execute the method.
Class<?>[] classes = MyBigClass.class.getDeclaredClasses();
for (Class<?> clazz : classes) {
if(clazz.getSimpleName().equals("MyInnerClass")) {
Method method = clazz.getDeclaredMethod("wantedMethod", new Class[] {});
method.setAccessible(true);
method.invoke(clazz.getDeclaredConstructor(MyBigClass.class).newInstance(new MyBigClass()), new Object[] {});
}
}
The syntax is a bit strange, making you to use the outer class for getting hold of the inner class constructor. It behaves as if you have a constructor with the below signature defined in your inner class:
public MyInnerClass(MyBigClass bigClass) {
}
But, I assume that's how Java handles inner (nested) classes using reflection.
Note that you'll have to provide a public constructor for your inner class.
public class MyBigClass {
private class MyInnerClass {
public MyInnerClass() {
System.out.println("hello");
}
private void wantedMethod() {
System.out.println("world");
}
}
}
You'll also have to setAccessible(true) on the private method in order to be able to invoke it.
EDIT 2
Upon further investigation, when I decompiled the generated MyBigClass$MyInnerClass.class class, I found that my hunch was right:
public class MyBigClass$MyInnerClass {
public MyBigClass$MyInnerClass(MyBigClass paramMyBigClass) {
System.out.println("hello");
}
private void wantedMethod() {
System.out.println("world");
}
}
Would be really glad if someone can throw some light into this behaviour