public class OuterClass {
private static class InnerClass {
public int id = 0;
}
private static InnerClass[] innerArr;
}
Need to get innerArr value with reflection in Java.
ClassLoader loader = Thread.currentThread().getContextClassLoader();
Class<?> cla = loader.loadClass("OuterClass");
Field innerArrRef = cla.getDeclaredField("innerArr");
innerArrRef.setAccessible(true);
OuterClass.InnerClass[] innerArrValue = (OuterClass.InnerClass[])innerArrRef.get(cla);
Above code doesn't work for InnerClass is a private class.
Let's adjust your OuterClass code a bit to make it more interesting: put in instance of InnerClass in the array:
private static InnerClass[] innerArr = { new InnerClass() };
Now you can't directly refer to the private type InnerClass in another class that is trying to get the static field using reflection. You can first refer to it as an array of Object.
public static void main(String[] args) throws Exception {
Class<?> cla = OuterClass.class;
Field innerArrRef = cla.getDeclaredField("innerArr");
innerArrRef.setAccessible(true);
Object[] innerArrValue = (Object[]) innerArrRef.get(cla);
You'll need to use reflection and the Class object to use the InnerClas type.
One way is to use the declaredClasses property of the OuterClass' class object:
Class<?> inner = cla.getDeclaredClasses()[0];
But if there's more than one member class, you need to loop through the array and search for the right one. Another way is to use the knowledge that javac will give your InnerClass a fully-qualified type name that looks like mypackage.OuterClass$InnerClass:
Class<?> inner = cla.getClassLoader().loadClass(cla.getName() + "$InnerClass");
Once you have the class object of the InnerClass, you can use reflection to access its field and methods:
Field id = inner.getField("id");
System.out.println("Inner id: " + id.getInt(innerArrValue[0]));
}
Related
I am clear that accessing a private field in Java could be easily achieved by using Reflection. As is shown in posts as How to read the value of a private field from a different class in Java? and there are many.
To achieve that , the critical move is to set accessibility.
Field f = obj.getClass().getDeclaredField("aaa");
f.setAccessible(true);
But in my case, the situation is like:
class A{
private B b;
class B{
private String value;
}
}
and I want to get value of a.b.value in another class. When I was trying, I intended to do it as
A obj = createInstanceA();
Field f = obj.getClass().getDeclaredField("b");
f.setAccessible(true);
A.B b = f.get(obj);
Field f2 = b.getClass().getDeclaredField("value");
f2.setAccessible(true);
String value = f2.get(b);
Which doesn't work out because B could not be declared out of A.
Do I have other options if Class A can not be modified?
You have do like this,
public class A {
private B b = new B();
class B {
private String value = "String";
}
}
public class ClassB {
public static void main(String args[]) throws NoSuchFieldException, SecurityException, IllegalArgumentException, IllegalAccessException{
A obj = new A();
Field f = obj.getClass().getDeclaredField("b");
f.setAccessible(true);
A.B b = (B) f.get(obj);
Field f2 = b.getClass().getDeclaredField("value");
f2.setAccessible(true);
String value = (String) f2.get(b);
System.out.println(value);
}
}
What you are missing is to setAccessible(true) to inner class field.
As a first, in your example field b is null. Is this correct?
So, you try to get class of null.
As a second, in your example you use inner classes and there is a specific langugage mechanizm. You can create instance of class B only by some instance of class A. And all instances of class B has access to private field of it's parrent (class A). As in this example.
class OuterClass
{
// static member
static int outer_x = 10;
// instance(non-static) member
int outer_y = 20;
// private member
private int outer_private = 30;
// inner class
class InnerClass
{
void display()
{
// can access static member of outer class
System.out.println("outer_x = " + outer_x);
// can also access non-static member of outer class
System.out.println("outer_y = " + outer_y);
// can also access private member of outer class
System.out.println("outer_private = " + outer_private);
}
}
}
// Driver class
public class InnerClassDemo
{
public static void main(String[] args)
{
// accessing an inner class
OuterClass outerObject = new OuterClass();
OuterClass.InnerClass innerObject = outerObject.new InnerClass();
innerObject.display();
}
}
May be inner classes can solves your problem? (You can read abou it here https://www.geeksforgeeks.org/nested-classes-java/)
Then reflecsoin is not needed.
Its said that, statics are much comfortable with statics in java. I'm trying to achieve small thing there where I want to change outer's class static variable value using inner static class's instance for that specific instance only. I think its a ideal case. If not please share with me. And moreover all inner classes have access to outer class's members.
So here is my code.
package org;
import org.Outerclass.innerclass;
public class Outerclass {
static String name = "Europe";
String getname() {
return name;
}
public void setname(String name) {
this.name = name;
System.out.println(this.name);
}
void setstaticname() {
Outerclass.innerclass i = new Outerclass.innerclass();
i.name = "London"; // Error "name cannot be resolved or is not a field" ?
System.out.println(i.name);
}
static class innerclass {
void updatename() {
Outerclass o = new Outerclass();
o.setname("USA");
}
}
public static void main(String[] args) {
innerclass p = new innerclass();
System.out.println(p.name); // Error "name cannot be resolved or is not a field" ?
}
}
I have tried in two ways and vice versa but same errors. Any suggestions ?
name is a member of OuterClass. And you are trying to access it using innerclass instance. That's why you are getting this error.
Also what is this + here System.out.println(+p.name); ?
Edit:
From inner class you can access outer class static members just like below:
name = "";
or
Outerclass.name = "";
change +p.name to name or OuterClass.name. + inside System.out.println will give you another compile time error.
static members are not available in object level they are available in class level. static are initialized at compile time where object is created at run time
i.name should be Outerclass.name since name is a member of Outerclass and not innerclass
in your code, i is an instance of innerclass.
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'm learning how to use inner classes, but I'm encountering a troubling error when I try to compile it. I'm trying to see how inner and outer classes can use one another's variables and methods.
When I try to compile this code it says:
.../src/MyOuter.java:39: non-static variable inner cannot
be referenced from a static context
Code:
public class MyOuter{
private int x;
public MyInner inner = new MyInner();
public int getOuterX(){
return x;
}
private void doStuff(){
inner.go();
}
class MyInner{
public int getInnerX(){
return x;
}
void go(){
x = 42;
}
}
public static void main(String[] args) {
MyOuter outer = new MyOuter();
outer.doStuff();
System.out.println("outer.x = " + outer.getOuterX());
System.out.println("inner.x = " + inner.getInnerX());
}
}
Thanks in advance for the help!
Since getInnerX() method is defined in MyInner class. You can't access it directly without the object of MyInner class .So change the line
System.out.println("inner.x = " + inner.getInnerX());
to
System.out.println("inner.x = " + outer.inner.getInnerX());
As was said, you first need to extract the inner variable before referencing it the static main method. Try something like the following:
{
public static void main(String[] args) {
MyOuter outer = new MyOuter();
MyInner inner = outer.inner;
outer.doStuff();
System.out.println("outer.x = " + outer.getOuterX());
System.out.println("inner.x = " + inner.getInnerX());
}
From Understanding Instance and Class Members:
Fields that have the static modifier in their declaration are called static fields or class variables. They are associated with the class, rather than with any object. Every instance of the class shares a class variable, which is in one fixed location in memory. Any object can change the value of a class variable, but class variables can also be manipulated without creating an instance of the class.
Since your inner variable is associated with an object, it cannot be referenced like a static variable might be. Were it static, it would be shared between all instance of 'MyOuter' and would be accessible in the manner you have tried there.
I have a Java class with a static variable
package com.mytest
public class MyClass{
public static final TextClass TEXT_CLASS = new TextClass();
}
How can I access the object TEXT_CLASS using reflection?
(I have the string "com.mytest.MyClass.TEXT_CLASS". I need to access the object.)
Accessing static fields is done exactly the same way as normal fields, only you don't need to pass any argument to Field.get() method (you can pass a null).
Try this:
Object getFieldValue(String path) throws Exception {
int lastDot = path.lastIndexOf(".");
String className = path.substring(0, lastDot);
String fieldName = path.substring(lastDot + 1);
Class myClass = Class.forName(className);
Field myField = myClass.getDeclaredField(fieldName);
return myField.get(null);
}