Android: how to get an instance of a member field via reflection - java

Here's a fairly convoluted question. I am trying to access the webviewcore instance member of a webview via reflection. I want a reference to the webviewcore that is used by my webview, so that i can invoke a method that the webviewcore uses. I have to do this via reflection because the public sdk does not let you access this class. I know using reflection to do this is discouraged but i've made my peace with that.
I've read here that to achieve this i would do something like this:
Class aClass = MyObject.class
Field field = aClass.getField("someField");
MyObject objectInstance = new MyObject();
Object value = field.get(objectInstance);
field.set(objetInstance, value);
The problem with doing this (and maybe im misunderstanding this) is that it looks like i have to create a new instance of the WebViewCore to work with and then set it back to my instance. First and formost, am i understanding this correctly. If so, then can someone translate the code above to do what i am looking for it to do. If my understanding is incorrect, does anyone know how else i can access the WebViewCore of an instance of a webview?
Thanks!
EDIT: Due to confusion i will restate my question. I have an instance of a webview. That webview has a member field called 'mWebViewCore' which is an instance of the WebViewCore class. The WebViewCore has a member class called called TextSelectionData. I need to access the the TextSelectionData object via reflection. I know how to access fields and methods of the webview through reflection. So i can get mWebViewCore field, but i don't know how to take that field and access it's fields, methods, classes etc. The broadstrokes are take an instance of an object, find a specific field in that instance, and access the fields of that field.
Sorry for the confusion. It come from my weak understanding of reflection, and partially from the fact that i didn't adequately understand WebViewCore class. here's where i've gotten to in the code:
Class c = mWebView.getClass();
try {
Field webViewCoreField = c.getDeclaredField("mWebViewCore");
webViewCoreField.setAccessible(true);
//how do i get the fields of webViewCoreField?
}

Assuming a WebViewCore with a private String s field:
public class WebViewCore {
private String s;
public WebViewCore(String s) { this.s = s; }
#Override
public String toString() {
return "WebViewCore{" + "s='" + s + '\'' + '}';
}
}
Assuming a WebView with a private WebViewCore webViewCore field:
public class WebView {
private WebViewCore webViewCore;
public WebView() { webViewCore = new WebViewCore("ohai"); }
}
Now we reflect:
public class Main {
public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException {
// First get the private WebViewCore field...
Field fWvc = WebView.class.getDeclaredField("webViewCore");
fWvc.setAccessible(true);
System.out.println(fWvc);
// Then get an instance of a WebView; you already have one,
// I'm constructing one...
WebView wv = new WebView();
WebViewCore wvc = (WebViewCore) fWvc.get(wv);
System.out.println(wvc);
// Now get the private String field from the WebViewCore class...
Field fS = WebViewCore.class.getDeclaredField("s");
fS.setAccessible(true);
System.out.println(fS);
// Now get the value of the private String field from the instance
// of the WebViewCore we retrieved above...
String s = (String) fS.get(wvc);
System.out.println(s);
}
}
So, here's my rant: reflection is a relatively advanced technique, although it's pretty straight-forward. (With the caveat I've been doing this for a really long time, with languages that have better reflective abilities than Java.)
This seems to still be a bit out-of-reach--that being the case, I'd be really, really careful about using it, and would avoid it at essentially any cost. I question your need to do whatever it is you're trying to do, and after that, I'd question the wisdom of doing whatever it is you're trying to, until stuff like the toy example we're mucking with here causes zero conceptual issues.
Here there be dragons, and they will cook and eat you.

Reflection offers you ability to access private fields, private methods of a class(or rather, an object), and runtime informations.
Your understanding of reflection is correct. But in the code snippet you posted, your use of reflection does not make sense to me. You are setting a value to a field with a value from that field, i.e. you are doing something like:
obj.setValue(obj.getValue());
You said you wanted to access a private field of WebView, I assume you already have the WebView instance, so once you get the Field reference, you just set the value of that field on your original WebView instance, you don't and shouldn't create a new WebView object, because it was the original WebView object that you wanted to operate on.
Something like this:
WebView myWebView = ...;
Object myValueToSet = ...;
Class webViewClass = WebView.class
Field field = webViewClass.getField("someField");
field.setAccessible(true);
field.set(myWebView, myValueToSet);

Related

Java nested enum understanding

I want to ask about nested enums. I am working with old code and i found very strange construction that i not really good understand.
I have this enum :
public enum DbEngines {
ORACLE("oracle", "set define on", "set define off")
, POSTGRESQL("postgresql", "--TODO set define on", "--TODO set define off");
private final String dbEngine;
private String setOn;
private String setOff;
DbEngines(String dbEngine, String setOn, String setOff) {
this.dbEngine = dbEngine;
this.setOn = setOn;
this.setOff = setOff;
}
public String getSetOn() {
return setOn;
}
public String getSetOff() {
return setOff;
}
public String toString() {
return this.dbEngine;
}
}
I added private String to this enum, that are engine specific, so it is good place for me here. The problem is, that in some places in method declaration i see something like that
public someMethod(Enum<DbEngines> engine, ...)
And it worked perfectly without methods, but now, after changing, I couldn't call public getters of this enum. But if i change to :
public someMethod(DbEngines engine, ...)
it works without any problems with all public getters. Maybe someone could explain that?
Enum in Java is the base class for all enumeration types. One can think of it as similar to Object class.
Just like one can hold reference of object of any class using the reference of type Object, one can refer to an enumeration type using the reference of type Enum.
Object o = new Integer(10);
Enum e = DBEngine.ORACLE;
One cannot invoke a method present in inherited class but absent in superclass using the reference of superclass.
Similar explanation over here.

Java :Setter Getter and constructor

I'm a bit confused about the use of getter/setters and constructors (see the below code for an example)
public class ExampleClass {
private int value = 0;
public ExampleClass () {
value = 0;
}
public ExampleClass (int i) {
this.value = i;
}
public int getValue() {
return value;
}
public void setValue(int val) {
this.value = val;
}
public static void main(String[] args) {
ExampleClass example = new ExampleClass (20);
example.setValue(20);
//Both lines above do same thing - why use constructor?
System.out.println(example.getvalue());
}
}
All I've learned is that we need getters/setters for security and that they can also be used to change or edit values later on.
My question is that if the constructor is the point of initialization and a default constructor is always present, why use a constructor with parameters to initialize values instead of getters/setters?. Wouldn't using the getter and setter provide security as well being able to easily change values at any stage. Please clarify this point for me.
default constructor is always there
Well actually its not always there. A default constructor is the one which is provided by the compiler (of course it is a no-arg constructor ) Only if there is no other constructor defined in the class
why we use constructor with parameters to initialize values instead of set get
Because there could be a condition that an object can always be created only when all the values are provided at the time of initialization itself and there is no default value. So all values must be provided otherwise code will not compile.
Consider this Book class
public class Book {
private String title;
private String author;
public Book(String title, String author){
this.title = title;
this.author = author;
}
//getters and setters here
}
Consider a condition where a book can be created only if it has title and author.
You cannot do new Book() because no-arg constructor is absent and compiler will not provide one because one constructor is already defined.
Also you cannot do new Book() because our condition does not meet as every book requires a title and author.
This is the condition where parameterized constructor is useful.
Sometimes, when creating a new object of a class, some values HAVE TO be provided. For an example, when connecting to database and creating Connection class object you have to provide a connection string, so that it knows what are you connecting to. Creating new connection without specyfing target database would be pretty useless, right?
Also, take a look at this
Foo foo=new Foo(1,2,3,4,5,6,7);
and this
Foo foo=new Foo();
foo.setP1(1);
foo.setP2(2);
foo.setP3(3);
foo.setP4(4);
foo.setP5(5);
foo.setP6(6);
foo.setP7(7);
First one looks better, right?
My question is that if constructor is point of initialization and
default constructor is always there so why we use constructor with
parameters to initialize values instead of set get.
If you think about an object transitioning into different states then it makes sense to have a parameterized constructor alongwith setters and getters. Let me try to put a real life scenario: Think about an Employee class, a new employee joins, you don't know many details but few and you create the object of Employee with defualt and base value of its attributes. You need to register the employee in the system and hence you used the parameterized constructor. Once you get more details about the employee, you use getters and setters to update the attributes.
this is purely upto your coding style. But IMO, I would use parametrized constructor:
to initialize those values which should not be changed. (like username parameter for a person object)
to initialize those values, without setting which, the object will be in invalid state.
Say, you are sending login parameters to a method. You can use in these to ways
Login obj = new Login();
obj.setUsername("user");
obj.setPassword("pw")// what if someone commented this out, or you forget to call it
and otherway,
Login obj = new Login("user", "pw");
while you can send Login object just after setting username in 1st case, it would be invalid at recieving end. but the second method is less prone to bugs, bcz it becomes necessary to pass all the required parameters.
Just to make it easier. It takes less code to use a constructor than to create an object and use the setters.
Sometimes you don't need to set all the fields to specific values at the time of creating. For examle, when you make an array. Also, as already said, it's safer when you use getters -- you can't get nullpointer.
Remember to write the default constructor when you've defined constructor with parameters. Or be sure not to use it.
First, both methods: Constructor and Setter are safe ways to change object's attributes. Are expected from Class author to expose or not safe ways to modify an instance.
The default constructor is always provided if you have not written one:
// Example of a Class with a Default Constructor
public class GetSet {
private String value;
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
public static void main(String[] args) {
// Theres a implicit Default Constructor here
// Its ok to do that
// GetSet obj = new GetSet();
GetSet obj = new GetSet();
}
}
// Example of a Class without a Default Constructor
public class GetSet2 {
public GetSet2(String value) {
this.value = value;
}
private String value;
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
public static void main(String[] args) {
// GetSet2 obj = new GetSet2(); // compile time error
// Default constructor is not provided, since u wrote one
}
}
2. About which is better: Using a constructor or via setter, it depends on what u want. If you will only modify an attribute of a existing object, u may use the setter, or for a completely filled object you may prefer the constructor instead.
// Example of modifing an obj via Setter and Constructor
public class GetSet3 {
public GetSet3(String value1, String value2, String value3, String value4) {
this.value1 = value1;
this.value2 = value2;
this.value3 = value3;
this.value4 = value4;
}
private String value1;
private String value2;
private String value3;
private String value4;
// ... Getters and Setters
public static void main(String[] args) {
// Its easier to this
GetSet3 obj;
obj= new GetSet3("j", "a", "v", "a");
// instead that
// its also easy to forget or do something wrong
// when u have a lot of attributes to set
obj.setValue1("j");
obj.setValue2("a");
obj.setValue3("v");
obj.setValue4("a");
}
}
It's easier and safer to initialize your object variables via your constructor to avoid nullpointers.
If you instantiate your object without initializing your variables first and you do a get operation on one of your null variables, you might get a nullpointer exception at runtime because you forgot to manually set its value.
On the flipside of that, if you always initialize your object variables in your default constructor, you have a seriously reduced risk of getting nullpointer exceptions during runtime because none of your variables can be null unless you specifically set them via a setter (which is not recommended).
Constructor with arguments makes you get the object fully constructed. If you want to use default one, you will have to make sure the fields are set using setters. During set of some property, assume the exception is thrown, now you have an object which is not usable. In several cases, setter wouldn't be exposed but getters. In those cases, having constructor with arguments or a named constructor is the right option. In a nutshell, getters and setters do have their own importance rather than initializing the object.
Why use getters and setters?
Because you write it using less, more elegant and better readable code when you set the values as parameters in a constructor. Moreover, sometimes some fields are indispensable for the object, so a parameter constructor prevents the user from creating an object omitting necessary fields for the object's functionality. One is though not "oblidged" to call the setters.
To answer this question, I say by writing getters/setters, we create a provision to add any validation method in the future, currently, there is no validation, but if anything goes wrong in the future we just add validation logic in the setter.
we can also write the logic/validation in constructors but it's not a good practice. The constructor should be used only to initialize your object's state/fields. You should delegate the responsibility of other things to other methods.
Note that a constructor is called only once i.e, whenever you create a new object With a sufficiently large input, you can cause an exception in your constructor.
This is one of several reasons why you should not use a constructor to contain "business logic".

Java - set an object variable via setter method, but I dont want the ability to change it again

I have Spring Web Services project, where I have access to the logged in username.
The processes then takes place via several classes, but what I want to do is, set the username in a User class/bean when I first receive it in the first class.
i.e. the following:
My first web services class:
// Set the Spring Security Name of the user
user.setSpringSecurityUsername(request.getUserId());
String springSecurityUsername = user.getSpringSecurityUsername();
My User class
private String springSecurityUsername = "";
private final String windowsUsername = System.getProperty("user.name");
public String getSpringSecurityUsername() {
return springSecurityUsername;
}
public void setSpringSecurityUsername(String springSecurityUsername) {
this.springSecurityUsername = springSecurityUsername;
}
public String getWindowsUsername() {
return windowsUsername;
}
I want to be able create a new instance of the User bean and set the SpringSecurityUsername. I then wish to pass the user object to the other processing classes, but I don't what them to have access to the setter method in the user (e.g. don't want other classes to be able to use the .setSpringSecurityUsername.
I only want to be able to set it the once.
Can anyone help with this?
I only want to be able to set it the once.
It sounds like you should be passing it to the constructor then. You've referred to the class as a bean in some cases - does it have to be a strict JavaBean with a parameterless constructor? Or should everything still work for you if you just add a constructor?
The benefit of putting it into the constructor over ignoring/throwing on a second setSpringUsername call is that you simply can't express the incorrect code. It's always better to make something impossible than to have to tell people not to do it :)
(It also means you can make it a final field, too.)
It sounds like the initializing value should just be a constructor parameter and there should be no setter method at all. In the case it's also valid to never call the setter, include both a constructor without the argument and one with the argument.
Initialize it internally with some value, then in your setter check to see if it still has that value. If it does, allow it to be set. If it doesn't it has already been set - simply do nothing in that case.
You can't prevent the method from being called, but you can check whether it got called previously:
boolean usernameSet = false;
public synchronized void setSpringSecurityUsername(String springSecurityUsername) {
if (!usernameSet) {
this.springSecurityUsername = springSecurityUsername;
usernameSet = true;
}
}
This is actually a requirement of the builder pattern. You have each setter return "this" and when you want to finalize it you call a method like "finish" to disable all the setters. Goes like this:
new MyClass()
.setAge(20)
.setWeight(200)
.setHeight(6.0)
.finish();
Not a bad pattern at all, kind of gives you named parameters for java without losing the advantages of a immutability.
I would say go for setting it in constructor and no setter methods.
public User(String userName){
this.springSecurityUsername = userName;
}
Here's some code that will allow it to be set once:
private Object v;
public void setV(Object o) {
if (v == null)
v = o;
}
Or if null is a possible value zfor the first set, do this:
private Object notSer = new Object();
private Object v = notSer;
public void setV(Object o) {
if (v == notSer)
v = o;
}

What names should getter and setter methods have

I am still very confused about getter and setter methods. I had this code;
public class MethodsInstances {
public MethodsInstances(String name){
girlName = name;
}
private String girlName;
public String getName(){
return girlName;
}
public void sayName(){
System.out.printf("Your first gf was %s", getName());
}
}
But for "sayName", why couldnt you instead of using getName(), just type girlName? It would be the same, because getName() returns girlName, as seen in the code. Also, do the methods have to start with get and set, or can be named whatever you want?
Huge thanks from the newbie coder, Dan B
The point of getters and setters is that only they are meant to be used to access the private varialble, which they are getting or setting. This way you provide encapsulation and it will be much easier to refactor or modify your code later.
Imagine you use girlName instead of its getter. Then if you want to add something like a default (say the default name is 'Guest' if it wasn't set before), then you'll have to modify both the getter and the sayName function.
There is no requirement for getters and setter to start with get and set - they are just normal member functions. However it's a convention to do that. (especially if you use Java Beans)
You absolutely can use the variable directly in your example, mostly because sayName() is in the same class.
Other than that, I see 3 reasons for having getters and setters:
1.) It's a principle of object oriented programming to keep values (state) private and provide public methods for interaction with other classes.
2.) Classes with getters and setters often follow the Java beans design pattern. This pattern allows those objects to be used in template engines or expression languages like JSP or Spring.
3.) In some cases it prevents actual errors. An example:
public class DateHolder() {
public Date date;
public static void main(String... args) {
DateHolder holder = new DateHolder();
holder.date = new Date();
System.out.println("date in holder: "+holder.date);
Date outsideDateRef = holder.date;
outsideDateRef.setTime(1l);
//will be different, although we did not change anything in the holder object.
System.out.println("date in holder: "+holder.date);
}
}
wrapping the date variable with getter and setter that operate only with the value, not the reference, would prevent this:
public class DateHolder() {
private Date date;
public Date getDate() {
return (Date)this.date.clone();
}
public void setDate(Date date) {
this.date = (Date) date.clone();
}
public static void main(String... args) {
DateHolder holder = new DateHolder();
holder.setDate( new Date() );
System.out.println("date in holder: "+holder.getDate());
Date outsideDateRef = holder.getDate();
outsideDateRef.setTime(1l);
//Date in holder will not have changed
System.out.println("date in holder: "+holder.getDate());
}
}
You can use girlName here you really don't have to call getName(). The reason you need getName() is if you you want to get the name outside of this class. For example if you create a new class and then create the above class object in the new class and assign that object a name (value for girlName) you won't be able to access girlName from new class since it is private .. so you need a public method which will get the value for you.
Also it doesn't have to be getName or setName but this just makes it easy to understand what function is doing.
It's a common design patter to encapsulate the process of "getting" and "setting" variables in methods. This gives you more freedom if you ever want to change the underlying implementation.
For an example, lets say you one day want to change the parameter girlName to be an object Girl instead;
If you directly access girlName from your outer classes, you will have to change all your external code.
With a setter method, you could simply change one method and do
public void setGirlname(String name)
{
girlname = new Girl(name, some_other_data);
}
Or perhaps you want to make sure girlname always is returned with uppercase.
public String getGirlname()
{
return girlName.toUpperCase();
}
Thus giving you a loot more flexibility in your code design.
You must first read about abstraction, encapsulation and OOP to understand about accessors, mutators, immutability and data access.
We want to prevent direct access to the variable, we make the variable a private variable.
When the variable is private, other classes are not able to access that variable.
If we create variable as public it is accessible for all.
to change the actual private variable we will now need public getter() or setter().
The basic naming conventions say that we will take the name of the variable and prefix it with get and/or set.
in your specific case the getGirlname would be correct.
We call this encapsulation
This way you can inspect classes and invoke them at runtime using Reflection. See more here
HTH
Ivo Stoykov

How to read the value of a private field from a different class in Java?

I have a poorly designed class in a 3rd-party JAR and I need to access one of its private fields. For example,
why should I need to choose private field is it necessary?
class IWasDesignedPoorly {
private Hashtable stuffIWant;
}
IWasDesignedPoorly obj = ...;
How can I use reflection to get the value of stuffIWant?
In order to access private fields, you need to get them from the class's declared fields and then make them accessible:
Field f = obj.getClass().getDeclaredField("stuffIWant"); //NoSuchFieldException
f.setAccessible(true);
Hashtable iWantThis = (Hashtable) f.get(obj); //IllegalAccessException
EDIT: as has been commented by aperkins, both accessing the field, setting it as accessible and retrieving the value can throw Exceptions, although the only checked exceptions you need to be mindful of are commented above.
The NoSuchFieldException would be thrown if you asked for a field by a name which did not correspond to a declared field.
obj.getClass().getDeclaredField("misspelled"); //will throw NoSuchFieldException
The IllegalAccessException would be thrown if the field was not accessible (for example, if it is private and has not been made accessible via missing out the f.setAccessible(true) line.
The RuntimeExceptions which may be thrown are either SecurityExceptions (if the JVM's SecurityManager will not allow you to change a field's accessibility), or IllegalArgumentExceptions, if you try and access the field on an object not of the field's class's type:
f.get("BOB"); //will throw IllegalArgumentException, as String is of the wrong type
Try FieldUtils from Apache commons-lang3:
FieldUtils.readField(object, fieldName, true);
P.S. In my opinion, reflection is evil.
Reflection isn't the only way to resolve your issue (which is to access the private functionality/behaviour of a class/component)
An alternative solution is to extract the class from the .jar, decompile it using (say) Jode or Jad, change the field (or add an accessor), and recompile it against the original .jar. Then put the new .class ahead of the .jar in the classpath, or reinsert it in the .jar. (the jar utility allows you to extract and reinsert to an existing .jar)
As noted below, this resolves the wider issue of accessing/changing private state rather than simply accessing/changing a field.
This requires the .jar not to be signed, of course.
One other option that hasn't been mentioned yet: use Groovy. Groovy allows you to access private instance variables as a side effect of the design of the language. Whether or not you have a getter for the field, you can just use
def obj = new IWasDesignedPoorly()
def hashTable = obj.getStuffIWant()
Using the Reflection in Java you can access all the private/public fields and methods of one class to another .But as per the Oracle documentation in the section drawbacks they recommended that :
"Since reflection allows code to perform operations that would be illegal in non-reflective code, such as accessing private fields and methods, the use of reflection can result in unexpected side-effects, which may render code dysfunctional and may destroy portability. Reflective code breaks abstractions and therefore may change behavior with upgrades of the platform"
here is following code snapts to demonstrate basic concepts of Reflection
Reflection1.java
public class Reflection1{
private int i = 10;
public void methoda()
{
System.out.println("method1");
}
public void methodb()
{
System.out.println("method2");
}
public void methodc()
{
System.out.println("method3");
}
}
Reflection2.java
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
public class Reflection2{
public static void main(String ar[]) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException
{
Method[] mthd = Reflection1.class.getMethods(); // for axis the methods
Field[] fld = Reflection1.class.getDeclaredFields(); // for axis the fields
// Loop for get all the methods in class
for(Method mthd1:mthd)
{
System.out.println("method :"+mthd1.getName());
System.out.println("parametes :"+mthd1.getReturnType());
}
// Loop for get all the Field in class
for(Field fld1:fld)
{
fld1.setAccessible(true);
System.out.println("field :"+fld1.getName());
System.out.println("type :"+fld1.getType());
System.out.println("value :"+fld1.getInt(new Reflaction1()));
}
}
}
Hope it will help.
As oxbow_lakes mentions, you can use reflection to get around the access restrictions (assuming your SecurityManager will let you).
That said, if this class is so badly designed that it makes you resort to such hackery, maybe you should look for an alternative. Sure this little hack might be saving you a few hours now, but how much will it cost you down the road?
Java 9 introduced Variable Handles. You can access a private field of a class using them.
The code for your example will look like following:
var lookup = MethodHandles.lookup();
var handle = MethodHandles
.privateLookupIn(IWasDesignedPoorly.class, lookup)
.findVarHandle(IWasDesignedPoorly.class, "stuffIWant", Hashtable.class);
var value = handle.get(obj);
It is also advisable to use Lookup and VarHandle objects as static final fields.
Use the Soot Java Optimization framework to directly modify the bytecode.
http://www.sable.mcgill.ca/soot/
Soot is completely written in Java and works with new Java versions.
If using Spring:
In a testing context, ReflectionTestUtils provides some handy tools that can help out here with minimal effort. It's described as being "for use in unit and integration testing scenarios".
In a non-testing context, there is also a similar class named ReflectionUtils but this is described as "Only intended for internal use" - see this answer for a good interpretation of what this means.
To address the example in the original post:
Hashtable iWantThis = (Hashtable)ReflectionTestUtils.getField(obj, "stuffIWant");
You need to do the following:
private static Field getField(Class<?> cls, String fieldName) {
for (Class<?> c = cls; c != null; c = c.getSuperclass()) {
try {
final Field field = c.getDeclaredField(fieldName);
field.setAccessible(true);
return field;
} catch (final NoSuchFieldException e) {
// Try parent
} catch (Exception e) {
throw new IllegalArgumentException(
"Cannot access field " + cls.getName() + "." + fieldName, e);
}
}
throw new IllegalArgumentException(
"Cannot find field " + cls.getName() + "." + fieldName);
}
You can use jOOR for that.
class Foo {
private final String value = "ABC";
}
class Bar {
private final Foo foo = new Foo();
public String value() {
return org.joor.Reflect
.on(this.foo)
.field("value")
.get();
}
}
class BarTest {
#Test
void accessPrivateField() {
Assertions.assertEquals(new Bar().value(), "ABC");
}
}
Just an additional note about reflection: I have observed in some special cases, when several classes with the same name exist in different packages, that reflection as used in the top answer may fail to pick the correct class from the object. So if you know what is the package.class of the object, then it's better to access its private field values as follows:
org.deeplearning4j.nn.layers.BaseOutputLayer ll = (org.deeplearning4j.nn.layers.BaseOutputLayer) model.getLayer(0);
Field f = Class.forName("org.deeplearning4j.nn.layers.BaseOutputLayer").getDeclaredField("solver");
f.setAccessible(true);
Solver s = (Solver) f.get(ll);
(This is the example class that was not working for me)
It is quite easy with the tool XrayInterface. Just define the missing getters/setters, e.g.
interface BetterDesigned {
Hashtable getStuffIWant(); //is mapped by convention to stuffIWant
}
and xray your poor designed project:
IWasDesignedPoorly obj = new IWasDesignedPoorly();
BetterDesigned better = ...;
System.out.println(better.getStuffIWant());
Internally this relies on reflection.
Try to go around the problem for the case, the calass of which you want to set/get data is one of your own classes.
Just create a public setter(Field f, Object value) and public Object getter(Field f) for that. You can even do some securoty check on your own inside theses member functions. E.g. for the setter:
class myClassName {
private String aString;
public set(Field field, Object value) {
// (A) do some checkings here for security
// (B) set the value
field.set(this, value);
}
}
Of course, now you have to find out the java.lang.reflect.Field for sString prior to setting of field value.
I do use this technique in a generic ResultSet-to-and-from-model-mapper.

Categories