Подтвердить что ты не робот

Java: массив примитивных типов данных не автобокс

У меня есть такой способ:

public static <T> boolean isMemberOf(T item, T[] set)
{
    for (T t : set) {
        if (t.equals(item)) {
            return true;
        }
    }
    return false;
}

Теперь я пытаюсь вызвать этот метод, используя char для T:

char ch = 'a';
char[] chars = new char[] { 'a', 'b', 'c' };
boolean member = isMemberOf(ch, chars);

Это не работает. Я ожидал бы, что char и char[] получат autoboxed до Character и Character[], но это, похоже, не происходит.

Любые идеи?

4b9b3361

Ответ 1

Нет никаких автобоксинга для массивов, только для примитивов. Я считаю, что это твоя проблема.

Ответ 2

Почему char[] был помещен в поле Character[]? Массивы всегда являются ссылочными типами, поэтому бокс не требуется.

Кроме того, это было бы ужасно дорого - это включало бы создание нового массива, а затем по боксу каждый char по очереди. Хлоп!

Ответ 3

Вы можете использовать отражение, чтобы получить метод, который работает для всех типов массивов, но вы потеряете безопасность типа, поэтому это, вероятно, не то, что вы хотите.

import java.lang.reflect.Array
public static boolean isMemberOfArray(Object item, Object array)
{
    int n = Array.getLength(array)
    for (int i = 0; i < n; i++) {
        if (Array.get(array, i).equals(item)) {
            return true;
        }
    }
    return false;
}

Ответ 4

Правильно, нет автобоксинга для массивов (что приводит к странности в таких случаях, как int[] ints; ...; Arrays.asList(ints) - asList возвращает список, содержащий один объект, массив!)

Вот простая утилита для размещения массива.

public static Integer[] boxedArray(int[] array) {
    Integer[] result = new Integer[array.length];
    for (int i = 0; i < array.length; i++)
        result[i] = array[i];
    return result;
}

Разумеется, вам понадобится другая версия для каждого примитивного типа.

Ответ 5

Это, по-видимому, по дизайну, чтобы избежать такой дорогостоящей операции автобоксинга и потому, что дженерики должны быть обратно совместимы с существующим байт-кодом Java.

Смотрите эту статью и эту ошибку, например.

Ответ 6

Массивы представляют собой тип реализации на уровне низкого уровня. char[] будет смежной областью памяти с двухбайтовыми символами. Character[] будет смежной областью памяти с четырьмя или восьмибайтовыми ссылками. Вы не можете получить Character[] для обертывания char []. Однако List<Character> может обернуть char[].

Массивы ссылок обычно не являются хорошей идеей, если вы не пишете низкоуровневый код. Вы можете, если хотите, написать или получить эквивалент java.util.Arrays.asList.

Ответ 7

Как уже упоминалось, для массивов примитивов нет автобоксинга. Если вы хотите использовать свой метод с примитивными массивами, вам нужно будет обеспечить перегруз для каждого примитивного типа. Кажется, это стандартный способ делать вещи в библиотеках классов. См. Перегрузки в java.util.Arrays, например.

Ответ 8

Во-первых, я старался избегать массивов столько, сколько вы можете, вместо этого используйте списки.

Нет автобоксинга для массивов, но для varargs существует автобоксинг. Поэтому, если вы объявите свой метод как (с тем же телом):

public static <T> boolean isMemberOf(T item, T ... set)

тогда вы можете написать

isMemberOf('a', 'a', 'b', 'c');

Лично я предпочитаю использовать google guava, где вы можете писать такие вещи, как

char ch = 'a';
char[] chars = new char[] { 'a', 'b', 'c' };
boolean member = isMemberOf(ch, Chars.asList(chars).toArray(new Character[0]));

Ваш код, вероятно, был всего лишь примером, но если вы действительно хотели проверить членство, вы можете сделать это следующим образом:

Chars.contains(chars, ch);

or

ImmutableSet.of('a', 'b', 'c').contains('a')

Ответ 9

Введите Java 8 и пусть primArray будет идентификатором типа PrimType[], тогда вы можете сделать следующее:
BoxedType[] boxedArray = IntStream.range(0, primArray.length).mapToObj(i -> primArray[i]).toArray(BoxedType[] :: new);

Ответ 10

Более простой способ сделать это -

char ch = 'a';
String chars = "abc";
boolean member = chars.indexOf(ch) >= 0;