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
Related
Consider the following code:
class Scratch<T> {
class InnerClass<T> {
public void executeHiddenMethod(){
//..some code to use Inner (T) type
T r = null; //declared T from inner T type
//..some code to use Outer (T) type
//?? How to use outer T type?
}
}
//when trying to invoke the code:
public static void main(String[] args) {
Scratch<String> scr = new Scratch<>();
Scratch<String>.InnerClass<Double> d = scr.new InnerClass<>();
d.executeHiddenMethod();
}
}
Is there any way to reveal the Hidden Type Parameter of the Outer Class Scratch into the inner class InnerClass?
Or is there any clause in JLS that forbids this exposure in case of type parameters that get hidden?
Unless I misunderstood the question, you should be able to use a different type parameter for the outer and inner class. T for Scratch and S for InnerClass.
class Scratch<T> {
class InnerClass<S> {
public void executeHiddenMethod(){
...
S s = null;
...
T t = null;
}
}
}
In Java, I'm trying to override a class coming from a library. One of the constructors of the class is private and thus I'm not able to call it from my class. Is there a way to work around this (reflection?)?
public class LibraryClass extends ProtectedLibraryClass {
public LibraryClass() {
super();
}
private LibraryClass(Boolean useFeature) {
super(useFeature);
}
// Other methods
}
public class MyClass extends LibraryClass {
public MyClass() {
super();
}
private MyClass(Boolean useFeature) {
super(useFeature); // <-- This line throws exception as super class constructor is private
}
// Override other methods
}
I can't just call super() and then set useFeature flag as useFeature flag is final in protectedLibraryClass and is set only through it's constructor.
they made it for a reason but you can use reflection in java to create object from this class even if it private
here is example :
public static void main(String[] args) {
LibraryClass copy = null;
try {
Constructor[] constructors = LibraryClass.class.getDeclaredConstructors();
for (Constructor constructor : constructors) {
constructor.setAccessible(true);
copy = (LibraryClass) constructor.newInstance();
break;
}
} catch (Exception e) {
e.printStackTrace();
}
}
I don't think this is possible, looking at this post and these docs. What you could possibly do is place the two (or however many) class files into their own package and then use the protected access modifier so that the constructor is only usable within the package. If you only place classes that inherit from the LibraryClass class it would have the same effect as making the constructor private as indicated above.
I have a class with a local inner class in one of its methods:
public class Outer {
String hello = "hello";
public void myMethod() {
class Inner {
public void myInnerMethod() {
System.out.println(hello);
}
}
[...really slow routine...]
(new Inner()).myInnerMethod();
}
}
I would like to test the myInnerMethod(). So I instantiate the local inner class using reflection and call the myInnerMethod() on it.
public void test() {
Object inner = Class.forName("Outer$Inner").newInstance();
inner.getClass().getDeclaredMethod("myInnerMethod").invoke(inner); // hello will be null
}
But when myInnerMethod() accesses hello, which is in the scope of the Outer class, it is null.
Is there a way to mock or otherwise provide hello to myInnerMethod()?
I know I could refactor my code by extracting the inner class or just test the public methods of Outer. But is there still a way to do it?
You would need to make some small refactoring before being able to verify the inner behavior:
1) Create a package level method that would contain the code invoked from within the myInnerMEthod:
public class Outer {
String hello = "hello";
public void myMethod() {
class Inner {
public void myInnerMethod() {
Outer.this.printHello(hello); // !!! change here
}
}
[...really slow routine...]
(new Inner()).myInnerMethod();
}
void printHello(String hello){/* */} // !! add this
}
2) Spy on the Outer class and verify the printHello has been called with the hello instance variable:
public void test() {
// Arrange
Outer outerSpy = spy(new Outer());
doNothing().when(outerSpy).printHello(anyString()); // optional
// Act
outer.myMethod();
// Assert
verify(outerSpy).printHello("hello");
}
I have learnt that static nested class should be accessed like a field of outer class(line 2). But even instantiating the inner class directly worked (line 1). Can you please help me understand?
public class OuterClass
{
public OuterClass()
{
Report rp = new Report(); // line 1
OuterClass.Report rp1 = new OuterClass.Report(); // line 2
}
protected static class Report()
{
public Report(){}
}
}
accessed like a field of outer class
And that's what you are doing. Imagine this:
class OuterClass
{
SomeType somefield;
static SomeType staticField;
public OuterClass()
{
//works just fine.
somefield = new SomeType();
//also works. I recommend using this
this.somefield = new SomeType();
//the same goes for static members
//the "OuterClass." in this case serves the same purpose as "this." only in a static context
staticField = new SomeType();
OuterClass.staticField = new SomeType()
}
}
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