Skip to content

Variables and Data Types — Primitives, Type Conversion, var, and Default Values

DodaTech Updated 2026-06-28 8 min read

In this tutorial, you will learn about Variables and Data Types. We cover key concepts, practical examples, and best practices to help you master this topic.

Java variables are strongly typed containers for data, with eight primitive types and a unified type system. Unlike dynamically typed languages, every variable in Java has a fixed type determined at compile time — the compiler enforces that you never assign a string to an integer variable, which eliminates entire categories of runtime errors.

What You'll Learn

  • The eight primitive types and their memory sizes
  • Implicit (widening) and explicit (narrowing) type conversion
  • Local variable type inference with var
  • Default values for fields vs local variables

Why It Matters

Understanding the primitive types is essential because Java's performance, memory footprint, and correctness depend on choosing the right type. Using int when byte suffices wastes memory; using float when double is needed loses precision.

Real-World Use

Every program you write will declare variables. Financial applications use BigDecimal for currency, game engines use float for 3D coordinates, and high-performance systems use byte arrays for network buffers.


The Eight Primitive Types

Java has eight primitive types, divided into four categories:

Category Type Size Range / Values
Integer byte 8 bits -128 to 127
Integer short 16 bits -32,768 to 32,767
Integer int 32 bits -2^31 to 2^31-1
Integer long 64 bits -2^63 to 2^63-1
Floating float 32 bits ~ ±3.4e-38 to ±3.4e38, 6-7 decimal digits
Floating double 64 bits ~ ±1.7e-308 to ±1.7e308, 15-16 decimal digits
Character char 16 bits 0 to 65,535 (Unicode UTF-16 code unit)
Boolean boolean JVM-dependent true or false

Integer Types

byte b = 100;          // 8-bit, good for small numbers or raw bytes
short s = 30_000;      // 16-bit, rarely used directly
int i = 2_000_000_000; // 32-bit, the default for whole numbers
long l = 9_000_000_000_000_000_000L; // 64-bit, note the L suffix

Underscores in numeric literals (Java 7+) improve readability and are ignored by the compiler.

The L suffix is required for long literals exceeding int range. Without it, the compiler treats the literal as int and reports an error.

Floating-Point Types

float f = 3.14f;       // 32-bit, note the f suffix
double d = 3.14159265358979; // 64-bit, the default for decimals

Without the f suffix, 3.14 is a double literal and cannot be assigned to a float without a cast. Double is the default for floating-point literals because it provides far greater precision.

The char Type

char c1 = 'A';         // single quotes for characters
char c2 = '\u0041';    // Unicode escape for 'A'
char c3 = 65;          // integer literal, also 'A'

A char is a single 16-bit Unicode character. It is not a string — you must use single quotes. char can also hold values from 0 to 65,535, making it an unsigned integer underneath.

The boolean Type

boolean active = true;
boolean completed = false;

Booleans are not numeric — you cannot write if (1) in Java (unlike C/C++). The JVM does not specify a size for boolean; it often uses an int (4 bytes) in practice.

Type Conversion

Widening (Implicit) Conversion

Java automatically converts smaller primitive types to larger ones when there is no risk of losing information:

byte b = 42;
int i = b;      // byte -> int: OK, implicit
long l = i;     // int -> long: OK, implicit
double d = l;   // long -> double: OK (possible precision loss for very large longs)

The widening order is: byte -> short -> int -> long -> float -> double and char -> int.

Narrowing (Explicit) Conversion

Converting a larger type to a smaller type requires a cast because data can be lost:

long big = 1_000_000_000_000L;
int i = (int) big;         // truncates: i becomes -727,379,968 (overflow)
double pi = 3.14159;
float f = (float) pi;      // loses precision
int ch = (int) 'A';        // char to int: 65

Always check the range before casting. (int) big does not throw an exception — it silently wraps around due to integer overflow.

Type Promotion in Expressions

When evaluating expressions, Java automatically promotes smaller operands:

byte a = 10;
byte b = 20;
int result = a + b;        // a and b are promoted to int before addition

short x = 5;
int y = 2;
double z = x / y;          // int division first: 5/2 = 2, then promoted to 2.0

Any operation on byte, short, or char produces an int. You cannot assign the result back without a cast:

byte a = 10;
byte b = 20;
byte c = a + b;            // COMPILE ERROR: int cannot be converted to byte

The var Keyword (Java 10+)

var allows local variable type inference — the compiler infers the type from the initializer:

var name = "Alice";         // inferred as String
var count = 42;             // inferred as int
var price = 19.99;          // inferred as double
var list = new ArrayList<String>(); // inferred as ArrayList<String>

var is not a dynamic type. The inferred type is fixed at compile time:

var value = "Hello";
value = 42;                 // COMPILE ERROR: String cannot be converted to int

Restrictions:

  • Only valid for local variables (not fields, method parameters, or return types)
  • Requires an explicit initializer — var x; does not compile
  • Cannot be used with null initializer — the compiler cannot infer a type

Default Values

In Java, fields (class-level variables) have default values. Local variables do not.

Type Default Value
byte 0
short 0
int 0
long 0L
float 0.0f
double 0.0d
char '\u0000' (null character)
boolean false
Reference types null
public class Defaults {
    int x;        // default 0
    boolean flag; // default false
    String name;  // default null

    public void show() {
        int y;    // NOT initialized — compile error if used
        // System.out.println(y); // does not compile
    }
}

Common Mistakes

  1. Using int for monetary values. int and double both lose precision for money. Use BigDecimal for currency.
  2. Forgetting the L suffix for long literals. long x = 9999999999; fails because the literal exceeds int range. Write 9999999999L.
  3. Assuming boolean is numeric. if (1) is invalid in Java. Always use explicit boolean conditions.
  4. Believing var makes Java dynamically typed. The type is still fixed at compile time — var is just syntax sugar for writing the type explicitly.
  5. Assuming local variables have defaults. They do not. The compiler forces you to initialize them before use.

Practice Questions

1. What is the difference between float and double?
float is 32 bits with ~7 decimal digits of precision; double is 64 bits with ~15-16 decimal digits. Double is the default for floating-point literals.

2. Why does byte b = 10; byte c = b + b; fail to compile?
The expression b + b promotes both operands to int, producing an int result. Assigning an int to a byte requires a narrowing cast: byte c = (byte) (b + b);.

3. What is the default value of an int field?
0. Fields are automatically initialized; local variables are not.

4. Can var be used for method parameters?
No. var is restricted to local variables with initializers.

5. What range of values can a byte hold?
-128 to 127.

Challenge Question:
Write a program that declares variables of all eight primitive types, assigns them values, and then attempts to assign each to every other type — both with and without casts. Document which conversions compile and which values change. Explain why byte -> int works but int -> byte requires a cast.

FAQ

Why does Java have eight primitive types and not just one 'number' type?

Each type serves a specific purpose: byte for memory-efficient arrays, short for compatibility with older protocols, int for general use, long for large values, float for graphics/GPU, double for scientific computing, char for text, and boolean for logic. Using the right type improves performance and readability.

What happens when an integer overflows?

Java integer arithmetic wraps around silently. For example, Integer.MAX_VALUE + 1 equals Integer.MIN_VALUE. No exception is thrown. Use Math.addExact() (Java 8+) to get an ArithmeticException on overflow.

{{< faq "Is String a primitive type?" "No. String is a class in java.lang. It is not a primitive, but it has special language support — string literals (\"hello\"), concatenation with +, and the string pool for efficient memory management." >}}

What is the difference between `==` and `.equals()` for strings?

== compares references (memory addresses). .equals() compares the character content. For strings created with literals, == often works due to interning, but you should always use .equals() for value comparison.

Can I use `var` with a method return type?

No. var is only for local variables inside methods. Method signatures must declare explicit types.

Mini Project

Write a program DataTypes.java that:

  1. Declares a byte, short, int, long, float, double, char, and boolean
  2. Prints the minimum and maximum values for each numeric type using the MIN_VALUE / MAX_VALUE constants (e.g., Integer.MIN_VALUE)
  3. Demonstrates overflow: add 1 to Integer.MAX_VALUE and print the result
  4. Demonstrates floating-point imprecision: add 0.1 ten times and compare with 1.0
  5. Converts a double to int with a cast and shows the truncated value
  6. Uses var to declare at least three local variables of different inferred types

Run the program and observe the outputs. The overflow and floating-point precision outputs are especially instructive.

What's Next

Now that you understand how to store data, the next lesson shows you how to transform it. Lesson 5 covers operators — arithmetic, relational, logical, bitwise, and assignment operators — along with precedence rules that determine the order of evaluation in complex expressions.

Built by the developers of DodaTech

Doda Browser, DodaZIP & Durga Antivirus Pro