DEV Community

Cover image for Java Data Types: A Quick Reference Guide
Marta Kravchuk
Marta Kravchuk

Posted on

Java Data Types: A Quick Reference Guide

This article offers concise technical Java notes, covering primitive and reference types, literals, type conversion rules, and more. Whether you're preparing for an interview or seeking a quick refresher, this guide provides essential insights.


Table of Contents

  1. Primitive Types
  2. Reference Types
  3. Wrapper Classes

Java contains two types of data: primitive types and reference types.

1. Primitive Types

Java has 8 built-in data types, referred to as the Java primitive types. A primitive is not an object in Java and does not represent an object. A primitive is simply a single value in memory, such as a number or a character.

Keyword Type Example Wrapper class
boolean true or false true Boolean
byte 8-bit integral 123 Byte
short 16-bit 123 Short
int 32-bit 123 Integer
long 64-bit 123L Long
float 32-bit floating-point 123.45f Float
double 64-bit floating-point 123.45 Double
char 16-bit Unicode 'a' Character

The data value of a primitive data type is stored in memory and is not a location reference of the data. This makes accessing primitive data types faster and leads to more efficient performance when it really matters.

Each primitive type has a corresponding wrapper class, which is an object type.

Key Differences: short vs. char

The primary difference is that short is signed integer type (can represent both positive and negative values). Alternatively, char is unsigned character type (can represent only positive including 0).

short bird = 'd';           // 'bird' is equal to 100 (the Unicode value of 'd')
char mammal = (short) 83;   // 'mammal' is equal to 'S' (the Unicode character with value 83)
short negative = -100;

Enter fullscreen mode Exit fullscreen mode

Note: If you try to set a value outside the range of short or char, the compiler will report an error.

short reptile = 65535;     // DOES NOT COMPILE
char fish = (short) -1;    // DOES NOT COMPILE
Enter fullscreen mode Exit fullscreen mode

Literals

When a numeric primitive is present in the code, it is called a literal. And you can use underscores in numbers to make them easier to read:

int million1 = 1000000;
int million2 = 1_000_000;
Enter fullscreen mode Exit fullscreen mode

Note: Underscores cannot be placed at the beginning or end of a literal, or immediately before/after a decimal point.

double notAtStart = _1000.00;   // DOES NOT COMPILE
double notAtEnd = 1000.00_;     // DOES NOT COMPILE
double notByDecimal = 1000_.00; // DOES NOT COMPILE

double annoyingButLegal = 1_00_0.0_0; // Ugly, but works
double reallyUgly = 1__________2;     // Also compiles
Enter fullscreen mode Exit fullscreen mode

Declaring Primitive Types

A declaration consists of the data type and variable name(s). A variable name must be a valid identifier. You can identify multiple variables of the same type on a single line, but not multiple variables of different types.

int x, y, z;
int a, double b;     // DOES NOT COMPILE
Enter fullscreen mode Exit fullscreen mode

Declaring float and double

When declaring float or double variables with decimal literals, remember that decimal literals are treated as double by default. To define a float, use the 'f' suffix.

double decimalValue = 3.14;  // Valid double declaration
float floatValue = 3.14f;    // 'f' is required for float
Enter fullscreen mode Exit fullscreen mode

Type Conversion Rules

Java supports both widening (implicit) and narrowing (explicit) conversions between data types. They increase type safety, maintain code clarity, control data loss, and optimize performance.

  • Widening Conversion: occurs when a smaller data type is converted to a larger data type, allowing expanding the range of values without losing information.

Java's primitive types can be converted in the following order:
byte -> short -> int -> long -> float -> double
char -> int -> long -> float -> double

float myFloat = 1000L;
double myDouble = 1000L;
Enter fullscreen mode Exit fullscreen mode
  • Narrowing Conversion: occurs when a larger data type is converted to a smaller data type. This can potentially lead to loss of information or truncation of data and, therefore, requires explicit casting.
char myChar = (char) 1000L;
byte myByte = (byte) 1000L;
short myShort = (short) 1000L;
int myInt = (int) 1000L;
Enter fullscreen mode Exit fullscreen mode

2. Reference Types

A reference type refers to an object (an instance of a class). A value is assigned to a reference in one of two ways:

  • A reference can be assigned to another object of the same or compatible type.
  • A reference can be assigned to a new object using the new keyword.

An object is a specific instance of a class that exists in memory while the program is running. An object is also referred to as an instance of the class. A variable that points to an object is called a reference. To create an instance of a class, you have to write new before the class name and add parentheses after it.

Park p = new Park();
Enter fullscreen mode Exit fullscreen mode

First, you declare the type you’ll create Park and give the variable a name p. This gives Java a place to store a reference to the object. Then you write new Park() to create the object.

Key Differences: Primitives vs. References

There are a few important differences between primitives and reference types.

  • The reference types can be assigned null, which means they do not currently refer to an object. But instead, primitive types will give you a compiler error if you attempt to assign them null.
int value = null;          // DOES NOT COMPILE
String s = null;
Enter fullscreen mode Exit fullscreen mode
  • The reference types can be used to call methods, assuming the reference is not null. And, primitives do not have methods declared on them.
String reference = "hello";
int len = reference.length();
int bad = len.length();     // DOES NOT COMPILE
Enter fullscreen mode Exit fullscreen mode

3. Wrapper Classes

Wrapper classes encapsulate primitive types into objects. They offer methods for converting between primitives and objects.

Common Methods:

parse(): used for converting objects back to primitives.

int number = Integer.parseInt("10");          // String to int
double decimal = Double.parseDouble("3.14");  // String to double
Enter fullscreen mode Exit fullscreen mode

valueOf(): returns an instance of the corresponding wrapper class. If the value is a primitive, it is converted to the appropriate wrapper object.

Integer wrappedInteger = Integer.valueOf(10);
Double wrappedDouble = Double.valueOf("5");
Enter fullscreen mode Exit fullscreen mode

MIN_VALUE and MAX_VALUE: constants representing the smallest and largest possible values of that primitive type.

int min = Integer.MIN_VALUE;  // -2147483648
int max = Integer.MAX_VALUE;  // 2147483647
Enter fullscreen mode Exit fullscreen mode

Autoboxing and Unboxing:

With autoboxing, the compiler automatically converts a primitive to the corresponding wrapper. Unsurprisingly, unboxing is the process in which the compiler automatically converts a wrapper class back to a primitive.

Primitive type Wrapper class Example of initializing
boolean Boolean Boolean.valueOf(true)
byte Byte Byte.valueOf((byte) 1)
short Short Short.valueOf((short) 1)
int Integer Integer.valueOf(1)
long Long Long.valueOf(1)
float Float Float.valueOf((float) 1.0)
double Double Double.valueOf(1.0)
char Character Character.valueOf('c’)
Integer pounds = 120;
Enter fullscreen mode Exit fullscreen mode

This is an example of autoboxing as the int primitive is autoboxed into an Integer object.

Character letter = "robot".charAt(0);
Enter fullscreen mode Exit fullscreen mode

This line demonstrates that autoboxing can involve methods. The charAt() method returns a primitive char. It is then autoboxed into the wrapper object Character.

char r = letter;
Enter fullscreen mode Exit fullscreen mode

Finally, this line shows an example of unboxing. The Character object is unboxed into a primitive char.

Note: There are two tricks in the space of autoboxes and unboxes. The first is related to null values. This harmless-looking code throws exceptions:

var heights = new ArrayList<Integer>();
heights.add(null);
int h = heights.get(0);           // NullPointerException
Enter fullscreen mode Exit fullscreen mode

Adding null to a list is legal, as a null reference can be assigned to any reference variable. However, when attempting to unbox that null to an int primitive, a problem arises. Java tries to get the int value of null, but since any method call on null results in a NullPointerException, that is precisely what occurs. Therefore, caution is advised when dealing with null in relation to autoboxing.

Note: And the second one, be careful using autoboxing with Integer in collections, as it can affect the behavior of methods like remove().

List<Integer> numbers = new ArrayList<Integer>();
numbers.add(1);
numbers.add(Integer.valueOf(3));
numbers.add(Integer.valueOf(5));   // the list 'numbers' contains the elements [1, 3, 5]
numbers.remove(1);
numbers.remove(Integer.valueOf(5));
System.out.println(numbers);       // [1]

Enter fullscreen mode Exit fullscreen mode

The remove() method has two overloaded versions:

  • remove(int index) removes the element at the specified index.
  • remove(Object obj) removes the first occurrence of the object obj from the list.

Since numbers.remove(1) receives an int, Java invokes remove(int index), deleting the element at index 1 (this is a value 3). The list then becomes [1, 5].


Thanks for reading! Hope you found some useful info in this article. Got any questions or ideas? Drop them in the comments below. More cool Java stuff is coming soon!

Top comments (1)

Collapse
 
ganesh_kumar_e4e98249188e profile image
ganesh kumar

Helpful guide on Java data types—clear and concise! For anyone looking to learn more, our Java Course in Coimbatore is a great place to start.

Visit - appincoimbatore.com/java-course-in...