Getting value of private not primitive field using reflection - java

Presume we have two different packages... one package can't be accessed but we like to know the value of a complex field called b.
public class A {
private String whatever;
private B b;
private static class B {
final ArrayList<Z> c = new ArrayList<Z>();
private void addItem(Z z) {
this.c.add(z);
}
private Z getItem(int nr) {
return this.c.get(nr);
}
}
}
public class Reflect extends A {
public static void main(String[] args) throws NoSuchFieldException, SecurityException {
Reflect ref = new Reflect();
Class getA = ref.getClass().getSuperclass();
Field getB = getDeclaredField("b");
getB.setAccessible(true);
Class bInst = getB.getClass();
Method bMeth = bInst.getMethod("getItem", Integer.TYPE);
Object zInst = bMeth.invoke(new Integer(123));
}
}
How can I get the value if I don't get the complex type B from the package ?
Still get java.lang.NoSuchMethodException: stackOver.A.getItem(int) even I set the field gstB accessible ....

The only thing you are missing is that getField only gives you public accessible fields.
Field getB = getA.getDeclaredField("b");
will give you any field of that class.
A longer example
class Main {
public static class A {
private String whatever;
private B b = new B();
private static class B {
final ArrayList<String> c = new ArrayList<String>();
private void addItem(String z) {
this.c.add(z);
}
private String getItem(int nr) {
return this.c.get(nr);
}
}
}
public static class Reflect extends A {
public static void main(String... ignored) throws Exception {
Reflect ref = new Reflect();
Class getA = ref.getClass().getSuperclass();
Field getB = getA.getDeclaredField("b");
getB.setAccessible(true);
Object b = getB.get(ref);
Method addItem = b.getClass().getDeclaredMethod("addItem", String.class);
addItem.setAccessible(true);
addItem.invoke(b, "Hello");
Method getItem = b.getClass().getDeclaredMethod("getItem", int.class);
getItem.setAccessible(true);
String hi = (String) getItem.invoke(b, 0);
System.out.println(hi);
}
}
}
prints
Hello

How can I get the value if I don't get the complex type B from the package ?
You can get it as an Object, and then use reflection to further discover the methods that it exposes.
Object bInst = ... // Get b through reflection
Class bClass = bInst.getClass();
Method[] bMeth = bClass.getMethod("getItem", Integer.TYPE);
Object zInst = bMeth.invoke(new Integer(123));

Use commons beanutils library and use following method, it is much cleaner than doing it yourself
PropertyUtils.getNestedProperty(ref, "b.propertyOfClassB");
replace propertyOfClassB with actual property name.

Related

How to access a private field in a private field in another class using Java

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.

How do I reflect a private static nested subclass?

First, I'm looking for an answer in Kotlin, but I'm interacting with a Java library.
I need to get an instance from a private static nested class, derived from an instance of the surrounding superclass.
Given you have these (simplified) nested Java classes
public abstract class GLFWKeyCallback extends Callback implements GLFWKeyCallbackI {
public static GLFWKeyCallback create(GLFWKeyCallbackI instance) {
new Container(instance.address(), instance);
}
private static final class Container extends GLFWKeyCallback {
private final GLFWKeyCallbackI delegate;
Container(long functionPointer, GLFWKeyCallbackI delegate) {
super(functionPointer);
this.delegate = delegate;
}
}
}
I get back a Container instance as a GLFWKeyCallback, by way of another external method. You can think of this method as:
public static GLFWKeyCallback getCallback() {
return GLFWKeyCallback.create(anInternalInstance)
}
in Kotlin:
val callback:GLFWKeyCallback = getCallback()
// I would now want to cast,
// or in other ways use callback
// as the GLFWKeyCallback.Container class it actually is.
val callbackAsContainer = callback as GLFWKeyCallback.Container // Error: Container is private
val ContainerClass = GLFWKeyCallback::class.nestedClasses.find { it.simpleName?.contains("Container") ?: false }!!
// Gives me a KClass<*> that I don't know how to use, can't find documentation for this kind of circumstance
// If using the class instance itself is not possible I would at least want to get the
// Container.delegate of GLFWKeyCallbackI
val delegateField = ContainerClass.memberProperties.findLast { it.name == "delegate" }!!
val fieldValue = field.get(callback)
// Error: Out-projected type 'KProperty1<out Any, Any?>' prohibits the use of 'public abstract fun get(receiver: T): R defined in kotlin.reflect.KProperty1'
Why you don't want to use Java reflection? You can use it also from Kotlin:
val callback = getCallback()
val field = callback::class.java.getDeclaredField("delegate")
field.isAccessible = true
val delegate = field.get(callback) as GLFWKeyCallbackI
You can still get the class via .getClass(). This example prints '5':
public class Example {
public static void main(String[] args) throws Exception {
Object o = Target.get();
Field f = o.getClass().getDeclaredField("field");
f.setAccessible(true);
Integer i = (Integer) f.get(o);
System.out.println(i);
}
}
public class Target {
public static Object get() { return new Inner(); }
private static class Inner {
private int field = 5;
}
}
If you know precise names:
Class<?> c = Class.forName("com.foo.pkgof.Target$Inner");
c.getDeclaredField("field");
works. Note the dollar. That's the separator to use between 'outer' and 'inner'.

Cannot get value of property from extending class

I have two Java classes, one of which inherits from other. They are somewhat like the following:
A.java:
public class A {
public String invocations[] = {"foo"};
public A() {
// do stuff
}
}
B.java:
public class B extends A {
public String invocations = {"bar", "baz"};
public B() {
super();
}
}
In this example, assuming I create an instance of B and get its invocations property, it returns {"foo"} instead of the expected {"bar", "baz"}. Why is this, and how can I get the {"bar", "baz"}?
You have one variable hiding another one. You can refer to a variable in a super class by using a cast to the type explicitly. (I am assuming you fix the syntax errors)
public class Main {
static class A {
public String[] invocations = {"foo"};
}
static class B extends A {
public String[] invocations = {"bar", "baz"};
}
public static void main(String... args) {
B b = new B();
System.out.println("((A)b).invocations=" + Arrays.toString(((A) b).invocations));
System.out.println("b.invocations=" + Arrays.toString(b.invocations));
}
}
prints
((A)b).invocations=[foo]
b.invocations=[bar, baz]

Set and get a static variable from two different classes in Java

Lets say I have 3 Classes: A, Data, and B
I pass a variable from class A which sets that passed variable to a private variable in class Data.
Then in class B, I want to call that specific variable which has been changed.
So I do
Data data = new Data();
data.getVariable();
It will then return null, since in class Data I initialize variables to nothing (ex: int v;), and I think that class B is initializing a brand new class and resetting the values to default, but I don't know how to fix this.
I know that the variable is setting properly because in class A if I do data.getVariable() it will print the variable that was set.
Class A:
Data data = new Data();
int d = 1;
data.setVariable(d);
Class Data:
private static int b;
public void setVariable(int s)
{
b = s;
}
public int getVariable()
{
return b;
}
Class B:
Data data = new Data();
private int v;
v = data.getVariable();
System.out.println(v);
This will print out 0 instead of the actual value
When you instantiate a Data object in class A, and instantiate another Data object in class B, they are two different instances of the Data class. They both instantiate d to 0 by default. You then call setVariable on the instance in class A and pass it the value of 1; but the instance in class B remains in 0. In order to change the value of the instance in class B, you would need to call setVariable on the instance in class B.
What it seems like you're looking for is a static member. Static members are the same across all instances of the same class. Just put the static keyword before the method(s) or field(s) that you want to use it. Static members and fields are typically accessed using the name of the class in which they are declared (i.e. MyClass.doMethod()). For example:
Class Data (updated):
private static int b;
public static void setVariable(int s)
{
b = s;
}
public static int getVariable()
{
return b;
}
Class A:
Data.setVariable(d);
Class B:
v = Data.getVariable();
System.out.println(v);
Editing - my first suggestion was to use static for variable b, and the author changed his question adding that suggestion.
It fixes what you are trying to do. I write the example in code that compiles:
public class Demo {
public static void main(String[] args) {
A a = new A();
B b = new B();
a.doWhatever();
b.doSomethingElse();
}
}
class Data {
private static int b;
public void setVariable(int s)
{
b = s;
}
public int getVariable()
{
return b;
}
}
class A {
public void doWhatever() {
Data data = new Data();
int d = 1;
data.setVariable(d);
}
}
class B {
Data data = new Data();
private int v;
public void doSomethingElse() {
v = data.getVariable();
System.out.println(v);
}
}

static variable initialization java

how to initialize a private static member of a class in java.
trying the following:
public class A {
private static B b = null;
public A() {
if (b == null)
b = new B();
}
void f1() {
b.func();
}
}
but on creating a second object of the class A and then calling f1(), i get a null pointer exception.
The preferred ways to initialize static members are either (as mentioned before)
private static final B a = new B(); // consider making it final too
or for more complex initialization code you could use a static initializer block:
private static final B a;
static {
a = new B();
}
Your code should work. Are you sure you are posting your exact code?
You could also initialize it more directly :
public class A {
private static B b = new B();
A() {
}
void f1() {
b.func();
}
}

Categories