javacomparatorinner-classes

Why do we use the new operator to access the nested static class in Java?


The below is the Employee class which has a public static nested class called EmployeeNameComparator .

import java.util.Comparator;

public class Employee {

    public static class EmployeeNameComparator<T extends Employee> implements Comparator<Employee> {

        @Override
        public int compare(Employee o1, Employee o2) {
            return o1.name.compareTo(o2.name);
        }
    }

    private String name;
    private int id;
    private int yearStarted;

    public Employee(String name, int id, int yearStarted) {
        this.name = name;
        this.id = id;
        this.yearStarted = yearStarted;
    }

    @Override
    public String toString() {
        return "%d %-15s %d".formatted(id, name, yearStarted);
    }
}

Below is the Main class in which I want to sort the employeeList array with the static nested class comparator in the Employee. My question is that why are we using the new operator in order to use the static class in Employee. I mean we don't use the new operator in order to access, for example, static integer field. What is special about nested static classes in this context?

import java.util.ArrayList;
import java.util.List;

public class Main {
    public static void main(String[] args) {
        List<Employee> employeeList = new ArrayList<>(List.of(
                new Employee("Jack", 1002, 2014),
                new Employee("Mary", 1031, 2019),
                new Employee("Andrew", 1982, 2024),
                new Employee("Bob", 1721, 2000)
        ));

        employeeList.sort(new Employee.EmployeeNameComparator<>());
    }
}

I tried to use the EmployeeNameComparator without the new operator but I got a compilation error. I thought that I can access the nested static EmployeeNameComparator class without instantiating a new Employee class like static ints or doubles.


Solution

  • A static member just means that you don't need an instance of the enclosing class to access that member. In this case, you don't need an instance of Employee to access EmployeeNameComparator.

    The code uses new, simply because it wants to create an instance of EmployeeNameComparator, nothing to do with the static-ness of the class.

    sort needs an instance of some class that conforms to Comparator, and that's why the code is creating a new instance using new. And ultimately, sort needs an instance like that because it needs to call the non-static compare method - it needs an instance to be called.

    If EmployeeNameComparator had not been static, you would have needed to create an instance of Employee, before being able to create an instance of EmployeeNameComparator.

    Employee employee = ... // get some instance here, using "new" or otherwise
    EmployeeNameComparator<Employee> comparator = employee.new EmployeeNameComparator<>();
    

    Notice the use of employee.new. Because EmployeeNameComparator is static, your code doesn't need to do this. It can create a new instance of EmployeeNameComparator without needing an instance of Employee.