There are two kinds of data types: primitive and object.

primitive data types

The primitive types contain only a single immutable value, and do not have any properties or methods. There are eight primitive data types: byte, short, int, long, float, double, char, boolean.

Primitive types are passed by value, i.e the value will be copied from the source to the destination. If the source is changed, the destination variable will not change.

object data types

Everything non-primitive are objects. Objects represent complex data with properties and methods.

Unlike C ++, the Java classes themselves are objects of type Class and are stored in memory. They contain information for creating an instance of the class and static data that is shared by all instances.

An instance of the class is stored in a special part of memory called the heap. When no references to the instance, it will be removed from memory by garbage collector.

Creating many temporary objects can degrade performance. Of this reason JVM cache some String values and Integer values in the range [-127; 127].
For example, one of the beginners' mistakes is using the + or + = operators with strings inside the loop. These operators hiddenly use the StringBuilder object. So at each iteration a StringBuilder instance will be created.

String src="abc...x";
int len = src.length();
String dst="";
StringBuilder sb = new StringBuilder();

for (int i=0; i < len; ++i){
  // dst+=src.charAt(i);

dst= sb.toString();

Object types are passed by reference, i.e variable stores "address" of object, not object itself. Thus:

  • when you compare two object variables by == operator, you are compare adresses. If you want compare objects, you must use method equals.
  • when two variables refer to the same object and the object changes, the change will be visible in both variables.
HashMap<String, Integer> map1 = new HashMap<>();
map1.put("one", 1);

HashMap<String, Integer> map2 = new HashMap<>();
map2.put("one", 1);

HashMap<String, Integer> map3 = map1;

System.out.println("map1==map2 is "+(map1==map2)); // false
System.out.println("map1==map3 is "+(map1==map3)); // true
System.out.println("map1.equals(map2) is "+(map1.equals(map2))); // true
// usually true, but may be false
// (for example, got this on samsung mobile device)
System.out.println("b".equals("b")); // always true

The instanceof operator compares an object to a specified type.

boolean a = "" instanceof String;
boolean b = String.class.isInstance("");

autoboxing and unboxing

Each primitive type has a corresponding object wrapper class:

  • byte - Byte
  • short - Short
  • int - Integer
  • long - Long
  • float - Float
  • double - Double
  • boolean - Boolean

Autoboxing is the automatic conversion that the Java compiler makes between the primitive types and their corresponding object wrapper classes. For example, converting an int to an Integer, a double to a Double, and so on. If the conversion goes the other way, this is called unboxing.