Java - Язык:Массив примитивных типов данных не блокируется автоматически

StackOverflow https://stackoverflow.com/questions/517751

  •  21-08-2019
  •  | 
  •  

Вопрос

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

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[], но, похоже, этого не происходит.

Есть какие-нибудь идеи?

Это было полезно?

Решение

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

Другие советы

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

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

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

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;
}

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

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

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

Видишь эта статья и этот баг, например.

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

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

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

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

Автобоксинг для массивов отсутствует, но есть автобоксинг для 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')

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

Более простым способом сделать это является

char ch = 'a';
String chars = "abc";
boolean member = chars.indexOf(ch) >= 0;
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top