Java: массив примитивных типов данных не autobox
у меня есть способ такой:
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[]
, но этого, похоже, не происходит.
какие выводы?
10 ответов
зачем 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[]
обернуть типа char[]. Однако List<Character>
можно обернуть char[]
.
массивы ссылок обычно не являются хорошей идеей, если вы не пишете низкоуровневый код. Вы можете, если хотите, написать или получить эквивалент java.util.Arrays.asList
.
Как упоминали другие, для массивов примитивов нет автобоксинга. Если вы хотите использовать свой метод с примитивными массивами, вам нужно будет предоставить перегрузку для каждого примитивного типа. Кажется, это стандартный способ делать что-то в библиотеках классов. См. перегрузки в java.утиль.Массивы, например.
во-первых, я бы постарался избегать массивов столько, сколько вы можете, вместо этого используйте списки.
нет автобоксинга для массивов, но есть автобоксинг для 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')
введите Java 8 и пусть primArray
быть идентификатором типа PrimType[]
, то can сделать следующее:
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;