Boolean.FALSE不等于false

时间:2019-02-04 13:30:01

标签: java reflection reflect

所以我在玩java.lang.reflect的东西,并尝试制作类似this的东西。这是我的问题(可能是一个错误):

我将字段设置为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);
}

我在其中打印的代码:

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

当您使用System.out.format("%s", false)时,它会按预期返回“ true”

但是当您使用System.out.println(false)时,它会显示“ false”。

当我尝试使用System.out.println(Boolean.FALSE == false)时,它会打印“ false”。

请您解释一下?

2 个答案:

答案 0 :(得分:0)

  

当您使用System.out.println(false)时,它会显示“ false”。

此布尔值永远不会自动装箱,因此您通过反射进行的更改不相关。

这是调用堆栈:

thing_ids = []
for thing in Thing.objects.all():
    status = thing.status_set.last()
    if status is not None and status.value == 'bar':
        thing_ids.append(thing.id)

queryset = Thing.objects.filter(id__in=thing_ids)

PrintStream::println(boolean x) PrintStream::print(boolean b) String::valueOf(boolean b) 的实现方式如下:

String.valueOf(boolean)

因此,您已经更改了包装器类使用的常量这一事实没有任何区别。我们从不使用包装器类。

  

当我尝试这个System.out.println(Boolean.FALSE == false)时   打印“假”。

public static String valueOf(boolean b) { return b ? "true" : "false"; } 会自动取消装箱到原始Boolean.FALSE中。 true是错误的。

答案 1 :(得分:0)

没有错误,您重写的Boolean.FALSE用于自动装箱,因为boolean自动装箱是由编译器通过以下主体静默调用Boolean.valueOf()方法实现的:

public static Boolean valueOf(boolean b) {
    return (b ? TRUE : FALSE);
}

在您的示例中,使用boolean类型的Object参数传递给方法,例如System.out.format(String, Object...)将接受自动装箱。他们将受到您的反思性变化的影响,false将成为true

否则,使用boolean原语的方法将不会受到影响,例如System.out.println(boolean)false将停留在false

您的示例中最有趣的两行是:

  • System.out.println(Boolean.FALSE == false)

    编译器通过调用Boolean.FALSE开箱 Boolean.FALSE.booleanValue()由于您的反射而被覆盖 返回true。自true == false起,您得到false。这可以是 通过在Boolean.booleanValue()中放置一个断点来进行确认。

  • System.out.format("%s\n", Boolean.FALSE == false)

    尽管您确实从上面的比较中获得了false,但它会自动装箱到Boolean中以匹配System.out.format(String, Object...)方法签名。由于您的反射覆盖,这将输出true