Java basics come down to four ideas: variables store data, data types decide what kind of data, objects bundle data with behaviour, and loops repeat work. This page covers each one with examples from automation code. Writing your very first program? Start with Hello World in Java, and for all eight value types see Primitive Data Types in Java.

What Kinds of Variables Can a Class Have?

A class in Java can consist primarily of three types of variables: instance variables, static (class) variables, and local variables.

Instance variables store object-specific data, static variables store common data shared by all objects, and local variables exist only inside methods.

Instance Variables

Declared inside the class but outside methods.

Each object gets its own copy.

Used when object-specific data is required (e.g., each user object has its own username and password).

Static (Class) Variables

Declared with the static keyword, shared across all objects, with memory allocated only once (e.g., a common wait time, environment URL, or driver path).

Local Variables

Declared inside methods or constructors, existing only during method execution.

They have no default values and must be initialized before use (e.g., temporary counters, flags, or dynamic data inside methods).

Real-life example

Think of a BankAccount template. Each account has a different balance (instance variable), all accounts belong to the same bank name (static variable), and any temporary value you calculate inside a method, like interest for this month, is a local variable.

Real-time testing example

In a Selenium Page Object class, web elements declared with @FindBy are instance variables, a global timeout defined once is a static variable, and a temporary variable used only inside a test method is a local variable.

Project example (STAR)

Situation: In my framework, we had to design reusable Page Objects.

Task: Define variables so objects remain independent while certain values stay common.

Action: I used instance variables for element locators, static variables for constants such as wait time and the base URL, and local variables for temporary values within methods.

Result: The Page Object classes became more readable, memory-efficient, and easy to maintain across the automation suite.

Quick summary

Instance = per object, Static = shared, Local = method-level.

These are used heavily in frameworks (instance for elements, static for constants, local for temporary data), helping maintain a clean, optimized, and scalable Java + Selenium architecture.


Advertisement

What is a Singleton Class?

A Singleton class is a design pattern in which only one object of the class is allowed to be created during the entire execution of the application. It provides a single shared instance accessible globally.

Key points

  • The constructor is private, so nobody can create objects from outside.
  • The class holds a static reference to itself.
  • A public static method (usually getInstance()) returns the single instance.

Why it's useful in frameworks

  • Ensures one WebDriver instance per test run, preventing multiple browsers from opening.
  • Maintains a single configuration manager, logging utility, or database connection across the project.
  • Helps maintain consistent test execution while reducing memory usage.

Real-life example

Think of a country's Prime Minister—there can be only one at a time, and everyone refers to the same authority. That is exactly how a Singleton object works.

Real-time testing example

In Selenium frameworks, the WebDriver Manager or DriverFactory is often implemented as a Singleton so the same browser driver instance is reused across tests, avoiding "Session not created" errors or multiple browser conflicts.

Project example (STAR)

Situation: While building a hybrid Selenium framework, multiple browser instances were opening accidentally.

Task: Ensure the framework uses only one WebDriver instance throughout the run.

Action: I implemented WebDriver initialization inside a Singleton DriverManager class with a private constructor and a public getInstance() method.

Result: Browser conflicts were resolved, execution stabilized, and the framework became easier to maintain.

Important for parallel runs: a classic Singleton gives the whole program one WebDriver, so tests running in parallel would share — and close — the same browser. Frameworks that run in parallel keep the Singleton idea for the factory but store one driver per thread:

public final class DriverManager {
    private static final ThreadLocal<WebDriver> DRIVER = new ThreadLocal<>();
    private DriverManager() { }                                   // no instances

    public static WebDriver get() {
        if (DRIVER.get() == null) DRIVER.set(new ChromeDriver());  // one browser per test thread
        return DRIVER.get();
    }
    public static void quit() {
        if (DRIVER.get() != null) { DRIVER.get().quit(); DRIVER.remove(); }
    }
}

In interviews, mention both: Singleton for shared, read-only things like configuration, and ThreadLocal for the driver. See Parallel Execution & Grid.


The Three Steps for Creating an Object

An object is created from a class using the new keyword in three steps:

Declaration

A variable declaration with a variable name and an object type (declare a reference variable).

Instantiation

The new keyword is used to create the object.

Initialization

The new keyword is followed by a call to a constructor, which initializes the new object by connecting the reference to the object.

Real-life example

Think of booking a cab.

You create a contact name (reference), the cab company assigns a driver and car (object creation), and the driver is linked to your booking (assignment).

Real-time testing example

In Selenium, declare a WebDriver reference (WebDriver driver;), create the object (new ChromeDriver();), and assign it (driver = new ChromeDriver();).


When is the byte Datatype Used?

The byte data type is a primitive, 8-bit signed integer with a value range of −128 to 127 (default value is 0).

It is mainly used to save memory in large arrays where memory savings matter most and can also be used in place of int when the value range is small.

When to use byte

  • Memory efficiency — For large datasets (millions of values), using byte instead of int saves significant memory.
  • Binary or raw data — Low-level I/O such as reading binary files, processing image/audio bytes, and communicating with hardware or network streams.
  • Small value range — When a number will always stay within −128 to 127.
  • Serialization and data transmission — File systems, protocols, and APIs often work in bytes.

Real-life example

Think of packing clothes for travel. With limited luggage space, you carry only small, light items. Similarly, byte is used when space is limited and data values are small.

Real-time testing example

In automation, byte is useful when reading binary files, image data, or HTTP response bytes—for example, when validating image download size or file-upload content.

byte[] arrays are commonly used when testing file uploads/downloads and API response streams.

Project example (STAR)

Situation: During API testing, I had to verify that downloaded images were not corrupted.

Task: Read the file content with the smallest memory footprint.

Action: I used a byte array to read the image data and validated the file size and checksum.

Result: The test became faster, memory usage decreased, and it provided accurate binary-level validation.


while vs do-while Loop

Both loops execute a block of code multiple times, but they differ in when the condition is checked.

while loop

Checks the condition before executing the block.

If the condition is false from the outset, the code block may not execute at all.

do-while loop

Executes the code block once before checking the condition.

This means the block always executes at least once, regardless of whether the condition is true or false.

// while loop

while (condition) {

   // Code to execute

}

// do-while loop

do {

   // Code to execute

} while (condition);

How to remember it

Use a while loop when you want to check the condition first.

Use a do-while loop when you want the code to run at least once and check the condition afterward.


Try It: Everything on This Page in One Program

public class JavaBasicsDemo {
    static class User {
        static int createdCount = 0;          // static: one copy shared by all users
        String username;                      // instance: each object has its own

        User(String username) {               // constructor initialises the new object
            this.username = username;
            createdCount++;
        }
    }

    public static void main(String[] args) {
        User a = new User("asha");            // declaration + instantiation + initialisation
        User b = new User("ravi");
        System.out.println(a.username + ", " + b.username + " | users created: " + User.createdCount);

        byte max = 127;
        max++;                                // byte wraps around silently
        System.out.println("127 + 1 as a byte = " + max);

        int tries = 5;                        // local variable: must be initialised before use
        while (tries < 3) {
            System.out.println("while body ran");
            tries++;
        }
        do {
            System.out.println("do-while body ran once even though tries = " + tries);
        } while (tries < 3);
    }
}

Output (compiled and run with Java 17):

asha, ravi | users created: 2
127 + 1 as a byte = -128
do-while body ran once even though tries = 5

Three things to notice: the static counter is shared by both objects; byte overflows silently from 127 to −128 (a real source of bugs when reading binary data); and with the same false condition, the while body never runs while the do-while body runs once. Step through it line by line — and watch the heap, the static field and each local variable — in the Java Code Visualizer.

From Real Projects

Java has been the language of every automation framework I've worked with — Selenium, TestNG, POM classes and Apache POI for Excel data. Interviews for automation roles regularly include basic programs like this one, often followed by a question on OOP concepts. Practise writing it by hand and explaining how you'd test it. On Canolog, the many forms and screens across sales, inventory, finance and service are where keeping page details in POM classes and reusable steps in a business library paid off. Knowing the difference between primitives and objects explains many surprises later, such as comparing values with == versus equals().


📚 Official documentation: dev.java: Learn Java (Oracle) · Java 21 API documentation

👉 See also: Count Vowels and Consonants in Java | Step-by-Step Guide with Code Examples

Start Here: Hello World and Primitive Types

New to Java? Write and run your first program, and learn what every line of public static void main(String[] args) means, in Hello World in Java and the Structure of a Java Program.

Java has exactly eight primitive data types: byte, short, int, long, float, double, char and boolean. Use int and double by default, long for large numbers, and BigDecimal (not double) for money.

👉 Sizes, ranges, default values and the overflow and division traps, printed by Java itself: Primitive Data Types in Java.

Primitive vs Non-Primitive Data Types in Java

Every Java variable is one of two kinds. A primitive variable holds the value itself. A non-primitive (reference) variable holds a reference to an object that lives on the heap.

PrimitiveNon-primitive (reference)
Examplesbyte, short, int, long, float, double, char, booleanString, arrays, classes (WebDriver, WebElement), interfaces, enums, wrappers like Integer
StoresThe valueA reference to an object
Default value (fields)0, 0.0, '\u0000' or falsenull
SizeFixed (for example int is 32 bits)Depends on the object
Has methods?NoYes, for example name.length()
int retries = 3;                       // primitive: holds 3
String user = "admin";                 // non-primitive: reference to a String object
int[] ids = {101, 102, 103};           // arrays are objects too
List<WebElement> rows = driver.findElements(By.cssSelector("table tr"));

The trap in test code: == compares values for primitives but references for objects. Compare strings with equals(), and compare Integer objects with equals() too, because == only works reliably for small cached values.

FAQs

1. What kinds of variables can a Java class have?

Instance variables (object-specific), static/class variables (shared across all objects), and local variables (temporary, inside methods).


2. What is the difference between instance and static variables?

Each object gets its own copy of an instance variable, whereas a static variable is shared across all objects and is allocated only once.


3. What is a Singleton class?

A design pattern that allows only one object of a class during the whole application using a private constructor, a static self-reference, and a public getInstance() method.

It is commonly used for WebDriver, configuration readers, and log managers.


4. What are the three steps to create an object in Java?

  • Declaration (reference variable)
  • Instantiation (new keyword)
  • Initialization (constructor call that connects the reference to the object)

5. When is the byte data type used?

When storing small integers (−128 to 127) and memory efficiency matters, such as in large arrays, binary/file processing, streams, and network or API byte data.


6. What is the difference between while and do-while?

A while loop checks the condition before executing the code (it may run zero times), whereas a do-while loop executes the code once before checking the condition (it always runs at least once).


7. What are non-primitive data types in Java?

Non-primitive data types are reference types: String, arrays, classes, interfaces, enums and wrapper classes such as Integer. The variable holds a reference to an object, can be null, and lets you call methods on it.


8. Is String a primitive data type in Java?

No. String is a class, so it's a non-primitive (reference) type. It feels primitive because you can create it with a literal like "admin", but it has methods and its default value as a field is null.


9. What is the default value of a non-primitive variable?

null, when the variable is a field of a class. Local variables get no default at all; the compiler makes you assign them before use.