简体   繁体   中英

Java: Help (and review) with reflection with Generic class

I am creating a Matrix class (just for experiment) with generic type

import java.lang.reflect.Array;
import java.util.Arrays;

@SuppressWarnings("unused")
public class Matrix<T extends Number> {
  private int nRow;
  private int nCol;
  private T[] elements;
  private T[][] elementsGrid;

  public Matrix(int nRow, T[] elements) {
    this(nRow, nRow, elements);
  }

  public Matrix(int nRow, int nCol, T[] elements) {
    if (elements.length != nRow * nCol) {
      throw new IllegalArgumentException(
          "Incorrect size: Expected(" + nRow * nCol + "), but provided(" + elements.length + ")");
    }
    this.nRow = nRow;
    this.nCol = nCol;
    this.elements = elements;

    @SuppressWarnings("unchecked")
    T[][] t = (T[][]) Array.newInstance(elements.getClass().getComponentType(), new int[] { nRow, nCol });

    elementsGrid = t;
    for (int i = 0; i < nRow; i++) {
      for (int j = 0; j < nCol; j++) {
        elementsGrid[i][j] = elements[i * nCol + j];
      }
    }
    System.out.println(Arrays.deepToString(elementsGrid));

  }

Basically i am just taking a single dim array and copying it to double dim array. The code works fine, but I had to struggle a lot with this, and I am not sure if this is indeed the correct way to handle this. For eg if I remove the @SuppressWarnings("unchecked"), it gives me the warning, of unchecked cast. Is it fine to ignore this warning, since I have already declared my generic to only allow subclasses of Number .

Both Class.getComponentType and Array.newInstance are a bit primitive. You can merely do:

Object[][] t = (Object[][]) Array.newInstance(elements.getClass().getComponentType(),
                             nRow, nCol); // Object is actually type T.

But that actually is even formally wrong. It should be T. So your version is not worse.

Look at this:

int[][] t = (int[][]) Array.newInstance(int.class, nRow, nCol);

Not feasible with generics.

For a run-time cast:

Class<?> ctype = elements.getClass().getComponentType();
ctype.cast(object);

An improvement would seem:

// Array:
static <C> C[] newInstance​(Class<C> componentType, int length);

Unfortunately you also can have int.class besides Integer.class for int[].class and Integer.class .

The language means of the typing system in java do not form a complete "algebra" with which to describe all this.

However in a couple of year we will see List<int> .

Meanwhile either look for a more complete language or try ArrayList<T> instead of T[] with an explicit Class<T> componentType to represent the missing getComponentType().

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM