>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 proto...@googlegroups.com.
To unsubscribe from this group, send email to 
protobuf+unsubscr...@googlegroups.com.
For more options, visit this group at 
http://groups.google.com/group/protobuf?hl=en.

Reply via email to