1. Integer class

Integer is also good in that it is a class, which means that it can have fields and methods. And, of course, it has them. A lot of them — dozens of them. Here we'll consider the most basic ones.

The Integer class has two fields that contain the maximum and minimum possible values of the int type:

Field Description
Integer.MAX_VALUE
Maximum possible value of the int type
Integer.MIN_VALUE
Minimum possible value of the int type

Sometimes you want to assign the smallest or largest possible int value to a variable. To avoid cluttering up your code with incomprehensible constants, you can write this very clearly as follows:

Code Description
int min = Integer.MIN_VALUE;
min == 0x80000000

The Integer class also has some interesting methods. Here they are:

Methods Description
String Integer.toHexString(int)
Returns a string that is the hexadecimal representation of the number
String Integer.toBinaryString(int)
Returns a string that is the binary representation of the number
String Integer.toOctalString(int)
Returns a string that is the octal representation of the number
Integer Integer.valueOf(int i)
Wraps the passed int in an Integer object
Integer Integer.parseInt(String)
Returns the number obtained from the passed string

You previously encountered the static Integer.parseInt() method. Let's recall how it works:

int name = Integer.parseInt(string);

If a string containing a number (only digits) is passed to the parseInt() method, it will parse the string and return the number it contains.

The rest of the methods are also useful. For example, some of them can convert a passed number to a string containing the binary, octal or hexadecimal representation of the number.



2. Double class

In general, the Double class is similar to the Integer class, only it wraps a double rather than an int. It also has fields and methods that will be of interest to us. Consider a few of them:

The Double class has six interesting fields:

Field Description
double Double.NEGATIVE_INFINITY
Negative infinity
double Double.POSITIVE_INFINITY
Positive infinity
int Double.MIN_EXPONENT
Minimum possible exponent (2x)
int Double.MAX_EXPONENT
Maximum possible exponent (2x)
double Double.MIN_VALUE
Minimum possible value of the double type
double Double.MAX_VALUE
Maximum possible value of the double type

Infinity

If you divide -1.0 by 0.0, you get negative infinity. If you divide 1.0 by 0.0, you get positive infinity. Not only can you divide a double by zero, but you can also use it store the result of these operations.

Exponent of a double

Understanding the exponent is easy. Internally, a double consists of a mantissa and an exponent. But here the value of the exponent is not 10x, but 2x. Thus, if the exponent increases by 1, the total value of the number will double.

MIN_EXPONENT == -1024, which means 2-1024, which is approximately equal to 10-308

And of course, the Double class has interesting methods:

Methods Description
String Double.toHexString(double)
Returns a string that is the hexadecimal representation of the number
boolean Double.isInfinite(double)
Checks whether the passed number is infinity.
boolean Double.isNaN(double)
Checks whether the passed number is NaN
Double Double.valueOf(double)
Wraps the passed double in a Double object
Double Double.parseDouble(String)
Returns the number obtained from the passed string

Interestingly, there is an isInfinite() method that returns true if the passed number is positive or negative infinity.

The isNaN() method is similar — it checks whether the passed number is NaN (Not-a-Number, a special constant that indicates an undefined value).



3. Character class

The Character class is interesting primarily for its large number of static utility methods that let you check whether characters belong to various categories.

Examples

Methods Description
Character.isAlphabetic(int)
Checks whether a character is an alphabetic character
Character.isLetter(char)
Checks whether the character is a letter
Character.isDigit(char)
Checks whether the character is a digit
Character.isSpaceChar(char)
Checks whether the character is a space, a line break, or a page break (codes: 12, 13, 14)
Character.isWhitespace(char)
Checks whether the character is whitespace: a space, tab, etc.
Character.isLowerCase(char)
Checks whether the character is lowercase
Character.isUpperCase(char)
Checks whether the character is uppercase
Character.toLowerCase(char)
Converts the character to lowercase
Character.toUpperCase(char)
Converts the character to uppercase

A feature of these methods is that they work with all known alphabets: Arabic numerals are classified as digits, etc.



4. Boolean class

The Boolean type is virtually the same as the boolean type. The differences are minimal.

Below we show a simplified version of the Boolean class:

Code Description
class Boolean
{
   public static final Boolean TRUE = new Boolean(true);
   public static final Boolean FALSE = new Boolean(false);

   private final boolean value;

   public Boolean(boolean value)
   {
      this.value = value;
   }

   public boolean booleanValue()
   {
      return value;
   }

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


Constants: TRUE and FALSE


Variable

Boolean class constructor




The method returns the value of the internal variable



This static method converts true to TRUE and false to FALSE.

The Boolean type has two constants (two fields):

Constants of the class Counterpart for the boolean type Description
Boolean.TRUE
true
true
Boolean.FALSE
false
false

You can work with them in the same way that you work with the boolean type:

Code Note
if (Boolean.TRUE)
{
}
The Boolean class is the only class that can be written inside a condition
Boolean a = Boolean.TRUE;
boolean b = Boolean.TRUE;
boolean c = true;
All three variables are equal to true/TRUE
Boolean a = Boolean.TRUE;
Boolean b = Boolean.TRUE;
if (a == b)
Constants can be compared using both equals and ==

This will also work.

Autoboxing works great here. That means you can use this type in the same way as the boolean type — there are no pitfalls to watch out for.

How it is written How it works
Boolean a = true;
Boolean b = true;
Boolean c = false;
boolean d = a;
Boolean a = Boolean.valueOf(true);
Boolean b = Boolean.valueOf(true);
Boolean c = Boolean.valueOf(false);
boolean d = a.booleanValue();

And here a comparison of the boolean and Boolean types:

boolean a = true;
Boolean b = true; // b will be equal to Boolean.TRUE
Boolean c = true; // c will be equal to Boolean.TRUE

a == b; // true (compared by value)
a == c; // true (compared by value)
b == c; // true (compared by reference, but they point to the same object)

If you really need an independent Boolean object, then you need to create it explicitly:

boolean a = true;
Boolean b = new Boolean(true); // New Boolean object
Boolean c = true; // c will be equal to Boolean.TRUE

a == b; // true (compared by value)
a == c; // true (compared by value)
b == c; // false (compared by reference, and they point to different objects)

One more example, where we'll use a Boolean inside of an if:

Code Note
Boolean less = (2 < 3);
if (less)
{
   ...
}
This will compile and work

This will compile, but it won't work!

Code Note
Boolean less = null;
if (less)
{
   ...
}

Error. This line will throw an exception


5. Caching values during autoboxing

There are some pitfalls related to integer wrapper types.

As you already know, if we compare an int and an Integer, the Integer is converted to an int:

How it is written How it works
int a = 5;
Integer b = 5;
if (a == b)
{
   ...
}
int a = 5;
Integer b = Integer.valueOf(5);
if (a == b.intValue())
{
   ...
}

If you compare two Integer objects with each other, they are not converted to ints:

Code Console output
Integer a = 500;
Integer b = 500;
int c = 500;

System.out.println(a == b); // Compared by reference
System.out.println(a == c);
System.out.println(b == c);




false
true
true

a == c and b == c, but a != b, because when we compare a and b we are comparing references. Which is essentially what we would expect.

Surprise

But if we replace 500 with 100, then we get a completely different result:

Code Console output
Integer a = 100;
Integer b = 100;
int c = 100;

System.out.println(a == b); // Compared by reference
System.out.println(a == c);
System.out.println(b == c);




true
true
true

The issue here is that a new Integer object is not always actually created during autoboxing. Objects are cached for values -128 through 127 inclusive.

The Integer class has a hidden array that stores objects: Integer(-128), Integer(-127), ... Integer(126), Integer(127)

If you write Integer x = 128, then the autoboxing process creates a new object, but if you write Integer x = 127, then the autoboxing process retrieves the existing object from the cache (from the array).

If you don't want the Integer object to come from the cache, you will have to create it explicitly by writing: Integer x = new Integer(127);

All wrapper types have such a cache: Integer, Long, Byte, Short, Boolean. For the Boolean type, its TRUE and FALSE values are both constants, so they are also essentially cached.