длина и длина () в Java
Почему у нас длина массива как атрибута, array.length
, а для String у нас есть метод str.length()
?
Есть ли какая-то причина?
- Как печатать двойные кавычки внутри ""?
- Как получить значение переменной, если имя переменной хранится как строка?
- C путаница строк
- Android: что-то лучше, чем андроид: ellipsize = "end", чтобы добавить "..." в укороченные длинные строки?
- Выберите , который href заканчивается некоторой строкой
- Какова цель выражения «new String (...)» в Java?
- Как эффективно конкатенировать строки в Go?
- Почему println (массив) имеет странный выход? ("
- Как сделать нечеткое совпадение имен компаний в MYSQL с PHP для автоматического заполнения?
- Подобный строковый алгоритм
- Как интерполировать переменные в строках в JavaScript, без конкатенации?
- Заменить нечисловую пустую строку
- что такое Ljava.lang.String; @
Позвольте мне сначала выделить три разных способа для аналогичной цели.
length
– массивы ( int[]
, double[]
, String[]
) – знать длину массивов
length()
– связанный с String объект ( String
, StringBuilder
и т. д.) – знать длину строки
size()
– Объект коллекции ( ArrayList
, Set
и т. д.) – знать размер коллекции
Теперь забудьте о length()
рассмотреть только length
и size()
.
length
– это не метод, поэтому совершенно очевидно, что он не будет работать с объектами. Он работает только с массивами.
size()
его имя описывает его лучше, и поскольку это метод, он будет использоваться в случае тех объектов, которые работают с коллекцией (фреймворками коллекции), как я сказал там.
Теперь length()
:
Строка не является примитивным массивом (поэтому мы не можем использовать .length
), а также не коллекцию (поэтому мы не можем использовать .size()
), поэтому нам также нужен другой, который является length()
(сохраняйте различия и подавайте цель).
Как ответ на вопрос почему?
Я считаю это полезным, легким для запоминания и использования и дружелюбия.
Немного упрощенная, вы можете думать об этом как о массивах, которые являются особым случаем, а не обычными classами (немного похожими на примитивы, но нет). Строка и все коллекции являются classами, поэтому методы получения размера, длины или аналогичных вещей.
Я предполагаю, что причиной во время разработки была производительность. Если они создали его сегодня, они, вероятно, придумали что-то вроде массивов коллекции с поддержкой массивов.
Если кому-то интересно, вот небольшой fragment кода, иллюстрирующий разницу между двумя в сгенерированном коде, сначала источник:
public class LengthTest { public static void main(String[] args) { int[] array = {12,1,4}; String string = "Hoo"; System.out.println(array.length); System.out.println(string.length()); } }
Вырезая путь не столь важной части байтового кода, запуск javap -c
в classе приводит к следующим двум двум строкам:
20: getstatic #3; //Field java/lang/System.out:Ljava/io/PrintStream; 23: aload_1 24: arraylength 25: invokevirtual #4; //Method java/io/PrintStream.println:(I)V 28: getstatic #3; //Field java/lang/System.out:Ljava/io/PrintStream; 31: aload_2 32: invokevirtual #5; //Method java/lang/String.length:()I 35: invokevirtual #4; //Method java/io/PrintStream.println:(I)V
В первом случае (20-25) код просто запрашивает JVM для размера массива (в JNI это было бы вызовом GetArrayLength ()), тогда как в случае String (28-35) ему нужно выполнить вызов метода для получения длины.
В середине 1990-х годов, без хороших JIT и т. Д., Он бы полностью уничтожил производительность, чтобы иметь только java.util.Vector (или что-то подобное), а не конструкцию языка, которая на самом деле не вела себя как class, но была быстрой. Разумеется, они могли маскировать свойство как вызов метода и обрабатывать его в компиляторе, но я думаю, что было бы еще более запутанным иметь метод для чего-то, что не является реальным classом.
Рассматривать:
int[] myArray = new int[10]; String myString = "hello world!"; List myList = new ArrayList (); myArray.length // Gives the length of the array myString.length() // Gives the length of the string myList.size() // Gives the length of the list
Весьма вероятно, что строки и массивы были сконструированы в разное время и, следовательно, были использованы в разных соглашениях. Одно из обоснований состоит в том, что, поскольку строки используют внутренние массивы, метод, length()
использовался для избежания дублирования одной и той же информации. Другое заключается в том, что использование метода length()
помогает подчеркнуть неизменность строк, хотя размер массива также не меняется.
В конечном счете это просто несогласованность, которая сложилась, которая определенно была бы исправлена, если бы язык был переработан с нуля. Насколько я знаю, никакие другие языки (C #, Python, Scala и т. Д.) Не делают то же самое, так что это, вероятно, просто небольшой недостаток, который оказался частью языка.
Вы получите сообщение об ошибке, если в любом случае вы используете неверный.
.length
является одноразовым свойством Java. Он используется для определения размера одномерного массива .
.length()
– это метод. Он используется для определения длины String
. Это позволяет избежать дублирования значения.
В Java массив хранит свою длину отдельно от структуры, которая фактически хранит данные. Когда вы создаете массив, вы указываете его длину и становится определяющим атрибутом массива. Независимо от того, что вы делаете с массивом длины N (значения изменения, нулевые значения и т. Д.), Он всегда будет массивом длины N.
Длина строки является случайной; это не атрибут String, а побочный продукт. Хотя Java-строки на самом деле неизменяемы, если бы можно было изменить их содержимое, вы могли бы изменить их длину. Сбрасывание последнего символа (если это было возможно) уменьшило бы длину.
Я понимаю, что это прекрасное различие, и я могу проголосовать за него, но это правда. Если я делаю массив длиной 4, эта длина 4 является определяющей характеристикой массива и истинна независимо от того, что удерживается внутри. Если я создаю строку, содержащую «собак», эта строка имеет длину 4, потому что она содержит четыре символа.
Я рассматриваю это как оправдание для одного с атрибутом, а другой – с помощью метода. По правде говоря, это может быть непреднамеренная непоследовательность, но это всегда имеет смысл для меня, и это всегда то, как я думал об этом.
Мне учили, что для массивов длина не извлекается методом из-за следующего страха: программисты просто назначили длину локальной переменной перед входом в цикл (думаю, цикл for, где условное использует длину массива.) Программист предположительно сделает это, чтобы обрезать вызовы функций (и тем самым повысить производительность). Проблема в том, что длина может измениться во время цикла, а переменная не будет.
Всякий раз, когда создается массив, задается его размер. Таким образом, длину можно рассматривать как атрибут конструкции. Для String это по существу массив символов. Длина – это свойство массива char. Нет необходимости ставить длину как поле, потому что не все нуждается в этом поле. http://www.programcreek.com/2013/11/start-from-length-length-in-java/
Я просто хочу добавить несколько замечаний к большому ответу Фредрика .
Спецификация языка Java в разделе 4.3.1
Объект – это экземпляр classа или массив .
Таким образом, массив действительно играет особую роль в Java. Я действительно удивляюсь, почему.
Можно утверждать, что текущий массив реализации / был важен для лучшей производительности. Но это внутренняя структура, которую не следует раскрывать.
Разумеется, они могли маскировать свойство как вызов метода и обрабатывать его в компиляторе, но я думаю, что было бы еще более запутанным иметь метод для чего-то, что не является реальным classом.
Я согласен с Фредриком в том, что оптимальный выбор оптимального компилятора был бы лучшим выбором. Это также решит проблему: даже если вы используете свойство для массивов, вы не решили проблему для строк и других (неизменяемых) типов коллекций, потому что, например, string
основана на массиве char
как вы можете видеть на определение classа String
:
public final class String implements java.io.Serializable, Comparable, CharSequence { private final char value[]; // ...
И я не согласен с тем, что это будет еще более запутанным, потому что массив наследует все методы из java.lang.Object
.
Как инженер мне действительно не нравится ответ «Потому что это всегда было так». и пожелал бы лучшего ответа. Но в этом случае это похоже.
ТЛ; др
На мой взгляд, это дизайнерский недостаток Java и не должен реализовываться таким образом.