Select Page

Java Non-primitive Data Types | Developer.com

Robert Gravelle
Published: December 16, 2022

Java Programming tutorials

Java data types can be divided into two distinct categories: primitive and non-primitive. As stated in the Java Primitive Data Types article, primitive data types are the building blocks for the non-primitive data types and store discreet and irreducible values. Examples include byte, short, int, long, float, double, Boolean, and char. Today’s tutorial will
cover non-primitive data types. These are objects that can be created or modified by programmers. For example, all classes in Java are non-primitive data types. Other non-primitive data types are built into the language. These include Arrays and Strings.

You can read about traditional primitive data types in our programming tutorial Java Primitive Data Types.

Primitive versus Non-Primitive Data Types in Java

There are several notable differences between primitive and non-primitive data types in Java. For starters, non-primitive data types are also known as reference types because they refer to objects. As such, variables of non-primitive data types store references to their data, while variables of primitive types contain their data directly. Since each variable has its own copy of the data, it is not possible for operations on one variable to affect the other. Meanwhile, with reference types, two variables can reference the same object; therefore, operations on one variable can affect the object referenced by the other variable.

Other differences between primitive and non-primitive data types include:

  • Primitive types are always predefined, whereas non-primitive types may be created by the programmer.
  • Non-primitive types can define methods, while primitive types cannot.
  • A primitive type always has a value, while non-primitive types can be null.
  • A primitive type starts with a lowercase letter, while non-primitive types start with an uppercase letter, eg, int vs. Integer.
  • The size of a primitive type depends on the data type, while non-primitive types always have the same size.

Non-primitive Data Types in Java

There are five types of non-primitive data types in Java, including the built-in String and Array, custom Classes and Interfaces, as well as the special Object class, which is the superclass of all classes in Java. Hence, every class in Java is a non-primitive data type and Object is a class, which means that it, too, qualifies as a data type.

The String Class in Java

Strings in Java are designed in such a way that they can hold a sequence of characters in a single variable, unlike character arrays where there are separate char entities. There is no need to end strings in Java with the null character, which is compulsory in older languages such as C or C++.

The syntax for String declaration in Java is:

String <string_variable_name> = "<sequence_of_characters>";

OR

String <string_variable_name> = new String("<sequence_of_characters>");

Here is a code example of a class that declares two Strings using each of the above declaration styles, which then prints their values to the console:

public class StringExample {

  public static void main(String[] args) {
    // String declared and initialized in one statement
    String str1 = "I am a String.";
    
    // String declared using the new operator
    String str2 = new String("I am also a String.");
    // Outputs: I am a String. I am also a String.
    System.out.print(str1 + " " + str2);
  }
  
}

The Array Class in Java

Arrays are used to store elements of the same data type in a contiguous sequence. They are not pre-defined, so developers have to declare and initialize arrays before referencing them. Elements are then accessed by their index number, which start from 0. For that reason, arrays in Java are often referred to as being zero-based.

Memory for arrays is dynamically allocated and their size can be set by the programmer upon declaration using an integer value (as opposed to a long or short).

Here is the syntax for Array declaration in Java:

// Array declaration
<data_type>[] <array_name> = new <data_type>[size];
// Declaration and initialization of array in a single line
<data_type> <array_name> [] = {array_item_values};

The following class declares a couple of arrays and and initializes them in different ways before printing their contents to the console:

import java.util.Arrays;

public class ArrayExample {

  public static void main(String[] args)
  {
    // Declaration and initialization
    int arr1[] = { 1, 2, 3, 4, 5 }; 
    
    // Array of size 5 declared
    int[] arr2 = new int[5]; 
    for (int i = 0; i < arr1.length; i++) {
      arr2[i] = i;
    }
    
    System.out.print("Array arr1 elements: ");
    System.out.println(Arrays.toString(arr1));
    
    System.out.print("Array arr2 elements: ");
    System.out.println(Arrays.toString(arr2));
  }
}

Programmers can not print array elements directly in Java, so we need to use the Arrays.toString() utility method to achieve this.

Read: Java Tools to Increase Productivity

Classes in Java

A class in Java is a user-defined data type that acts as a template to the data, which consists of member variables and methods. The concrete implementation of the class is called an instance, which can access the member variables and methods.

In the example below, we have two classes: Abacus and ClassExample. The latter contains the main() method; inside the Abacus class, you will find:

  • The PI constant. It is defined as static so that it can be accessed without instantiating the class.
  • The add() and sub() methods to perform addition and subtraction operations.
  • A default constructor that will be invoked upon creating the Abacus class using the new keyword.

The main() method prints the value of the PI class member variable as well as the results of the add() and sub() methods:

class Abacus { 

  // Class member variable
  public final static double PI = 3.14159265359; 

  // Class default constructor
  Abacus() { 
    System.out.println("Instantiating class...");
  }

  // Class member function
  public void add(int a, int b) { 
    int c = a + b;
    System.out.println("Addition of numbers: " + c);
  }

  // Class member function
  public void sub(int a, int b) { 
    int c = a - b;
    System.out.println("Subtraction of numbers: " + c);
  }
}

public class ClassExample {

  public static void main(String[] args) {
    System.out.println(Abacus.PI); // 3.14159265359
    Abacus abacus = new Abacus(); // Instantiating class...
    abacus.add(10, 20); // Addition of numbers: 30
    abacus.sub(50, 25); // Subtraction of numbers: 25
  }
}

Interfaces in Java

An interface is similar to a class except that its methods are abstract by default, i.e. they do not have body. Since an interface has only the final variables and method declarations, it may also be referred to as a fully abstract class. It acts as a contract, which states that, by implementing the interface, a class must implement all the methods defined by the interface. However, if the class is declared as abstract, it does not have to implement all of the class methods, but its child classes do.

In our last example, we will put the add() and sub() methods in an interface named “AbacusInterface”. That way, if a class wants to be an abacus, it should implement the AbacusInterface methods. That is done by the InterfaceExample class below. This time the main() method is also found in the same class so that it is runnable:

interface AbacusInterface {  
  void add();  
  void sub();  
}  

public class InterfaceExample implements AbacusInterface {  
      
  // Class member variable
  public final static double PI = 3.14159265359; 

  // Class default constructor
  Abacus() { 
    System.out.println("Instantiating class...");
  }

  // add() method implementation
  public void add(int a, int b) { 
    int c = a + b;
    System.out.println("Addition of numbers: " + c);
  }

  // sub() method implementation
  public void sub(int a, int b) { 
    int c = a - b;
    System.out.println("Subtraction of numbers: " + c);
  } 
	
  public static void main(String[] args) {
    System.out.println(Abacus.PI); // 3.14159265359
    Abacus abacus = new Abacus(); // Instantiating class...
    abacus.add(10, 20); // Addition of numbers: 30
    abacus.sub(50, 25); // Subtraction of numbers: 25
  }
}  

Final Thoughts on Java Non-primitive Data Types

This programming tutorial provided an introduction to Java’s non-primitive data types including Objects, Classes, Interfaces, Strings and Arrays. Far more complex than their primitive counterparts, non-primitive types incorporate the four major building blocks of Object-oriented Programming (OOP), namely: Polymorphism, Encapsulation, Abstraction, and Inheritance. We will cover those important topics in later articles.

Read more Java programming tutorials and software development tips.

Source: www.developer.com