Overriding Object's toString method.
I want verbose output from my toString methods. I wrote a generic routine that introspects itself to output all the fields in the object. Great. But it can't just sit in a utility class since it needs to access private and protected fields.
What I want is to override the code in Object.toString( ) without violating the license agreement. Isn't there a way to inject the bytecode into the memory image of Object?
Rick
I don't think so... but maybe you could make a subclass of Object that would then be the superclass of all the classes you write after that? You would get the effect you want on your own classes but not on others, but then again you hardly need to debug other classes...
Replacing the code in java.lang.Object might not be such a good idea also because the API says exactly what the toString method should return so there can be apps that use that feature and depend on it.
I tried that, but I wasn't able to resolve access issues.I never seem to be able to get data out of the private fields even though I am calling my superclass method from within myself (so to speak). For example:
package stupendous;
import java.lang.reflect.*;
public class Object extends java.lang.Object
{
public String toString()
{
StringBuffer sb = new StringBuffer(this.getClass().getName() + "\n");
try
{
Field[] fa = this.getClass().getDeclaredFields();
for (int i = 0; i < fa.length; i++)
{
java.lang.Object ob = fa[i].get(this);
sb.append("" + fa[i].getName() + " : " + ob + "\n");
if (ob instanceof java.lang.Object[])
{
java.lang.Object[] oba = (java.lang.Object[])ob;
for (int j = 0; j < oba.length; j++)
{
sb.append("" + oba[j] + "\n");
}
}
}
}
catch (IllegalAccessException iae)
{
iae.printStackTrace();
}
return sb.toString();
}
}
public class SomeClass extends stupendous.Object
{
/// some fields
public String someMethod( )
{
return this.toString( );
}
}
Always returns this kind of stack trace:
java.lang.IllegalAccessException: Class stupendous.Object can not access a member of class stupendou
s.command.CommandLine with modifiers "private"
at sun.reflect.Reflection.ensureMemberAccess(Reflection.java:57)
at java.lang.reflect.Field.doSecurityCheck(Field.java:811)
at java.lang.reflect.Field.getFieldAccessor(Field.java:758)
at java.lang.reflect.Field.get(Field.java:228)
at stupendous.Object.toString(Object.java:15)
at java.lang.String.valueOf(String.java:2173)
at java.io.PrintStream.print(PrintStream.java:462)
at java.io.PrintStream.println(PrintStream.java:599)
at stupendous.command.CommandLine.main(CommandLine.java:83)
stupendous.command.CommandLine
Whoops, aren't I a bit careless today...
Private members can be accessed only from the class itself. If you want to include the values of private variables you'll need to actually write that method in *every* class you write... or use JNI and write the code for that in eg C and wrap it in a utility class.
I don't have any other ideas, sorry... maybe JVMDI could help?
yeah, by default the reflection API will not have access to private/protected variables. If you just need this functionality for debugging and can afford to grant these permissions, you can grant the the reflection permissions that will allow classes like Field and Method to access private/protected variables. Look at the permissions for accessDeclaredMembers or surrpressAccessCheck (I think I have that last permission wrong, but it is close- basically it allows you to access variables and methods that would normally be denied by an access check ... the second permission implies the first one). If those permissions are granted, you could just do some thing like:
Field [] fields = object.getClass().getDeclaredFields();
for (int i = 0; i < fields.length; i++) {
System.out.println("value of " + fields[i].getName() + " is " + fields[i].get());
}
Hai everybody, don't know whether i'm too late to join this topic.
But, I little bit not sure about the sample code given above, since there's no complete code, I don't know what CommandLine object doing so it throw access violation to the "private" member.
But let me share something that maybe usefull for all java fans here.
Basicly we can grant access to private member to trusted code using AccessibleObject.setAccessible() method.
Here are the sample:
Field[] fields = someObject.getClass().getDeclaredFields();
AccessibleObject.setAccessible(fields, true);
after adding above method, means that you granted access to all private fields to this trusted code.
so you can freely inspect or modify the contents of all private fields inside someObject.
regards,
Loekito Mulyadi <loekitom@centrin.net.id>
>AccessibleObject.setAccessible(fields, true);Now that is interesting.
Right... I vaguely remembered that trick, but there are special rules for applying as I recall. That will have to do. I want to thank you all for you help. Very informative.R