简体   繁体   中英

Why do Java and C# not have implicit conversions to boolean?

Since I started Java it's been very aggravating for me that it doesn't support implicit conversions from numeric types to booleans, so you can't do things like:

if (flags & 0x80) { ... }

instead you have to go through this lunacy:

if ((flags & 0x80) != 0) { ... }

It's the same with null and objects. Every other C-like language I know including JavaScript allows it, so I thought Java was just moronic, but I've just discovered that C# is the same (at least for numbers, don't know about null/objects): http://msdn.microsoft.com/en-us/library/c8f5xwh7(VS.71).aspx

Microsoft changed it on purpose from C++, so why? Clearly I'm missing something. Why change (what I thought was) the most natural thing in the world to make it longer to type? What on Earth is wrong with it?

For clarity. It makes the following mistake simply illegal:

int x = ...;

if (x = 0)  // in C: assign 0 to x and always evaluate to false 
   ....     // never executed

Note: most modern C / C++ compilers will give a Warning (but not an Error) on this straightforward pattern, but there are many variations possible. It can creep up on you.

Both Java and C# abandoned implicit conversions to booleans to reduce the chance of programmer error .

For example, many programmers would accidentally write:

if( x = 5 ) { ... }

instead of:

if( x == 5 ) { ... }

Which of course results in completely different behavior, since the first statement performs an assignment (which will always result in true), while the second performs a comparison. In the past, developers would sometimes write such assignments in reverse to avoid the pitfall, since:

if( 5 = x ) { ... } // doesn't compile.

Now, in C#, you can still create implicit conversion operators to bool for your own types - although it is rarely advisable, since most developers don't expect it:

public class MyValue
{
   public int Value { get; set; }

   public static implicit operator bool( MyValue mb )
   {
       return mb.Value != 0;
   }
}

MyValue x = new MyValue() { Value = 10; }
if( x ) { ... } // perfectly legal, compiler applies implicit conversion

也许他们认为更加明确更符合强类型语言。

You've got it backward.
It's actually C that does not support boolean , so if ( and any other conditional statement ) actually expects an int value, not boolean . Then int value of 0 is treated as false and any other value is treated as true .

Some people actually find it a little ambiguous, because this type of behavior can lead to many errors, as others have pointed out. Because of this, Java designers have opted out to support only boolean types in the condition statements. And when Microsoft decided to implement MS-Java ( AKA C# ), they've borrowed this design principal.

If you don't like it, you can program in a variety of languages that do not have this restriction.

Implicit conversion of any int value (such as (flags & 0x80)) to a boolean implies a language defined mapping from an int value to a boolean. C did this, and caused a huge amount of confusion and a lot of programmer error. There is no good reason why a zero int value ALWAYS means true (or false) and a lot of good reasons why you might want to leave the decision to the programmer. For these reasons implicit conversion to boolean has been abandoned by most modern languages.

If typing seven extra characters every time you do a bit test constitutes 'lunacy' you may be in the wrong profession. If you are doing bit tests in an int extremely frequently you might want to think about whether you are prematurely optimizing to save memory.

Even the most experienced programmers have problems with an implicit conversion to boolean. I for one appreciate this little feature.

Some programming languages do no automatic coercion at all. An integer, for example, can only be compared to another integer; assignment to a non-integer variable results in an error. Such is the hallmark of a strongly-typed language.

That Java does any coercion is a convenience for you and breaks the strong-typing model.

Mapping the entire range of integers -- or the even larger range of floats -- onto the two boolean values is fraught with disagreement over arbitrary assignment of "truthness" and "falseness".

  • What values map onto false and true? If you're C, only zero maps to false and all other values are true. If you're the bash shell, it's reversed.
  • How should negative values be mapped?

When you try to automatically convert a double to an integer, Java flags this as a "loss of precision" error. By analogy, converting a number to a boolean should also result in a loss of precision. Instead, Java chose to not syntactically support it.

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