>Obviously, if you want you can use it to mutate the object, but if you like
you can mutate even
>perfectly final and immutable objects in Java (using some trickery).
>I'm pretty sure that's not true. Effective Java, for example, suggests
using immutable classes as a
>security measure, which would be a terrible suggestion if they were not
really immutable.
Actually, unless there's a SecurityManager in place any member (even final)
is accessible. For instance,
I've used code similar to the following (valid on Sun JVM only, I think) to
directly read a String's char[] to avoid data copying.
I *could* have modified the value.
Cheers,
david
///////////////////////////////////////
import java.lang.reflect.*;
public final class ReflectionUtils {
public static final Field STRING_VALUE_FIELD =
getFieldAccessible(String.class, "value");
public static final Field STRING_OFFSET_FIELD =
getFieldAccessible(String.class, "offset");
public static final Constructor<?> STRING_PP_CTOR =
getConstructor(String.class, 0, int.class, int.class, char[].class);
public static char[] getChars(final String s) {
//
// use reflection to read the char[] value from the string. . .
//
try {
return (char[]) STRING_VALUE_FIELD.get(s);
} catch (Throwable e) {
//
}
return null;
}
public static String sharedString(final char[] chars, final int offset,
final int length) {
try {
return (String) STRING_PP_CTOR.newInstance(offset, length,
chars);
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
public static Field getFieldAccessible(final Class<?> clazz, final
String fieldName) {
Field fld = null;
try {
fld = clazz.getDeclaredField(fieldName);
fld.setAccessible(true);
} catch (NoSuchFieldException e) {
e.printStackTrace();
} catch (SecurityException e) {
e.printStackTrace();
}
return fld;
}
public static Constructor<?> getConstructor(final Class<?> clazz, final
int searchModifier, Class<?>... paramTypes) {
//
// N.B. there is no explicit value for "package-private," so pass 0.
//
try {
Constructor<?>[] allConstructors =
clazz.getDeclaredConstructors();
for (Constructor<?> ctor : allConstructors) {
if (searchModifier == (ctor.getModifiers() &
(Modifier.PUBLIC | Modifier.PRIVATE | Modifier.PROTECTED))) {
//
// access modifier match. . .
//
final Class<?>[] parameterTypes =
ctor.getParameterTypes();
if (parameterTypes.length == paramTypes.length) {
//
// same number of parameters. . .
//
for (int i = 0; i < parameterTypes.length; i++) {
if (!parameterTypes[i].equals(paramTypes[i])) {
ctor = null;
break;
} else {
// Type[] gpType =
ctor.getGenericParameterTypes();
// for (int j = 0; j < gpType.length; j++) {
// char ch =
(gpType[j].equals(paramTypes[i]) ? '*' : ' ');
// System.out.format("%7c%s[%d]: %s%n",
ch, "GenericParameterType", j, gpType[j]);
// }
}
}
if (ctor != null) {
// System.out.format("%s%n",
ctor.toGenericString());
// System.out.format(" [ synthetic=%-5b
var_args=%-5b ]%n", ctor.isSynthetic(), ctor.isVarArgs());
ctor.setAccessible(true);
return ctor;
}
}
}
}
// production code should handle this exception more gracefully
} catch (Exception x) {
x.printStackTrace();
}
return null;
}
public static void main(String[] args) {
getConstructor(String.class, 0, int.class, int.class, char[].class);
}
public static boolean setAccessible(AccessibleObject o) {
try {
o.setAccessible(true);
return true;
} catch (SecurityException e) {
e.printStackTrace();
}
return false;
}
}
--
You received this message because you are subscribed to the Google Groups
"Protocol Buffers" group.
To post to this group, send email to [email protected].
To unsubscribe from this group, send email to
[email protected].
For more options, visit this group at
http://groups.google.com/group/protobuf?hl=en.