Thursday, August 7, 2014

Java's Primitive Data Types

There are eight primitive date types in Java which can be grouped into three separate categories:
  • Integer Types
    • byte
    • short
    • int
    • long
  • Floating Point Types
    • float
    • double
  • Other
    • boolean
    • char
They're called primitive types because they hold basic values like 27 or true. This blog post is primarily going to be focused on the numeric types.
Integer Types
byte
It only takes 8 bits of memory to store a byte. Since each bit can store one of two values, either a 1 or a 0, that means a byte has the capacity to store up to 256 different values.
2^8 = 256
That does not mean, however, that 256 is the maximum value that a byte can hold. Java uses a technique known as two's complement to allow bytes to store both positive and negative numbers.

Suppose you wanted to store -37. The way two's complement works is you take the binary representation of the absolute value of the number...
|-37| = 37 = 0b0010 0101
Flip all the bits so that 1s becomes 0s and 0s becomes 1s.
0b0010 0101 => 0b1101 1010
Add one to the result and truncate if necessary.
0b1101 1010 => 0b1101 1011
Note: 0b1101 1011 actually represents the value 219. The numbers 37 and 219 add up to 256. They "complement" each other.
System.out.println(Byte.MIN_VALUE); // -128
System.out.println(Byte.MAX_VALUE); // 127
Because Java uses two's complement, anything above 127 is going to be interpreted as a negative number.
byte max = (byte)(Byte.MAX_VALUE + 1);
System.out.println(max);  // -128
To see why this is consider that 128 is half of 256. (256 / 2 = 128) So there's 128 positive numbers and 128 negative numbers. The reason 127 is the maximum is because 0 is included in the range of positives.
127 positive numbers + 1 for zero = 128 numbers
Since 128 can't be positive then it must be negative. Past -128 the represented numbers get progressively closer and closer to -1. This time let's consider the twos complement of 127.

127 => 0b0111 1111 convert to binary
0b1000 0000 flip all the bits
0b1000 0001 add 1 to the result

Note: 0b1000 0001 is actually the value of 129.  256 - 127 = 129

127 = 0b0111 1111
-128 = 0b1000 0000
-127 = 0b1000 0001

Here's an example declaration of a byte variable.
byte me = 27;
Note: All the numeric types in Java are signed which means they can store both positive and negative numbers.
short
The next largest integer type is short. It is 16 bits in size.

Here's an example declaration of a short variable:
short stuff = 27;
You have to be careful when working with bytes or shorts. Java has a tendency to promote them to int.
byte max = Byte.MAX_VALUE;
System.out.println(max + 1); // outputs 128, not -128
You'll have to use a cast if you want to store the value back into a byte or short.
byte max = Byte.MAX_VALUE;
max = (byte)(max + 1);
System.out.println(max);  // -128
int
All ints take up 32 bits of space.

Here's an example declaration of an int variable:
int out;
long
Here's an example declaration of a long variable. It is 64-bits in size:
long john = 27;
Sometimes you'll see the letter L - it can be either uppercase or lowercase, although uppercase is recommended – appended to the end of a number. What this does is promote that integer value to a long.
int out  = 27L; // compiler error: incompatible types, found long required int
Floating Point Types
The floating point types, float and double, are meant for working with decimals. The float is 32-bits in size and the double is 64. Here's how you'd declare both types of variables
float rootBeer = 27;
double trouble = 27;
Similar to how bytes and shorts are promoted to ints, numbers with decimals are automatically promoted to double.
int out = 27.0; // compiler error: incompatible types, found double required int
And just like with longs, sometimes you'll see developers append either the letter F or D to the end of the number. This signifies the data type to use for the number. F for float and D for double.
float rootBeer1 = 27.0;  // compiler error: incompatible types, found double required float
float rootBeer2 = 27.0F; // okay
You can even convert numbers to scientific notation and store them in a floating point variable.
double trouble = 1.234E3;
System.out.println(trouble); // 1234.0
Other
Default Values
Default values are only assigned to class fields, not local variables
public class Klass {

   private int klassField;

   public Klass() {
      System.out.println("klassField = " + klassField); // klassField = 0

      int localVariable;
      System.out.println("localVariable = " + localVariable); // compiler error
         // localVariable might not have been initialized 
   }

   public static void main(String[] args) {
      new Klass();
   }
}
The following table was taken from The Java Tutorials : Primitive Data Types:

Primitive Type Default Value
byte 0
short 0
int 0
long 0L
float 0.0f
double 0.0d
char '\u0000'
boolean false

Using a Different Numbering System
Prefixing a 0 to a number indicates an octal number.
byte bad = 08; // compiler error: Integer number too large
byte good = 07;
A 0b prefix indicates a binary.
byte me = (byte)0b10000000;
System.out.println(me); // -128
A 0x prefix indicates a hexadecimal.
byte me = 0xF;
System.out.println(me); // 15
Grouping Digits
A new feature that was added into Java 7 is the ability to add underscore characters in a numerical literal. You can add as many underscores as you want, but there are a few rules on where they may be placed.

You can't start or end a numerical literal with an underscore.
int a = _1; // cannot resolve symbol
int b = 1_; // illegal underscore
You can't put an underscore before or after a decimal.
float a 1_.2; // illegal underscore
float b 1._2; // illegal underscore
You can't put an underscore before an F, L, or D suffix.
long john = 123_L;      // illegal underscore 
float rootBeer = 1.2_F; // illegal underscore 
double trouble = 1.2_D; // illegal underscore
You can't put an underscore between the 0 and b prefix, which indicates a binary number;
byte me = (byte)0_b10000000; // illegal underscore
Likewise, you can't put an underscore between the 0 and x prefix, which indicates a hexadecimal number.
byte me = 0_xF;
You also can't put an underscore after the 0b or 0x prefix.
byte mark = (byte)0b_10000000; // illegal underscore
byte me = 0x_F; // illegal underscore
You can, however, follow an underscore with another underscore. You can follow it with as many underscores as you want in fact.
int out = 1_2__3___4____5;
Autoboxing and Unboxing
Autoboxing occurs when Java converts a primitive into its corresponding object wrapper class.
Boolean cube = true;
Unboxing occur when Java converts the object wrapper into a primitive.
boolean cube = new Boolean(true);
References

No comments:

Post a Comment