All Posts

June 3, 2025

6 min read
JavaProgrammingFundamentalsData TypesVariablesOperators

Java Fundamentals: A Complete Guide to Data Types, Variables, and Operators

Hey there! πŸ‘‹ Welcome to the first post in my Java Fundamentals series!

I'm revisiting Java to refresh my memory and fill in some gaps in my knowledge. If you're also coming from other programming languages or just need a comprehensive review of Java's core concepts, this guide is for you.

"Java was designed to be easy to use and is therefore easier to write, compile, debug, and learn than other programming languages." β€” James Gosling, Creator of Java

Java is a statically typed language with explicit type declarations that help catch errors at compile time.

Let's dive into the fundamentals! πŸš€


Data Types in Java

Java data types are divided into two main categories: primitive and non-primitive (reference) types.

Primitive Data Types

Java provides eight primitive data types, each with specific memory allocation and use cases:

Numeric Data Types

Integer Types:

  • byte - 8 bits (range: -128 to 127)

    • Example: byte count = 100;
  • short - 16 bits (range: -32,768 to 32,767)

    • Example: short population = 30000;
  • int - 32 bits (range: -2Β³ΒΉ to 2Β³ΒΉ-1)

    • Example: int salary = 100000;
    • Most commonly used integer type in Java
  • long - 64 bits (range: -2⁢³ to 2⁢³-1)

    • Example: long distance = 1000000000L;
    • Double precision (about 15-16 decimal digits)
    • Must use suffix 'L' or 'l' to indicate long type

Floating-Point Types:

  • float - 32 bits (IEEE 754 single precision)

    • Example: float pi = 3.14f;
    • Single precision (about 6-7 decimal digits)
    • Must use suffix 'f' or 'F' to indicate float type
    • ⚠️ Note: If a long is assigned to float, it will be implicitly converted with potential data loss
  • double - 64 bits (IEEE 754 double precision)

    • Example: double precise = 3.1415926535;
    • Default floating-point type in Java (no suffix needed)
    • Double precision (about 15-16 decimal digits)

Character and Boolean Types

  • char - 16 bits (Unicode UTF-16)

    • Example: char grade = 'A';
    • ⚠️ Important: Uses Unicode UTF-16, do not assume ASCII encoding
  • boolean - Conceptually 1 bit (JVM dependent)

    • Example: boolean isActive = true;
    • Can only hold true or false values
    • Actual memory usage is JVM-dependent (can be 1 bit, 8 bits, or 32 bits)

Non-Primitive (Reference) Data Types

Reference types are stored as references/pointers in memory and have a default value of null:

  • String - Sequence of characters
  • Arrays - Collection of elements of the same type
  • Classes - User-defined types
  • Interfaces - Contracts for class implementation
  • Enums - Fixed set of constants
  • Records - Immutable data carriers (added in Java 14)

Default Value Behavior

Default values are automatically applied to instance variables and static variables, but not to local variables. In other words, all class-level variables receive default values automatically.

public class Test {
    static int x;  // default: 0 (static variable)
    int y;         // default: 0 (instance variable)
    
    public static void main(String[] args) {
        int z;  // must be initialized explicitly (local variable)
        // System.out.println(z);  // Compile-time error: variable not initialized
    }
}

Type Casting in Java

Java supports two types of casting:

Implicit Casting (Widening Conversion)

Automatic conversion from smaller to larger data types occurs without data loss:

byte b = 10;
int i = b;    // Implicit widening - no casting required
double d = i; // Implicit widening - no casting required

Widening Conversion Order:

byte β†’ short β†’ int β†’ long β†’ float β†’ double

Explicit Casting (Narrowing Conversion)

Manual conversion from larger to smaller data types may result in data loss:

int i = 300;
byte b = (byte) i;  // ⚠️ Explicit casting required - overflow occurs
System.out.println(b);  // Output: 44 (data loss due to overflow)

double d = 9.99;
int j = (int) d;    // ⚠️ Explicit casting required - decimal part lost
System.out.println(j);  // Output: 9

Special Casting Cases

Numeric Promotion: byte, short, and char are automatically promoted to int during arithmetic operations:

byte b1 = 10;
byte b2 = 20;
int sum = b1 + b2;  // Automatically promoted to int
System.out.println(sum);  // Output: 30

Variables in Java

Types of Variables

1. Local Variables

  • Scope: Declared inside methods, blocks, or constructors
  • Memory: Stored in the stack
  • Lifetime: Exist until method/block/constructor execution completes
  • Initialization: Must be explicitly initialized before use
void method() {
    int localVar;
    // System.out.println(localVar);  // ❌ Compile error: variable not initialized
    
    localVar = 10;  // βœ… Now it can be used
    System.out.println(localVar);  // Output: 10
}

Variable Shadowing: When a local variable has the same name as an instance variable, it shadows the instance variable within its scope:

class Test {
    int x = 10;  // instance variable
    
    void method() {
        int x = 20;  // local variable shadows instance variable
        System.out.println(x);        // Output: 20 (local variable)
        System.out.println(this.x);   // Output: 10 (instance variable)
    }
}

2. Instance Variables

  • Scope: Declared inside a class but outside methods
  • Memory: Stored in the heap
  • Lifetime: Exist as long as the object exists
  • Copies: Each object has its own copy
  • Initialization: Automatically assigned default values
class Car {
    String color;    // default: null
    int speed;       // default: 0
    boolean isNew;   // default: false
}

3. Static Variables (Class Variables)

  • Scope: Declared with the static keyword
  • Memory: Stored in the method area of heap
  • Lifetime: Exist for the entire program execution
  • Sharing: Shared across all instances of the class
  • Ownership: Belong to the class, not to individual instances
class Car {
    static int wheels = 4;  // shared by all Car objects
    String model;           // unique to each Car object
}

// Usage
Car car1 = new Car();
Car car2 = new Car();
System.out.println(Car.wheels);  // Output: 4 (accessed via class name)

Variable Naming Conventions

🧠 Best Practice: Use camelCase for variable names (e.g., myVariable) and PascalCase for class names (e.g., MyClass).

Follow these rules when naming variables in Java:

  • βœ… Must start with a letter, underscore (_), or dollar sign ($)
  • βœ… Can contain letters, digits, underscores, or dollar signs
  • ❌ Cannot start with a digit
  • ❌ Cannot use reserved keywords (int, class, public, etc.)
  • ⚠️ Case-sensitive (myVar and myvar are different variables)

Examples:

// βœ… Valid variable names
int age;
String _name;
double $price;
boolean isValid2;

// ❌ Invalid variable names
// int 2count;     // starts with digit
// String class;   // reserved keyword
// boolean my-var; // contains hyphen

Operators in Java

Operators are special symbols that perform operations on operands (variables and values).

Operator Categories

CategoryPurposeExamples
Arithmetic OperatorsPerform mathematical operations+, -, *, /, %
Relational OperatorsCompare two values==, !=, >, <, >=, <=
Logical OperatorsCombine multiple boolean expressions&&, ||, !
Bitwise OperatorsOperate on individual bits&, |, ^, ~, <<, >>, >>>
Assignment OperatorsAssign values to variables=, +=, -=, *=, /=, %=
Unary OperatorsOperate on a single operand++, --, +, -, !
Ternary OperatorShorthand conditional operator? :
instanceofCheck object type at runtimeobj instanceof ClassName

Practical Examples

Arithmetic Operators:

int a = 10, b = 3;
System.out.println(a + b);  // Addition: 13
System.out.println(a - b);  // Subtraction: 7
System.out.println(a * b);  // Multiplication: 30
System.out.println(a / b);  // Division: 3 (integer division)
System.out.println(a % b);  // Modulus: 1 (remainder)

Logical Operators:

boolean x = true, y = false;
System.out.println(x && y);  // Logical AND: false
System.out.println(x || y);  // Logical OR: true
System.out.println(!x);      // Logical NOT: false

Ternary Operator:

int age = 18;
String status = (age >= 18) ? "Adult" : "Minor";
System.out.println(status);  // Output: "Adult"

Operator Precedence

Precedence LevelOperator TypeOperators
HighestParentheses()
1Unary++, --, +, -, !, ~
2Multiplicative*, /, %
3Additive+, -
4Shift<<, >>, >>>
5Relational<, <=, >, >=, instanceof
6Equality==, !=
7Bitwise AND&
8Bitwise XOR^
9Bitwise OR`
10Logical AND&&
11Logical OR`
12Ternary? :
LowestAssignment=, +=, -=, *=, /=, %=

Precedence in Action

int result = 10 + 5 * 2;  // Multiplication first: 10 + (5 * 2) = 20
int result2 = (10 + 5) * 2;  // Parentheses first: (10 + 5) * 2 = 30

Best Practices and Tips

  1. Always initialize local variables before using them
  2. Use meaningful variable names that describe their purpose
  3. Be aware of data type ranges to prevent overflow
  4. Use parentheses to make operator precedence explicit
  5. Consider memory optimization when choosing between similar data types
  6. Understand the difference between = (assignment) and == (comparison)

Conclusion

Happy coding! πŸ’»