Concatenate unlimited amount of arrays with predefined function
The approach suggested by @Caridorc has the limitation that it requires the objects passed to be Iterables, which an array is not a subtype of due to certain limitations. Therefore, you either have to change your data type from an array to some Iterable extension or use a different approach.

A simple, naive solution would be to simple convert arrays to Lists and add all to a combined list like this:

private static &lt;T&gt; T[] merge2(T[] ... arrays) {
    final List&lt;T&gt; list = new ArrayList&lt;&gt;();
    for (T[] array : arrays) {
      list.addAll(Arrays.asList(array));
    }
    return list.toArray(arrays[0]);
}


which has certain runtime penalties as you create multiple new objects which furthermore on adding new lists via addAll(...) will increase the capacity of the list by 50% of its current length on exceeding the current size and therefore contain some unused space.

A further approach is based on your generic approach but contains only two loops. The first one to learn the total length, the second one to copy the data from the source array to the target array:

private static &lt;T&gt; T[] merge3(T[] ... arrays) {
    Class&lt;?&gt; componentType = arrays[0].getClass().getComponentType();
    int size = 0;
    for (T[] array : arrays) {
      size += array.length;
    }
    T[] result = (T[])arrays[0].getClass().cast(Array.newInstance(componentType, size));
    int pos = 0;
    for (T[] array : arrays) {
      System.arraycopy(array, 0, result, pos, array.length);
      pos += array.length;
    }
    return result;
}


This method is shorter and IMO easier to read then your implementation. A short comparison between the 4 algorithms reveals also, that it is faster then the other ones:

Original - Total: 51.402688 ms, Average: 5.1402688E-4 ms
Original Generics - Total: 42.150794 ms, Average: 4.2150794E-4 ms
Merge2 - Total: 87.06185 ms, Average: 8.706185E-4 ms
Merge3 - Total: 28.701731 ms, Average: 2.8701731E-4 ms


Note however, that I did a naive performance test and didn't take care of compiler optimizations or warm-up phases. The comparison therefore may be flawed and data messy.

Also note that I did not take care of checking if all of the passed arrays are of the same type. Mingling multiple arrays of different types might only work if the first passed array is of type object (or at least a supertype of any further arrays). In general, I wouldn't allow to pass arrays of different types though. 

BTW: the double cast in merge3 is to get rid of Unchecked cast warnings