Why is adding an element to a SortedSet permited despite SortedSet being an interface rather than a class

StackOverflow https://stackoverflow.com/questions/13900524

  •  09-12-2021
  •  | 
  •  

Вопрос

Can someone explain me why this code compiles and runs fine, despite the fact that SortedSet is an interface and not a concrete class:

public static void main(String[] args) {

    Integer[] nums = {4, 7, 8, 14, 45, 33};

    List<Integer> numList = Arrays.asList(nums);
    TreeSet<Integer> numSet = new TreeSet<Integer>();
    numSet.addAll(numList);

    SortedSet<Integer> sSet = numSet.subSet(5, 20);
    sSet.add(17);
    System.out.println(sSet);

}

It prints normally the result: [7, 8, 14, 17]

Furthermore, my wonder is heightened by the fact that the SortedSet cannot be instansiated (expectedly). This line does not compile:

SortedSet<Integer> sSet = new SortedSet<Integer>();

However, if I try the code:

public static void main(String[] args) {

    Integer[] nums = {4, 7, 8, 14, 45, 33};

    List<Integer> numList = Arrays.asList(nums);
    numList.add(56);

    System.out.println(numList);
}

it throws an UnsupportedOperationException. I reckon, this comes from the fact that List is an interface and cannot be handled as a concrete class. What is true about SortedSet?

Это было полезно?

Решение

SortedSet is an interface. This means you can have a reference to a class which implements this interface, but not create an instance of class with no implmenetation.

In the case of Arrays.asList() it returns a class which wraps the original array. You cannot add to the original array so add is not supported. If you use set for example, you will alter the original array.

Другие советы

List<Integer> numList = Arrays.asList(nums);

Array.asList() return an array but wrap in List interface. So The list is still backed by the array and the arrays are the fixed size, you cannot add/delete elements from array. That why next line will throw exception UnsupportedOperationException.

For more detail, java ArrayList is still an array behind, but it has some helper method, for you to delete/add elements (you can wiki for phrase resizeable array for more detail.

Secondly, SortedSet is an interface. Interface like abstract class, can have reference to a class that implements/extends its, but it's not concrete class, so you cannot create object on those (interface nor abstract class).

And I see, both two questions you ask, maybe relate to polymorphism in OOP, I recommend you wiki this phrase too.

Hope this help :)

SortedSet is an Interface not a class.

You could only instantiate from non-abstract classes.

List is an interface, too. But according to the doc of List the method "add" is optional, meaning there is NO guaranty to be supported.

I think optional methods contradicts the idea and contract of interfaces. The better would be to have an NonModifyableList (without add) and a ModifyableList (with add). The current poor choice is probably a result the history and the wish not to break old code.

If I understand correctly, you are asking why you can successfully refer to an object as a SortedSet (or any interface type). When a variable's type is an interface or abstract class, that means the variable must hold an object which inherits that variable's type (or the null object).

While every object's actual type has to be a concrete class, the sSet variable is only required to hold an instance of some class that inherits (implements) SortedSet.

In the case of the TreeSet.subSet method, it returns an object whose type is an internally defined concrete class which implements SortedSet.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top