So I was playing with java.lang.reflect
stuff and tried to make something like this . And here is my problem (maybe a bug):
The code for my method to set the field to true:
private static void setFinalStatic(Field field, Object newValue) throws Exception
{
field.setAccessible(true);
Field modifiersField = Field.class.getDeclaredField("modifiers");
modifiersField.setAccessible(true);
modifiersField.setInt(field, field.getModifiers() & ~Modifier.FINAL);
field.set(null, newValue);
}
The code where I print it:
setFinalStatic(Boolean.class.getField("FALSE"), true);
System.out.format("%s\n", false); //prints true
System.out.println(false); //prints false
System.out.format("%s\n", Boolean.FALSE); //prints true
System.out.println(Boolean.FALSE); //prints true
System.out.println(Boolean.FALSE == false); //prints false
System.out.format("%s\n", Boolean.FALSE == false); //prints true
When you use System.out.format("%s", false)
it return "true", as expected
but when you use System.out.println(false)
it prints "false".
And when I tried this System.out.println(Boolean.FALSE == false)
it printed "false".
You you please explain this?
when you use System.out.println(false) it prints "false".
This boolean value is never autoboxed, so the change you make via reflection is not relevant.
Here is the call stack:
PrintStream::println(boolean x)
PrintStream::print(boolean b)
String::valueOf(boolean b)
String.valueOf(boolean)
is implemented like this:
public static String valueOf(boolean b) {
return b ? "true" : "false";
}
So the fact that you've changed the constant used by the wrapper class makes no difference. We never use the wrapper class.
And when I tried this System.out.println(Boolean.FALSE == false) it printed "false".
Boolean.FALSE
is automatically unboxed to a primitive true
. true == false
is false.
There is no bug, Boolean.FALSE
that you overridden is used for autoboxing because boolean
autoboxing is implemented by compiler silently calling Boolean.valueOf()
method with following body:
public static Boolean valueOf(boolean b) {
return (b ? TRUE : FALSE);
}
In your example boolean
parameters passed to methods using Object
type eg System.out.format(String, Object...)
will be subject to autoboxing. They will be affected by your reflective change and false
will become true
.
Otherwise methods using boolean
primitive won't be affected eg System.out.println(boolean)
and false
will stay false
.
The two most interesting lines in your example are:
System.out.println(Boolean.FALSE == false)
The compiler is unboxing Boolean.FALSE
by calling Boolean.FALSE.booleanValue()
which due to your reflection override returns true
. Since true == false
you get false
. This can be confirming by placing a breakpoint in Boolean.booleanValue()
.
System.out.format("%s\\n", Boolean.FALSE == false)
Although you do get false
from comparison as per point above, it will be autoboxed into a Boolean
to match the System.out.format(String, Object...)
method signature. This will output true
due to your reflection override.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.