Почему не каждый метод является статическим методом? - PullRequest
0 голосов
/ 24 июля 2011

Если не-static функции копируются в кучу для каждого объекта, у которого есть этот метод, то почему не все методы в Java static по умолчанию? Зачем тратить всю эту кучу памяти таким образом?

Для меня было бы более полезно понять схему.

Ответы [ 6 ]

3 голосов
/ 24 июля 2011

Как правило, методы Java не реализованы путем копирования метода в кучу один раз для каждого объекта. Вместо этого методы обычно реализуются с использованием чего-то, называемого таблицей виртуальных функций (или «vtable»). Идея состоит в том, что существует ровно одна копия каждого метода, будь то статический или нестатический метод, и указатели на эти методы размещены в таблице. Каждый объект в куче затем сохраняет указатель на виртуальную таблицу для своего типа объекта. Это означает, что размер любого объекта кучи не зависит от количества методов, которые объект имеет. Фактически, объект с 100 методами будет иметь тот же размер, что и объект с 1 методом (при условии, что они имеют одинаковые поля). Каждый из них просто хранит указатель на vtable для своего типа объекта, из которых есть только одна копия.

Эта оптимизация первоначально использовалась в C ++ для поддержки быстрых виртуальных функций и с тех пор используется во многих других объектно-ориентированных языках. Он позволяет небольшим объектам, но поддерживает динамическую диспетчеризацию.

Другими словами, методы не должны быть static по умолчанию, потому что они не влияют на размер объектов в куче. Создание объекта не занимает больше времени для объектов с большим количеством функций или занимает больше места в куче.

Вот одна из возможных схем расположения некоторых объектов (извинения за искусство ASCII!). Предположим, что у нас есть два класса, A и B. Тогда в памяти объекты этих типов могут выглядеть так:

   A                      vtable for A
 +-------------+        +---------------+
 | vtable ptr  | --+->  | method one    |
 +-------------+   |    +---------------+
 |             |   |    | method two    |
 | fields of A |   |    +---------------+
 |             |   |    |     ...       |
 +-------------+   |    +----------------
                   |    | method N      |
   A               |    +---------------+
 +-------------+   |
 | vtable ptr  |---+
 +-------------+
 |             |
 | fields of A |
 |             |
 +-------------+

   B                  vtable for B
 +-------------+     +------------+
 | vtable ptr  | --> | method one |
 +-------------+     +------------+
 |             |     | method two |
 | fields of B |     +------------+
 |             |     |    ...     |
 +-------------+     +------------+
                     | method M   |
                     +------------+

Обратите внимание, как оба объекта типа A совместно используют одну и ту же таблицу vtable, и как объекты типов A и B используют только один и тот же объем пространства для своего указателя таблицы vtable, даже если у них разное количество методов.

1 голос
/ 24 июля 2011

Нестатические методы не «копируются для каждого объекта в куче». Существует только одна копия каждого метода (кода) на загрузчик классов, точно так же, как для static методов.

Создание метода static не относится к управлению памятью - статическому методу требуется столько же стека и кучи, сколько динамическим методам.

См. Понимание членов экземпляра и класса Учебник Java для объяснения того, для чего используется static.

1 голос
/ 24 июля 2011

Ваш вопрос для сравнения процедурного и объектно-ориентированного программирования.http://en.wikipedia.org/wiki/Procedural_programming#Comparison_with_object-oriented_programming. Основной мотивацией ОО по сравнению с процедурной является наличие структур данных, способных самостоятельно выполнять действия.

Что касается предположений о распределении памяти, методы не копируются в каждый объект, поскольку Java не поддерживаетдинамическое изменение типа.Например, если объект имеет тип Foo, тогда у него будут все методы, объявленные типом Foo.Новые методы не могут быть добавлены к экземплярам Foo без изменения самого типа.Всякий раз, когда метод вызывается для объекта, за кулисами он запускается как процедура.

Всякий раз, когда вы запускаете это:

foo.say( "Hello, world!" );

Java фактически делает что-то вроде этого:

  1. Создайте строку «Hello, world!»
  2. Найдите тип, объявленный для foo.
  3. Найдите метод с подписью say(String) для этого типа.
  4. Запустите этот метод, используя состояние экземпляра объекта foo.

Поскольку методы поддерживают свое собственное состояние, любой нестатический метод можно реализовать статическим путем, передав объектЭкземпляр в качестве параметра метода.Фактически, вышеприведенный шаг 4, вероятно, реализован таким образом компилятором Java.

1 голос
/ 24 июля 2011

Статические методы не могут получить доступ к переменным-членам экземпляра объекта ... Нет состояния, нет ООП.

0 голосов
/ 24 июля 2011

Код метода находится не в стеке, а в части кучи (постоянное поколение, специально созданное сборщиком мусора).В стеке находятся только локальные переменные метода (и подобные данные времени выполнения, например адрес возврата).

Это не зависит от того, являются ли они статическими или нестатическими методами.

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

0 голосов
/ 24 июля 2011

Потому что, если бы каждый метод был статическим, java не был бы объектно-ориентированным.

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

Что касается памяти - каждый статический вызов также идет в стек.

...