Как правило, методы 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, даже если у них разное количество методов.