В чём преимущество (T[]) Array.newInstance(newType.getComponentType(), newLength) перед (T[]) new Object[newLength]?

Если посмотреть в реализацию метода Arrays.copyOf java, то там мы увидим следующий код

? (T[]) new Object[newLength]
        : (T[]) Array.newInstance(newType.getComponentType(), newLength);

За счёт стирания типов, мы всё равно получим Object, так для чего тогда Array.newInstance(newType.getComponentType(), newLength) ?


Ответы (1 шт):

Автор решения: Alexandr

Советую Вам почитать про Ковариантность и контравариантность. Вы приводите только выдержку. Необязательно будет создан Object[], все зависит от параметра newType:

public static <T,U> T[] copyOf(U[] original, int newLength, Class<? extends T[]> newType) {
    @SuppressWarnings("unchecked")
    T[] copy = ((Object)newType == (Object)Object[].class)
            ? (T[]) new Object[newLength]
            : (T[]) Array.newInstance(newType.getComponentType(), newLength);
    System.arraycopy(original, 0, copy, 0,
            Math.min(original.length, newLength));
    return copy;
}

Для информации приведу небольшой тест (Jdk11+), в котором будет использоваться именно Array.newInstance(newType.getComponentType(), newLength):

package com.somepackage;

import lombok.Data;
import org.junit.jupiter.api.Test;

import java.util.Arrays;

import static org.junit.jupiter.api.Assertions.*;

public class ArraysCopyOfTest {

    @Data
    static class Shape { }

    @Data
    static class Circle extends Shape { }

    @Data
    static class Triangle extends Shape { }

    @Test
    public void test_throws() {
        assertThrows(
                ArrayStoreException.class,
                () -> {
                    Circle[] circles =
                            new Circle[]{
                                    new Circle(),
                                    new Circle()
                            };
                    Shape[] shapes = circles;
                    shapes[0] = new Triangle();
                });
    }

    @Test
    public void test_doesNotThrow() {
        assertDoesNotThrow(
                () -> {
                    Circle[] circles =
                            new Circle[]{
                                    new Circle(),
                                    new Circle()
                            };
                    Shape[] shapes =
                            Arrays.copyOf(
                                    circles, circles.length, Shape[].class);
                    shapes[0] = new Triangle();
                });
    }

    @Test
    public void test_class() {
        Circle[] circles =
                new Circle[]{
                        new Circle(),
                        new Circle()
                };
        assertEquals(
                Shape[].class,
                Arrays.copyOf(
                        circles, circles.length, Shape[].class
                ).getClass());
    }

}
→ Ссылка