Java: массив примитивных типов данных не блокируется автоматически - PullRequest
28 голосов
/ 05 февраля 2009

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

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[] будут автоматически упакованы в Character и Character[], но этого, похоже, не происходит.

Есть идеи?

Ответы [ 10 ]

37 голосов
/ 05 февраля 2009

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

13 голосов
/ 05 февраля 2009

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

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

3 голосов
/ 03 мая 2009

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

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;
}
2 голосов
/ 13 февраля 2009

Правильно, автобокс для массивов отсутствует (что приводит к странностям в случаях, подобных 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;
}

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

1 голос
/ 01 апреля 2016

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

1 голос
/ 14 ноября 2012

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

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

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

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

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

Лично я предпочитаю использовать гуаву от Google, где вы можете написать что-то вроде

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')
1 голос
/ 02 августа 2009

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

1 голос
/ 05 февраля 2009

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

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

1 голос
/ 05 февраля 2009

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

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

0 голосов
/ 06 февраля 2009

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

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