• notice
  • Congratulations on the launch of the Sought Tech site

Create Generic General Array in Java

1 Introduction

We may want to use arrays as part of a class or function that supports generics. This can be difficult due to the way Java handles generics.

In this tutorial, we will understand the challenges of using generics on arrays. Then, we will create an example of a generic array.

We will also look at where the Java API solves similar problems.

2.Precautions when using general-purpose arrays

The important difference between arrays and generics is how they perform type checking. Specifically, the array stores and checks type information at runtime. However, generics check for type errors at compile time, and there is no type information at runtime.

The syntax of Java suggests that we might be able to create a new universal array:

T[] elements = new T[size];

However, if you try to do so, you will get a compilation error.

To understand why, consider the following:

public <T> T[] getArray(int size) {
T[] genericArray = new T[size]; // suppose this is allowed
return genericArray;
}

When the unbound generic type Tresolves to Object,our method at runtime, it will be:

public Object[] getArray(int size) {
Object[] genericArray = new Object[size];
return genericArray;
}

Then, if we call the method and store the result in Stringan array:

String[] myArray = getArray(5);

The code can compile normally, but it fails at runtime with ClassCastException. This is because we just Object[]assigned to the String[]reference. Specifically, the compiler's implicit cast will not be able to Object[]convert to the String[]type we need .

Although we cannot directly initialize a general-purpose array, it is still possible to achieve equivalent operations if the calling code provides accurate information types.

3.Create a general array

For our example, let us consider a bounded stack data structure MyStackin which the capacity is fixed to a certain size. In addition, since we hope that the stack can use any type, a reasonable implementation choice will be a general-purpose array.

First, let's create a field to store stack elements, which is Ea generic array of type :

private E[] elements;

Second, let's add a constructor:

public MyStack(Class<E> clazz, int capacity) {
elements = (E[]) Array.newInstance(clazz, capacity);
}

Note that we java.lang.reflect.Array#newInstanceinitialize our general array , which requires two parameters. The first parameter specifies the type of objects in the new array. The second parameter specifies how much space to create for the array. Array#newInstanceThe result of is the Objecttype, and we need to use it E[]to create our general array.

We should also pay attention to the convention of naming type parameters clazzinstead class,of, which is a reserved word in Java.

4.ConsiderArrayList

4.1. Use ArrayListarray

In general, ArrayListit is easier to use general instead of general arrays. Let's see how to change it MyStackto use ArrayList.

First, let's create a field to store the elements:

private List<E> elements;

Second, in our stack constructor, we can use the initial capacityArrayList

elements = new ArrayList<>(capacity);

It makes our classes simpler because we don't have to use reflection. In addition, when creating the stack, we do not need to pass the class text. Finally, because ArrayListof the initial capacity we can set, we can get the same benefits as arrays.

Therefore, it is only necessary to construct a generic array in rare cases or when establishing an interface with an external library that requires an array.

4.2. ArrayListaccomplish

The interesting thing is that ArrayListit is implemented using a general-purpose array. Let's take a peek and ArrayListsee how.

First, let's look at the list element fields:

transient Object[] elementData;

Note the ArrayListuse Objectas an element type. Because our general type is not known until runtime, it is Objectused as a superclass of any type.

ArrayListAlmost all operations in can use this general array, because toArraythey do not need to provide a strongly typed array to the outside world except for one method .

5.Build an array from a collection

5.1. LinkedList example

Let's take a look at the use of generic arrays in the Java Collections API.We will build a new array in a collection.

First, let's use the type parameter String LinkedListand add items to it:

List<String> items = new LinkedList();
items.add("first item");
items.add("second item");

Second, let's build the array of the items we just added:

String[] itemsAsArray = items.toArray(new String[0]);

To build our array ListtoArrayThe method requires an input array. It uses this array purely to obtain type information to create a return array of the correct type.

In the above example, we used new String[0]as the input array to build the result Stringarray.

5.2. LinkedList.toArrayaccomplish

Let us LinkedList.toArraysee how it is implemented in Java JDK.

First, let's look at the method signature:

public <T> T[] toArray(T[] a)

Second, let's see how to create a new array when needed:

a = (T[])java.lang.reflect.Array.newInstance(a.getClass().getComponentType(), size);

Note how it is used Array#newInstanceto construct a new array, just like the previous stack example. Also, please pay attention to how to use parameters to a Array#newInstance.provide types. Finally, Array#newInstancethe result is cast to T[]create a universal array.

Six, conclusion

In this article, we first studied the difference between arrays and generics, and then introduced an example of creating generic arrays. Then, we showed that it ArrayListmay be easier to use than to use general-purpose arrays. Finally, we also studied the use of general arrays in the Collections API.


Tags

Technical otaku

Sought technology together

Related Topic

0 Comments

Leave a Reply

+