Fading Coder

One Final Commit for the Last Sprint

Home > Tech > Content

Mastering Java Classes, Objects, and Lambda Expressions

Tech 2

Creating and Using Objects

A typical Java application operates by creating objects, which interact by invoking methods. These interactions allow the program to perform tasks such as rendering GUIs, processing calculations, or handling network traffic. Once an object has fulfilled its purpose, its resources are reclaimed for reuse.

Consider the following example, GeometryDemo, which instantiates a Coordinate object and two Box objects.

public class GeometryDemo {

    public static void main(String[] args) {
        // Declare and create a coordinate and two box objects.
        Coordinate startPoint = new Coordinate(23, 94);
        Box containerOne = new Box(startPoint, 100, 200);
        Box containerTwo = new Box(50, 100);

        // Display containerOne's dimensions
        System.out.println("Width of containerOne: " + containerOne.width);
        System.out.println("Height of containerOne: " + containerOne.height);
        System.out.println("Area of containerOne: " + containerOne.calculateArea());

        // Set containerTwo's position
        containerTwo.origin = startPoint;

        // Display containerTwo's position
        System.out.println("X Position of containerTwo: " + containerTwo.origin.x);
        System.out.println("Y Position of containerTwo: " + containerTwo.origin.y);

        // Move containerTwo and display the new position
        containerTwo.move(40, 72);
        System.out.println("X Position of containerTwo: " + containerTwo.origin.x);
        System.out.println("Y Position of containerTwo: " + containerTwo.origin.y);
    }
}

The Lifecycle of an Object

Creating an object involves three distinct steps:

  1. Declaration: Associating a variable name with a specific object type.
  2. Instantiation: Using the new keyword to allocate memory.
  3. Initialization: Calling a constructor to initialize the new object.

Declaration

Declaring a variable does not create an object. It simply notifies the compiler that you will use a specific name to refer to data of a specific type.

Coordinate startPoint; // Declaration only

Instantiation and Initialization

The new operator instantiates a class by allocating memory for a new object and returning a reference to that memory. The operator is followed by a constructor call, which initializes the object.

Coordinate startPoint = new Coordinate(23, 94);

Using Objects

Once an object is created, you can interact with its fields and methods.

Accessing Fields

You access an object's fields using a dot operator (.). If the code is outside the class where the field is defined, you must use a qualified name:

objectReference.fieldName

Invoking Methods

Methods are invoked similarly, by appending the method name to the object reference, followed by arguments in parentheses.

objectReference.methodName(argumentList);

Garbage Collection

Java runtime environments manage memory automatically via garbage collection. An object becomes eligible for garbage collection when it is no longer referenced by any variable. You may explicitly drop a reference by setting the variable to null, but this is rarely necessary.

Classes and Class Members

Returning Values from Methods

A method returns to the code that invoked it when it completes all statements, reaches a return statement, or throws an exception. Methods declared with a return type other than void must use the return statement with a value of the corresponding type.

The this Keyword

Inside an instance method or constructor, this refers to the current object. It is commonly used to distinguish between instance variables and parameters that have the same name (shadowing).

public class Coordinate {
    public int x;
    public int y;

    public Coordinate(int x, int y) {
        this.x = x;
        this.y = y;
    }
}

Access Control Modifiers

Access modifiers determine whether other classes can use a particular field or invoke a specific method.

Modifier Class Package Subclass World
public Y Y Y Y
protected Y Y Y N
(default) Y Y N N
private Y N N N

Static vs. Instance Members

The static keyword creates fields or methods that belong to the class itself rather than to any specific instance. All instances share the same static variable.

public class Device {
    private int id;
    private static int deviceCount = 0;

    public Device() {
        id = ++deviceCount;
    }

    public static int getDeviceCount() {
        return deviceCount;
    }
}

Nested Classes

Java allows you to define a class within another class. These are categorized as:

  • Static Nested Classes: Behave like top-level classes but are nested for packaging convenience. They cannot access instance members of the outer class.
  • Inner Classes: Associated with an instance of the enclosing class and can access its private members.

Local and Anonymous Classes

You can also define classes inside method bodies. These are known as local classes. Anonymous classes are similar but do not have a name; they are used for one-time instantiation and implementation.

Lambda Expressions

Lambda expressions provide a concise way to represent functional interfaces (interfaces with a single abstract method). They allow you to treat functionality as a method argument, or code as data.

Syntax

A lambda expression consists of a parameter list, an arrow token (->), and a body.

(parameterList) -> { expression; }

Example: Filtering Data

Imagine you have a list of Product objects and want to filter them based on price.

Approach 1: Local Class

class PriceFilter implements Filter {
    public boolean test(Product p) {
        return p.getPrice() > 50;
    }
}

filterInventory(inventory, new PriceFilter());

Approach 2: Anonymous Class

filterInventory(inventory, new Filter() {
    public boolean test(Product p) {
        return p.getPrice() > 50;
    }
});

Approach 3: Lambda Expression

filterInventory(inventory, p -> p.getPrice() > 50);

Approach 4: Using Standard Functional Interfaces and Streams

Java provides standard functional interfaces like Predicate<T> in java.util.function.

inventory.stream()
    .filter(p -> p.getPrice() > 50)
    .forEach(p -> System.out.println(p.getName()));

Accessing Enclosing Scope

Like local and anonymous classes, lambda expressions can access local variables and parameters of the enclosing block. However, these variables must be final or effectively final (not modified after initialization).

Tags: Java

Related Articles

Understanding Strong and Weak References in Java

Strong References Strong reference are the most prevalent type of object referencing in Java. When an object has a strong reference pointing to it, the garbage collector will not reclaim its memory. F...

Comprehensive Guide to SSTI Explained with Payload Bypass Techniques

Introduction Server-Side Template Injection (SSTI) is a vulnerability in web applications where user input is improper handled within the template engine and executed on the server. This exploit can r...

Implement Image Upload Functionality for Django Integrated TinyMCE Editor

Django’s Admin panel is highly user-friendly, and pairing it with TinyMCE, an effective rich text editor, simplifies content management significantly. Combining the two is particular useful for bloggi...

Leave a Comment

Anonymous

◎Feel free to join the discussion and share your thoughts.