2009-02-18 2 views
7

Я часто думал, что было бы неплохо позволить использовать массивы в качестве правильных объектов своими собственными методами вместо того, чтобы полагаться на вспомогательные классы, такие как массивы, массивы и объекты ArrayUtils.Должна ли Java обрабатывать массивы как объекты?

Например:

ints.sort();     // Arrays.sort(ints); 
int[] onemore = ints.add(8); // int[] onemore = ArrayUtils.add(ints, 8); 

Я уверен, что я не первый с этой идеей, но я с трудом искали другие, которые писали об этом раньше. Может ли кто-нибудь помочь мне с некоторыми ссылками на эту тему?

Является ли эта мысль хорошей или плохой идеей и почему?

Насколько легко это реализовать?

Некоторые другие примеры могут включать в себя (но не зацикливаться на них, они постороннее для самого вопроса):

int[] ints = {5,4,3,2,1}; 

// Arrays.sort (ints); 
ints.sort(); 

// int pos = Arrays.asList(ints).indexOf (5); 
// int pos = ArraysUtils.indexOf (ints, 5); 
int pos = ints.indexOf (5); 

// Arrays.reverse (ints); 
ints.reverse(); 

Array<Integer> array = ints; // cast to super class. 

// int length = Array.getLength (array); 
int length = array.getLength(); 

// Object n = Array.get (array, 3); 
Object n = array.get (3); 

// Array.set (array, 3, 7); 
array.set (3, 7); 

Object obj = array; 
// if (obj instanceof int[]) 
//  System.out.println(Array.toString((int[]) obj)); 
// else if (....) 
System.out.println (obj); 
+0

Отличный вопрос! :) –

+0

Не уверен, что вы принимаете микки там, Билл :-) Это ответ на вопрос кого-то, как я бы написал, надеюсь, просвещать их.Вот почему я wiki'd это - не репрессивное для меня. – paxdiablo

+0

Я слежу за другими темами. Я просто не мог удержаться от трястись от удовольствия. Теперь, когда я действительно думаю об этом, это достойный вопрос. –

ответ

7

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

Если вы хотите использовать объекты, вы должны просто использовать Collection (ArrayList - пример коллекции). Он может быть неуклюжим, но коллекции предоставляют тип хорошего методологического доступа, который вам кажется нужным.

+1

Я согласен с тем, что обработка массивов, как примитивных, имеет смысл в 95-м, однако я думаю, что настало время для более объектно-ориентированного подхода. Подобно авто-боксу/un-boxing, это относится к функциям, уже доступным для массивов с более близким подключением. –

+2

Массивы не примитивы. Прочтите документы для Class.isPrimitive. –

+0

«Объектная ориентация» не всегда хорошая вещь Питер! –

1

Это не ПЛОХО идея. Дело в том, что это уже сделано в коллекциях. Попробуйте расширить ArrayList, если вы хотите сходить с ума.

+0

Недостаток ArrayList - это эффективная поддержка примитивов, оператор [] создает два объекта (ArrayList и Object []), когда вам нужен только один. –

3

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

Перед автобоксированием дело с примитивами и объектами было очень громоздким.

Если массивы были объектами и может быть autoboxed (и generisized!), Мы могли бы иметь что-то вроде

Array<Integer> myArray = new Integer[]; 
myArray.add(8); 
int x = myArray[0]; 
.... 

или

Array<Class<? extends MyBaseObject>> myArray = {ExtendedObject.class} 
ExtendedObject object = myArray[0].newInstance(); 
.... 
+0

Я согласен с тем, что примитивы, которые не могут быть прозрачно обработаны как объекты, являются неудачными. Компилятор/JVM должен иметь возможность работать. ArrayUtils имеет два метода toObject() и toPrimitive(). У него может быть другой способ изменить тип массива. –

+0

Я бы предположил, что Array и Integer [] - это два способа написания одной и той же вещи. ;) –

+0

Слишком поздно исправлять такие вещи на Java. Посмотрите на языки, на которых они были частью дизайна с самого начала. Например, в Scala все является объектом. –

5

Эти методы начинают выглядеть очень много, как рубин или питона идиомы. К сожалению, вы не можете сделать это в java (желательно, чтобы вы могли).

Во-первых, как указывали другие, классы коллекций делают это за вас. Для другого, myarray.sort() не так хорош, потому что вы можете создавать массивы объектов, для которых сортировка не определена. Предположим, у меня есть

Foo[] foos; 

И Foo не сопоставим. Что происходит на foos.sort()?Мы определенно не хотели бы, чтобы он работает только для примитивов

int[] ints; 
ints.sort(); //legal 
Object[] objects; 
objects.sort(); //illegal 

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

myarray.add(new Foo()); 

это своего рода бессмысленно, так как массивы в Java не расширяемые.

Это бы хорошо, если распечатывания массив не дать вам, что бесполезный

([I'm an array(*&(* 

мусор, хотя.

+0

ArrayUtils.add(), addAll() и remove() возвращает новый массив с добавленным элементом. –

+0

Эти методы очень полезны для управления массивом, когда вы не хотите накладных расходов на ArrayList. –

0

Для тех, кто пропустил предыдущую запись, которая была закрыта. Некоторые другие примеры включают

int[] ints = {5,4,3,2,1}; 
ints.sort(); // instead of Arrays.sort(ints); 
int pos = ints.indexOf(5); // instead of Arrays.asList(ints).indexOf(5); or ArraysUtils.indexOf(ints, 5); 
ints.reverse(); // instead of Arrays.reverse(ints); 
Array<Integer> array = ints; // cast to super class. 
int length = array.getLength(); // instead of Array.getLength(array); 
Object n = array.get(3); // instead of Array.get(array, 3); 
array.set(3, 7); // instead of Array.set(array, 3, 7); 
Object obj = array; 
System.out.println(obj); // prints [5,4,7,2,1] instead of having to 
// if (obj instanceof int[]) System.out.println(Array.toString((int[]) obj)); else if (....) 

int[] ints2 = ints.copyOf(2); 
int[] ints3 = ints.subArray(2,4); 
ints.sort(myComparator); 
List<Integer> list = ints.asList(); 
Set<Integer> set = ints.asSet(); 
long total = ints.sum(); 
double avg = int.average(); 
int max = ints.max(); 
int max2 = ints.max(myComparator); 
http://commons.apache.org/lang/api/org/apache/commons/lang/ArrayUtils.html 
int[] onemore = ints.add(8); // instead of ArrayUtils.add(ints, 8); 
int[] moreInts = ints.addAll(ints2); // instead of ArraysUtils.addAll(ints, ints2); 
int[] oneless = int.remove(3); // instead of ArrayUtils.remove(ints, 3); 
Integer[] integers = int.toObject(); 
int[] intsAgain = integers.toPrimitive(); 
+0

Я скопирую это на вопрос в качестве добавления, Питер. – paxdiablo

2

Прежде чем я отвечу за СЛЕДУЮЩЕЕ, я расскажу вам о состоянии этой проблемы.

В Java массивы считаются объектами - их можно хранить в списке, например. Однако они являются особыми объектами в том, что они наследуют объект, но не создаются или не получают доступ с тем же синтаксисом (спасибо за исправление Петра). Они агрессивно оптимизируются JVM для очевидных проблем с производительностью, и, таким образом, способ хранения массива зависит от реализации.

Таким образом, аргумент Sun состоял бы в том, что если они предоставили API-интерфейс объекта для массива, может потребоваться определенное аппаратное, программное обеспечение или другие функции спецификации.

Единственный реальный интерфейс для массивов - это статический метод System.arrayCopy или статические методы Array. *, Которые наиболее эффективно копируют в/из массивов.

В ответ следует СЛЕДУЕТ; он был решен, хотя стандарт был бы лучше, чем ответ: используйте ArrayList.

+0

Массивы реализуют только метод clone(), все остальные методы наследуются от Object. Это не значит, что они не реализованы/доступны. Они есть. Все они. –

2

Да, я считаю, что массивы должны иметь API, определенный за пределами, указанным в самом языке. В частности, раздражает то, что Foo[] не реализует Iterable<Foo>. Да, я знаю, что его легко обернуть, но это раздражает, что вам нужно.

. NET получает это в основном вправо, с типом Array, который в основном предназначен для не общего доступа, и различные общие интерфейсы, которые, как предполагается, реализуются с помощью реальных массивов. Например:

IList<int> intList = new int[10]; 

(Это помогает то, что .NET дженерики справиться с примитивными типами лучше, чем Java делает.)

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

В качестве альтернативы различные люди упоминают массивы как примитивы в этой теме. Хотя они, безусловно, имеют специальную обработку, они не определены как примитивы. Из language spec, section 4.2:

Примитивный тип предопределен языком программирования Java и назвал его зарезервированным ключевым словом (§ 3.9):

 
PrimitiveType: 
     NumericType 
     boolean 

NumericType: 
     IntegralType 
     FloatingPointType 

IntegralType: one of 
     byte short int long char 

FloatingPointType: one of 
     float double 
1

Я считаю, что это очень трудно реализовать без нарушения совместимости на многих уровнях.

  • JVM обрабатывает массивы немного иначе, чем другие объекты. Создание/инициализация различна: ни один конструктор не вызван для одной вещи. Как вы хотите добавить новые методы? Если добавив суперкласс, вы бы назвали его конструктором?
  • Массивы знают тип элемента во время выполнения, дженериков нет. Если вы хотите добавить новый суперкласс для всех массивов (например, вы предложили в оригинальном вопросе), вы бы сделали его общим? Также имейте в виду, что массивы являются ковариантными в Java, дженериков нет.
  • Массивы имеют фиксированный набор методов/полей, указанных в Спецификации языка Java (все методы из объектов, которые явно указаны в JLS, поле длины). В зависимости от этого, добавление новых членов, скорее всего, сломает существующих клиентов. (Т.е. массивы не ваш случайный класс)
  • Массив сериализации, вероятно, будут затронуты слишком
  • Я уверен, что есть больше деталей реализации, которые сделали бы это экстремально трудно :-(
  • программы компилируется для работы с новыми методами будет не работать на старых JVM. что еще хуже, в зависимости от реализации, программа, скомпилированная для старых виртуальных машин могут не работать с измененными массивами на новых виртуальных машинах.

Я хотел бы иметь методы непосредственно в «Array классе», я не» t думаю, что его можно реализовать сейчас.

1

Мне лично нравится идея всего, что является объектом, и это уже сделано, например, в небольшом объеме. Тем не менее, последствия создания всего, даже методы/функции объекта очень далеко идущие (взгляните на smalltalk, чтобы понять, что я имею в виду). Будучи последовательным в применении «все является объектом», пользовательский язык больше не похож на C (или Java).

Java был очень сознательно разработан, чтобы быть доступным для программистов C, и ему это удалось, но на самом деле он не очень объектно ориентирован по сравнению с smalltalk. Это наследие, поскольку вариант C появляется повсюду, как в массивах, и тот факт, что есть примитивы.

Так что, чтобы ответить на вопрос СЛЕДУЕТ, я бы сказал нет, потому что Java больше не будет Java с этим изменением. Как указывали другие, существуют и другие классы, которые позволяют обрабатывать задачи, которые могли быть выполнены с помощью массива в C, используя объекты на Java, но чтобы избавиться от примитивных типов данных и массивов alltogether, задача лучше оставлена ​​на другом языке , ИМХО.

0

Одна из причин, я считаю, что это было бы не так трудно, что вы можете добавить методы косвенно, изменяя объект (реальный хак я согласен, но это показывает, что он работает) Добавляя методы объекта, следующий код

int[] ints = {5, 4, 3, 2, 1}; 
System.out.println("ints= "+ints); 
ints.sort(); 
System.out.println("after sort() ints= "+ints); 
ints = ints.add(6); 
System.out.println("after add(6) ints= "+ints); 

Печать

ints= [5, 4, 3, 2, 1] 
after sort() ints= [1, 2, 3, 4, 5] 
after add(6) ints= [1, 2, 3, 4, 5, 6] 

Это работает с Java 5 & 6 и как компилятор и IDE обрабатываются это, как я ожидал.

Смежные вопросы