Change Inner Java Class Modifier to Public via Reflection - java

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.

Related

Why am I throwing no errors for calling object-specific methods/fields from inner classes?

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);
....
}

non-static inner class name as a type parameter

is there a way to use a non-static inner class name as a type parameter?
something like that:
public class Foo {
...
// non-static inner class
public class Bar {
...
}
}
and somewhere
public Baz<Bar> obj;
if class Bar had been static I could have written
public Baz<Foo.Bar> obj;
but in this case a non-static variable in Foo cannot be used in Bar. The problem is I need to use a non-static member of Foo in Bar.
The real situation in a Java Play framework based web app:
public class SignupController extends Controller {
#Inject
private UserService userService;
...
public class SignupForm {
public String validate() {
if (userService.findUserByEmail(email) != null) {
return Messages.get("error.email.is.in.use");
}
return null;
}
}
}
in a veiw template
#(signupForm: Form[controllers.SignupController.SignupForm])
...
userService must be seen in the inner class SignupForm and must not be static. This is why SignupForm cannot be static either.
unfortunately this will not be compiled.
is it possible to use SignupForm as a type parameter of class Form?
thanks in advance.
public Baz<Foo.Bar> obj;
To access the inner class as above, you don't need to make it static. It is directly accessible and perfectly compiles.
Why this works: Qualified Type Names
Because you are trying to access is a type using a type, which is perfectly legal for java compiler.
Here is a sample code. which compiles perfectly:
public class outer {
public class inner {
}
}
class another {
private List<outer.inner> list = new ArrayList<>();
public List<outer.inner> method() {
return new ArrayList<>();
}
}

How to instantiate an inner class with reflection in Java?

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});

Invoke Super class methods using Reflection

I have 2 classes, say A & B:
Class A extends B {
public void subClassMthd(){
System.out.println("Hello");
}
}
Class B {
public void printHelloWorld {
System.out.println("Hello");
}
}
Now, I am using reflection to invoke the methods on Class A. I would also like to invoke the printHelloWorld method present in Class B.
I tried using
Class clazz = Class.forName("com.test.ClassA");
Object classAInstance= clazz.newInstance();
Method superClassmthd = classAInstance.getClass()
.getSuperclass().getMethod("printHelloWorld", null);
superClassmthd.invoke(classAInstance);
Also tried as
Class clazz = Class.forName("com.test.ClassA");
Object classAInstance= clazz.newInstance();
Class superClazz = Class.forName(classAInstance.getClass().getSuperclass().getName());
Object superclassInstance = superClazz.newInstance();
Method superClassmthd = superclassInstance.getMethod("printHelloWorld", null);
superClassmthd.invoke(superclassInstance );
But none of them work; they throw an InstantiationException.
What am I doing wrong here?
Try this:
Method mthd = classAInstance.getClass().getSuperclass().getDeclaredMethod("XYZ");
mthd.invoke(classAInstance)
The difference is using getDeclaredMethod(), which gets methods of all visibilities (public, protected, package/default and private) instead of getMethod(), which only gets methods with public visibility.
What is the visibility of the methods you want to call (public, private etc).
If you want to see methods which you cannot call directly, you should use getDeclaredMethod().
Also, what the the constructors of your classes like? InstantiationException indicates that you are having trouble getting an instance of class A (or B).
I have the following code and it works:
A.java
import java.lang.reflect.Method;
public class A extends B {
public static void main(String[] args) throws Exception {
A classAInstance = new A();
Method mthd = classAInstance.getClass().getSuperclass().getMethod("XYZ", null);
mthd.invoke(classAInstance);
}
}
B.java
public class B {
public void XYZ() {
System.out.println("done");
}
}

How to use an instance of a class that has a private constructor?

If we have class A & B, and class A's constructor is private, and we want to use an instance of A in B, how to do that ? I see an answer that says "provide a static method or variable that allows access to an instance created from within the class " but I didn't understand that.
The code pattern you seek is called the Factory Method.
The class provides a static method that returns an instance of its own class. Private constructors are visible to all methods (including static ones) of the class, so the static method can invoke the private constructor on the caller's behalf.
Here's an example of this pattern in action:
public class A {
private A() {
}
public static A create() {
return new A();
}
}
This is often employed in conjunction with the Singleton Pattern, which would change the above example to this:
public class A {
private static A INSTANCE = new A();
private A() {
}
public static A getInstance() {
return INSTANCE;
}
}
A needs to have a public method that provides an instance of the class A, eg:
class A {
/*Constructors and other methods omitted*/
public static A getInstance() {
return new A();
}
}
Alternatively, if B is an inner class of A (or vice-versa), then B can directly reference the constructor eg:
public class A {
private A() {}
public static class B {
private A instanceOfA = new A();
public B() {}
}
}
A class that only has private constructors is designed so that other classes cannot instantiate it directly. Presumably there is a sound reason for this. The class may provide a factory method for instantiating the class ... or getting an existing instance of the class.
If you need to change the design, the best way is to modify the class; e.g. by making a constructor visible, or by adding a factory method. If you can't do that, I think it is possible to use reflection to break the visibility rules and create an instance using a private constructor. However, I'd only do this as a last resort ... and not before carefully analysing the consequences for the overall application.
Private constructors are intended to make a class not to have any instance. But the content can be accessed from child class using super(). Implementation is like this:
public class ClassA {
private int val;
private ClassA(int val)
{
this.val = val;
}
public int getVal() {
return val;
}
}
public class ClassB extends ClassA {
public ClassB(int val) {
super(val); } }
...
ClassB b = new ClassB(4);
System.out.println("value of b: " + b.getVal());
As an example see class Calendar. To get an instance you must not call its constructor but use a static method:
Calendar rightNow = Calendar.getInstance();
source

Categories