Tag Archives: Integer

Numeric literals in Java 7 and in C#

In both Java and C# it’s quite easy to express integer numerical literals. You can use both decimal and hexadecimal base to represent the value. Only for the hexadecimal base you need to prefix the value with 0x. For decimal base values that exceed 2^31-1 you need to provide a suffix (typically L) specifying this fact so the compiler will treat it like a long integer value. C# also provides unsigned long values (U prefix). In both languages the casing of the suffix does not matter.

Java : (notice, there are no unsigned primitives in Java)

int i1 = 23; // integer, decimal
int h1 = 0x17; // integer, hexadecimal
long i2 = 12345678900L; // long integer (64 bit signed integer)

C# :

int i1 = 23;
int h1 = 0x17;
ulong u1 = 12345678900U;
long i2 = 12345678900L;

As you might have read in Beginning Java for .NET developers on slide 14, beginning in Java 7 you can also use two more features, that are not present in C# (at least at the time of this writing) :

Binary base :

int b1 = 0b11001010;

Underscores in literals (no matter which base) :

int b1 = 0b1100_1010;
long myCardNumber = 2315_2432_2111_1110;
int thousandsSeparated = 123_456_000;

The restrictions on the underscore placing is that you may not place it at the beginning of the value (prefix) or at the end (suffix). Also, for non-integer literals, you may not place it adjacent to the decimal separator.

For floating-point literals you must use the dot as decimal separator (if you need to specify a fraction, if not, you’re not required). You must use F for float-single-precision (32 bit) and D for float-double-precision (64 bit). Moreover in C# you have also the M suffix corresponding to the decimal (128 bit) value type.

C# :

float x1 = 0.001F;
double x2 = 12.33D;
decimal x3 = 111.2M;
float x4 = 33F;

Java :

float f1 = 0.001F;
double f2 = 12.31D;
float f3 = 123F;

Beware of primitive wrappers in Java

A .NET developer can be tricked into thinking that, for example, Integer is the same with int in Java. This is dangerous, in particular for a C# developer, because in C# System.Int32 is absolutely equivalent to int. “int” is just an alias.

In Java there are 8 primitive data types :

  • byte (this is equivalent to sbyte in C#)
  • short (just like short / Int16 in C#)
  • int (just like int / Int32 in C#)
  • long (equivalent to long / Int64)
  • float (similar to float / Single)
  • double (similar to double / Double)
  • boolean (equivalent to bool / Boolean)
  • char (equivalent to char / Char)

Now, these primitive types are not part of the Java Type System, as you might have seen in Beginning Java for .NET developers in the slides, at page 21. These primitives (“value types”) have reference-type peers that are typically spelled the same (except int/Integer, char/Character) and just have the first letter capitalized.

Just like you should avoid comparing strings with == in Java, you should avoid declaring variables and fields of the reference-type peers, unless for a good reason.
The main danger lies in the fact that being reference types and Java not having operator overloading (see Beginning Java for .NET developers, slide 15) comparing two instances with the == operator will compare the instances and not the values.

“Oh, but you’re wrong!”, some of you might say, “I’ve written code like this and it worked!”. Code like this :

public class Main {

    public static void main(String[] args) {
        Integer i1 = 23;
        Integer i2 = 23;

        System.out.println("i1 == i2 -> " + (i1 == i2));
    }
}

Yes, it does print

i1 == i2 -> true

It will work to values up to 127 inclusive. Just replace 23 with 128 (or higher) and see how things go. I’ll wait here.
Surprised? You shouldn’t be. This thing works because of a reason called integer caching (and there are ways to extend the interval on which it works – by default -128 up to 127 inclusive) but you shouldn’t rely on it.

Just use int where available or at least use the .intValue() method.

You might wonder what is the Integer (and the rest of the reference-type wrappers) there for? For a few things where they are needed. Once, because the generics in Java are lacking and you can’t define a generic type with primitive type(s) as type arguments. That’s right, you can’t have List. Scary? Yes, especially when coming from .NET where generics are not implemented with type erasure. So you need to say List and then watch out for reference comparison instead of value comparison, autoboxing performance loss and so on.

The other reason why you need these wrappers is because there is no nullable-types support in Java. So if you need to have a variable or a field that can store a primitive type but might also have to store a null then Integer will be better for you than int.

Just make sure you understand these implications and … be (type :P) safe!