Можно ли вообще предположить, что toString() имеет низкую стоимость?

Вы обычно предполагаете, что toString() на любом заданном объекте имеет низкую стоимость (т.е. для ведения журнала)? Я делаю. Допустимо ли это предположение? Если у него высокая стоимость, которая обычно должна быть изменена? Каковы веские причины сделать метод toString() с высокой стоимостью? Единственный раз, когда я беспокоюсь о затратах toString, я знаю, что это какая-то коллекция со многими членами. От: http://jamesjava.blogspot.com/2007/08/tostring-cost.html

Обновление. Еще один способ: обычно ли вы смотрите на стоимость вызова toString в любом классе перед его вызовом?

Ответы

Ответ 1

Стандартная библиотека Java, похоже, была написана с целью очень низкой стоимости вызовов toString. Например, Java-массивы и коллекции имеют методы toString, которые не перебирают их содержимое; для получения хорошего строкового представления этих объектов вы должны использовать либо Arrays.toString, либо Collections.toString из пакета java.util.

Аналогично, даже объекты с дорогостоящими equals-методами имеют недорогие вызовы toString. Например, класс java.net.URL имеет метод equals, который использует интернет-соединение, чтобы определить, действительно ли два URL-адреса действительно равны, но он по-прежнему имеет простой и постоянный метод toString.

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

Конечно, вы не должны беспокоиться о производительности, пока не окажетесь в ситуации, когда ваша программа слишком длинная, и даже тогда вы должны использовать профилировщик, чтобы понять, что нужно делать так долго, а не беспокоиться об этом вещи раньше времени.

Ответ 2

Нет, нет. Поскольку ToString() может быть перегружен кем-либо, они могут делать все, что захотят. Это разумное предположение, что ToString() ДОЛЖЕН иметь низкую стоимость, но если ToString() обращается к свойствам, которые выполняют "ленивую загрузку" данных, вы можете даже попасть в базу данных внутри вашего ToString().

Ответ 3

Лучший способ узнать - это профайл вашего кода. Однако, вместо того, чтобы беспокоиться о том, что у конкретной функции есть большие накладные расходы, она (как правило) лучше беспокоится о правильности вашего приложения, а затем делает профилирование производительности на нем (но будьте осторожны, что использование в реальном времени и ваша тестовая установка могут сильно отличаться). Как выясняется, программисты обычно ошибаются в отношении того, что действительно медленное в их приложении, и они часто проводят много времени, оптимизируя вещи, которые не нуждаются в оптимизации (исключая этот тройной вложенный цикл, который потребляет только 0,01% вашего времени приложения отходы).

К счастью, есть много профилировщиков с открытым исходным кодом для Java.

Ответ 4

Вы обычно предполагаете, что toString() для любого данного объекта имеет низкую стоимость? Я делаю.

Зачем вам это делать? Профилируйте свой код, если вы столкнулись с проблемами производительности; это сэкономит вам много времени, проработав неверные предположения.

Ответ 5

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

Ответ 6

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

Ответ 7

Моим прагматичным ответом было бы: да, вы всегда считаете, что вызов toString() дешев, если вы не делаете их огромным количеством. С одной стороны, очень маловероятно, что метод toString() будет дорогостоящим, а с другой стороны, крайне маловероятно, что вы столкнулись с проблемой, если это не так. Обычно я не беспокоюсь о таких проблемах, потому что их слишком много, и вы не получите никакого кода, если вы это сделаете;).

Если вы столкнулись с проблемами производительности, все открыто, включая производительность toString(), и вы должны, как предлагает Shog9, просто профилировать код. Java Puzzlers показывают, что даже Sun написало несколько довольно неприятных конструкторов и методов toString() в своих JDK.

Ответ 8

Я думаю, что у этого вопроса есть недостаток. Я бы даже не предположил, что toString() напечатает полезную часть данных. Итак, если вы начнете с этого предположения, вы знаете, что вам нужно проверить его до его вызова и оценить его "стоимость" на индивидуальной основе.

Ответ 9

Возможно, наибольшая стоимость с наивным цепочкой toString() добавляет все эти строки. Если вы хотите генерировать большие строки, вы должны использовать базовое представление, поддерживающее эффективное добавление. Если вы знаете, что append эффективен, то toString(), вероятно, имеет относительно низкую стоимость.

Например, в Java StringBuilder предварительно выделяет некоторое пространство, так что определенное количество добавлений в строку занимает линейное время. Он будет перераспределяться, когда вы исчерпаете пространство.

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

Ответ 10

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

Ответ 11

Моя мысль:

Да на объектах стандартной библиотеки

Нет на нестандартных объектах, если у вас нет исходного кода и вы можете его проверить.

Ответ 12

Я всегда буду переопределять toString, чтобы вставить все, что я думаю, мне нужно будет отлаживать проблемы. Обычно разработчик должен использовать его либо путем вызова метода toString, либо для вызова другого класса (println, logging и т.д.).

Ответ 13

Там есть легкий ответ на этот вопрос, который я впервые услышал в дискуссии о размышлении: "Если вы должны спросить, вы не можете себе этого позволить".

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

ToString() для сообщений журнала автоматически в порядке, поскольку ведение журнала уже дорого. Если ваша программа слишком медленная, отключите уровень журнала! На самом деле не имеет значения, насколько медленно приходится генерировать отладочные сообщения, если вы не можете их генерировать. (Обратите внимание: ваша инфраструктура регистрации должна вызывать ToString() и только тогда, когда должно быть напечатано сообщение журнала. Не направляйте ToString() вручную по пути в инфраструктуру журнала или платите цену даже если уровень журнала низкий, и вы его больше не будете печатать! Подробнее см. http://www.colijn.ca/~caffeine/?m=200708#16.)

Ответ 14

Поскольку вы ставите "вообще" в свой вопрос, я бы сказал "да". Для большинства объектов, не будет дорогостоящей перегрузки ToString. Там определенно может быть, но вообще не будет.

Ответ 15

В общем, я считаю, что atString() низкая стоимость, когда я использую его на простых объектах, таких как целое или очень простая структура. Однако, когда применяется к сложным объектам, toString() - это немного дерьмовой стрельбы. Для этого есть две причины. Во-первых, сложные объекты, как правило, содержат другие объекты, поэтому один вызов toString() может каскадироваться во многие вызовы toString() для других объектов, а также из-за сокрытия всех этих результатов. Во-вторых, нет никакого "стандарта" для преобразования сложных объектов в строки. Один вызов toString() может выдать отдельную строку значений, разделенных запятыми; другая - гораздо более многословная форма. Только проверив это, вы можете знать.

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

Ответ 16

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

Обычно существует несколько причин, по которым вы используете toString(): регистрация/отладка, вероятно, является наиболее распространенной для случайных объектов; отображение является обычным для определенных объектов (например, чисел). Для ведения журнала я бы сделал что-то вроде

if(logger.isDebugEnabled()) {
    logger.debug("The zig didn't take off.  Response: {0}", response.getAsXML().toString());
}

Это делает две вещи: 1. Предотвращает создание строки и 2. Предотвращает ненужное добавление строки, если сообщение не будет зарегистрировано.

Ответ 17

В общем, я не проверяю каждую реализацию. Однако, если я вижу зависимость от общих ресурсов Apache, сигнальные колокола прекращаются, и я более внимательно смотрю на реализацию, чтобы убедиться, что они не используют ToStringBuilder или другие зверства.