为什么 Java 中的自动装箱允许我为布尔值提供 3 个可能的值?

发布于 2024-09-03 17:32:50 字数 637 浏览 5 评论 0原文

参考: http://java.sun.com/j2se /1.5.0/docs/guide/language/autoboxing.html

“如果你的程序尝试自动拆箱 null,它将抛出 NullPointerException。”

如果您尝试将 null 分配给布尔值,javac 会给您一个编译时错误。有道理。不过,将 null 分配给布尔值是可以的。我想也有道理。

但让我们考虑一下这样一个事实:当尝试自动拆箱 null 时,您将得到一个 NPE。这意味着如果没有空检查或异常处理,您就无法安全地对布尔值执行布尔运算。对整数进行数学运算也是如此。

很长一段时间,我都是java1.5+中自动装箱的粉丝,因为我认为它让java更接近真正的面向对象。但是,昨晚遇到这个问题后,我不得不说我认为这很糟糕。当我尝试使用未初始化的原语进行操作时,编译器给我一个错误是一件好事。如果我丢失了它,我不想使用自动装箱。

我想我可能误解了自动装箱的意义,但同时我永远不会接受布尔值应该能够有 3 个值。谁能解释一下吗?我没有得到什么?

Reference: http://java.sun.com/j2se/1.5.0/docs/guide/language/autoboxing.html

"If your program tries to autounbox null, it will throw a NullPointerException."

javac will give you a compile-time error if you try to assign null to a boolean. makes sense. assigning null to a Boolean is a-ok though. also makes sense, i guess.

but let's think about the fact that you'll get a NPE when trying to autounbox null. what this means is that you can't safely perform boolean operations on Booleans without null-checking or exception handling. same goes for doing math operations on an Integer.

for a long time, i was a fan of autoboxing in java1.5+ because I thought it got java closer to be truly object-oriented. but, after running into this problem last night, i gotta say that i think this sucks. the compiler giving me an error when I'm trying to do stuff with an uninitialized primitive is a good thing. I dont want to use autoboxing if I lose that.

I think I may be misunderstanding the point of autoboxing, but at the same time I will never accept that a boolean should be able to have 3 values. can anyone explain this? what am i not getting?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(9

阳光的暖冬 2024-09-10 17:32:50

装箱类型是引用类型,所有引用类型,无论是否是原始盒子,都可以引用 null。这就是为什么 Boolean 可以引用 null整数也可以。 String 等也可以。

装箱类型并不是为了使 Java 真正面向对象而设计的。 Java永远不会成为一种纯粹的面向对象语言,并且您不应该像这样编写代码。原始类型永远不会消失,事实上,只要有选择,就应该优先选择。

以下是《Effective Java 第二版》第 49 条的引述:优先使用原始类型而不是盒装原始数据(作者强调):

总之,只要有选择,就优先使用基元而不是盒装基元。原始类型更简单、更快。如果您必须使用盒装原语,请小心! 自动装箱减少了使用装箱基元的冗长性,但没有减少危险。当您的程序使用 == 运算符比较两个装箱基元时,它会进行身份比较,这几乎肯定不是您想要的。当您的程序执行涉及装箱和拆箱基元的混合类型计算时,它会进行拆箱,并且当您的程序进行拆箱时,它可能会抛出NullPointerException。最后,当您的程序装箱原始值时,可能会导致昂贵且不必要的对象创建。

Boxed types are reference types, and all reference types, primitive boxes or not, can refer to null. That's why a Boolean can refer to null. So can an Integer. So can a String, etc.

Boxed types are not designed to make Java truly object oriented. Java will never be a purely object oriented language, and you should not code as if this is the case. Primitive types will never go away, and in fact should be preferred whenever there's a choice.

Here's a quote from Effective Java 2nd Edition, Item 49: Prefer primitive types to boxed primitives (emphasis by author):

In summary, use primitives in preference to boxed primitive whenever you have the choice. Primitive types are simpler and faster. If you must use boxed primitives, be careful! Autoboxing reduces the verbosity, but not the danger, of using boxed primitives. When your program compares two boxed primitives with the == operator, it does an identity comparison, which is almost certainly not what you want. When your program does mixed-type computations involving boxed and unboxed primitives, it does unboxing, and when your program does unboxing, it can throw NullPointerException. Finally, when your program boxes primitive values, it can result in costly and unnecessary object creations.

葬心 2024-09-10 17:32:50

我至少见过一种 null 值很有用的情况。 Web 服务中的许多数据对象都有可为空的布尔字段。有时用户会忽略包含值。在这种情况下,您希望能够从默认值中辨别出缺少值。以前,人们会编写 getXsetXisXSet() 方法,其中 isXSet 返回 false,直到有人调用setX。现在可以使 X 成为可空类型,并且很明显,如果 getX 返回 null 则不会设置它。

I've seen at least one case where the null value is useful. Lots of data objects in webservices have nullable boolean fields. Sometimes the user neglects to include a value. In this case you want to be able to discern the lack of a value from a default value. Previously, people would write getX, setX, and isXSet() methods, where isXSet returns false until someone calls setX. Now it's possible to make X be a nullable type and it's clear that it wasn't set if getX returns null.

メ斷腸人バ 2024-09-10 17:32:50

除了这里所说的一切之外,在某些情况下,您非常希望布尔值具有第三个值 - “可选”属性的情况。

我们通常会在数据库中遇到这种情况,其中的布尔列允许空值。如果不使用布尔值,我们将需要使用两个单独的变量,一个指示值,另一个指示值是否有效。

事实上,如果您查看 JDBC API,您可以看到此问题的一个示例,其中如果列为 null(例如,数字字段为 0),则它们将获得默认值,然后您必须调用“wasNull”来检查它是真 0 还是假 null!

In addition to everything said here, there are cases where you would very much want to have a third value for booleans - the case of an "optional" property.

We usually encounter it with databases, with boolean columns that allow nulls. Without using Booleans, we would need to use two separate variables, one indicating the value and another whether it is valid.

In fact, if you look at the JDBC API, you can see an example of this problem, where columns get a default value if they are null (e.g., a 0 for numeric fields), and then you have to call "wasNull" to check whether it is a true 0 or a fake null!

硪扪都還晓 2024-09-10 17:32:50

您的问题是自动装箱,而不是自动装箱。我认为自动拆箱是邪恶的,有更重要的原因:

考虑一下:

Integer i = new Integer(1);
Integer i2 = new Integer(12);

System.out.println(i == 10 || i != i2);

一个 == 拆箱,而另一个则不拆箱。

在我看来,对运算符进行拆箱(而不是赋值)是一个错误(鉴于上述情况 - 它不是 Java)。然而,拳击是非常好的。

Your issue is with autounboxing, not autoboxing. I think autounboxing is evil for more significant reasons:

Consider this:

Integer i = new Integer(1);
Integer i2 = new Integer(12);

System.out.println(i == 10 || i != i2);

One == unboxes and the other doesn't.

Unboxing on operators (as opposed to assignments) was a mistake in my view (given the above - it is just not Java). Boxing, however, is very nice.

今天小雨转甜 2024-09-10 17:32:50

我认为这更多的是哲学问题而不是技术问题。当您将基本类型转换为引用类型时,您应该准备好引用类型(即对象)可以为空。

您可以观看十亿美元的错误 CAR Hoare 的演讲中表示,他引入 oop (Algol 60) 的空引用是一个错误。

Josh Bloch 在《Effective Java》中建议尽可能选择原始类型。但有时您确实必须验证布尔变量是否为 null。

I think it's more philosophical than technical question. When you transform primitive type to reference type you should be ready that reference types (i.e. objects) are nullable.

You can watch The Billion Dollars Mistake presentation where C.A.R. Hoare says that his introducing null references to oop (Algol 60) was a mistake.

Josh Bloch in Effective Java recommends to prefer primitive types where it's possible. But sometimes you do have to verify you Boolean variable against null.

七秒鱼° 2024-09-10 17:32:50

实际上与 Java 1.5 之前的日子没有太大区别 - 问题不是布尔类型(它仍然有两个状态)而是布尔包装器(总是有 3 个状态:Boolean.TRUE、Boolean.FALSE 和 null)。

从布尔对象到布尔原语的每次转换都需要空检查,无论是否带有自动装箱。

There is actually no big difference to the days before Java 1.5 - the problem is not the boolean type (it still has two states) but the Boolean wrapper (which always had 3 states. Boolean.TRUE, Boolean.FALSE and null).

Every conversion from a Boolean object to the boolean primitive requires null checks, with or without autoboxing.

朮生 2024-09-10 17:32:50

自动装箱会自动在内部类型和对象类型之间转换数据类型。

Boolean 的对象类型可以是 Boolean.TRUEBoolean.FALSEnull。这就是为什么您必须处理布尔值可能的 3 个值。

在数据库中,布尔类型通常具有三种状态。考虑一个跟踪某人是否通过课程的记录。 TRUE 表示通过; FALSE 表示未通过,NULL 表示“当前正在上课”。是的,这很奇怪,但在面向对象编程中没有值是继承的。

我也觉得自动装箱有点令人反感,主要是因为它是编译器添加字节码来处理转换过程的功能。在我看来,这可能会导致人们忘记转换过程中的重要细节,而这些细节可能会更好地记住(例如您案例中的空处理)。它很有用,但不如 Java 语言的大多数其他功能有用。

就我个人而言,我希望将内在函数实现为轻量级对象而不是“内置”类型。很多时候混合内在/对象类型系统会产生阻碍。也就是说,内部函数应该是为了提高性能,但似乎如果您必须对对象编组执行大量内部函数,则您无法享受仅内部函数的性能提升。

Autoboxing automatically transforms data types between intrinsic types and Object types.

Object types for Boolean can be Boolean.TRUE, Boolean.FALSE, or null. That's why you have to deal with the possible 3 values for a boolean.

In databases, it is common to have three states for a boolean type. Consider a record that tracks whether someone has passed a class. There's TRUE, for passing; FALSE for not passing, and NULL for "currently taking the class". Yes, it's odd, but not having a value is inherit in object oriented programming.

I too find autoboxing a bit distasteful, mainly because it is a feature where the compiler adds bytecode to handle the conversion process. In my opinion, this can lead to people forgetting about important details in the conversion process which might be better remembered (such as the null handling in your case). It is useful, but not nearly as useful as most other features of the Java language.

Personally, I wish that the intrinsics were implemented as lightweight objects instead of "built-in" types. There's a lot of times where the hybrid intrinsic / object type system gets in the way. That said, intrinsics were supposed to be there to improve performance, but it seems that if you must do a lot of intrinsic to Object marshalling, you can't enjoy the intrinsic-only performance boost.

空城仅有旧梦在 2024-09-10 17:32:50

这是自动装箱的问题,就像Integer i = null;一样。 Integer 对象可以为 null,而本机 int 则不能。

It is the problem with autoboxing, just like Integer i = null;. Integer object can be null while a native int cannot be.

感情旳空白 2024-09-10 17:32:50

随着自动装箱的引入,它从来没有打算取代原语。在大多数地方,基元就是您想要的。如果您想开始使用引用类型,因为“它让 java 更接近真正的面向对象”,那么这就是您的选择,但正如您所发现的,这种方法存在缺点。性能将是另一个问题。

自动装箱(和自动拆箱)有助于在使用原语(大多数)的代码和必须使用引用类型(很少)的代码之间进行转换。在引用类型中,布尔类型无疑是最稀有的,因为它的实例数量很少意味着它几乎不值得放入集合中。

总之:如果引用类型给您带来麻烦,请不要使用它们。但不要仅仅因为它们对您的情况没有帮助就说“自动装箱不好”。

It was never intended, with the introduction of autoboxing, that it replace the primitives. In most places primitives are what you want. If you want to start using the reference types because "it got java closer to be truly object-oriented" then that's your call, but as you are discovering, there are disadvantages with that approach. Performance will be another issue.

Autoboxing (and autounboxing) is there to help with the transitions between code that uses primitives (the majority) and the code that has to use reference types (rare). Of the reference types, Boolean is undoubtedly the rarest, since its small number of instances mean it's almost never worth putting in a Collection.

In summary: if the reference types are causing you trouble, don't use them. But don't say 'autoboxing is bad" just because they turned out not to be helpful in your situation.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文