The differences defined by theObjectInstance.amISafe() and cantModifyField.get(theObjectInstance).
After task g, the value of the the field doesn't change. The fact is simple, since the 2nd time create new instance without setting the private field will give it a inital value by itself.
But I do find some strange behaviors after changing this final field. Use get() and amISafe() tends to return different value, the get() will return the changed value "NOT SAFE", but the amISafe() method still return the inital value "I'm safe."
The fact is simple but maybe not simple. It is due to the mechanism of the keyword "final", as the JLS 17.5.3 Subsequent Modification of Final Fields said:
And furthermore, A final private variable of primitive type will be inlined by the compiler at compile-time, but things get different when happends at non-primitive type since a object reference won't be inlined at compiled time. And, yes, "String" in java is definitely not a primitive type.
That's pretty much of it!