简体   繁体   中英

Boolean.FALSE not equal to false

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM