2015-12-26 4 views
2

Я разработчик C++, перемещающийся в Java. Проводя параллели между двумя языками, у меня есть некоторые сомнения относительно использования кучи в java.Переменное распределение в Java

Если мне не нужно сохранять переменную за пределами функции в C++, я бы просто выделил ее в стеке, и пусть стек вызовов позаботится о ее очистке. Таким образом, этот код является совершенно законным в C++,

std::unordered_map<std::string, int> map; 

В Java, хотя, если я пишу подобный код,

HashMap<String, Integer> map; 

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

HashMap<String, Integer> map = new HashMap<>(); 

Мои вопросы, это соглашение Java для нового до каждого объекта, даже если мне не нужно упорствовать его за пределы стека вызовов?

+4

Это не конвенция. Это то, что вам нужно сделать, чтобы создать экземпляр объекта. – juanchopanza

+1

Рядом со всеми объектами в Java создаются «новые». Вы не можете этого избежать. – khelwood

+2

Да, Java имеет только (умные) указатели (сбор собранных мусора ссылок) для кучи объектов для определенных пользователем типов. Их невозможно создать в стеке. – Galik

ответ

6

Java не выделяет map вообще с кодом стиля C++ и предупреждает вас. И вы должны program to the interfaceMap. Вы можете преодолеть это предупреждение с чем-то вроде

Map<String, Integer> map = null; 

или, как в вашем примере,

Map<String, Integer> map = new HashMap<>(); 
3

В Java, вы имеете дело со ссылками на объекты, так что вам нужно либо использовать новые или каким-то образом назначить другому существующему объекту, или переменная будет null, как неинициализированный указатель на C++.

Переменная будет выходить за пределы области действия в конце блока, как на C++, и иметь право на сбор мусора. То есть, если какой-либо другой код не содержит ссылку на него, например, возвращая его из функции или помещая ее в список или карту.

+1

Чтобы укрепить эту идею, вы также можете сделать 'HashMap map = null;', чтобы удалить предупреждение компилятора. В этом случае у вас нет объекта, но есть хотя бы начальное значение. Лучше не выделять переменные, пока вы не собираетесь их использовать, imo. – markspace

5
Map<String, Integer> map; 

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

HashMap<String, Integer> map = new HashMap<>(); 

Создает объект HashMap, что позволяет назвать все методы HashMap и получить доступ к данным.

Map<String, Integer> map = new HashMap<>(); 

Создает объект карты, обобщая HashMap. Вы теряете доступ к некоторым специфичным для HashMap методам (you can check the docs), но если они вам не нужны, это лучше (обычно более общий, тем лучше, как упоминалось в других ответах).

Map<String, Integer> map = null; 

Назначает null переменной карты. Он закроет компилятор, но если вы попытаетесь сделать что-нибудь на нем, прежде чем вызывать конструктор, вы получите NullPointerException, и ваша программа выйдет из строя.

2

В Java (почти) каждый объект находится в «куче», и если в области действия, ссылающейся на объект, нет никаких переменных, объекты автоматически удаляются из кучи при запуске сборщика мусора.

Как и в C++, переменные для объектов не имеют значений до тех пор, пока они не будут созданы. Поэтому почему ваш компилятор предупреждает вас о том, что Map<String, Integer> map; неинициализирован. Это всего лишь предупреждение. Компилятор предупреждает вас, что это была ошибка, которую вы пропустили. Чтобы обойти это, вам нужно присвоить переменной какое-то значение. Это можно сделать либо путем инициализации объекта (говоря: ... = new HashMap<>();), либо вручную присваивая ему значение по умолчанию для неинициализированных объектов (null, говоря: null).

3

Чтобы охватить Java, вы откажетесь от некоторого (много?) Управления памятью по сравнению с C++. Хорошей новостью является то, что вы (в конце концов) не пропустите это.

Назовите свой код «легким» способом изначально, а затем профилируйте его для работы и принимайте контрмеры, если вы найдете узкие места. Следуйте за мантрой: сделайте это бегом, сделайте все правильно, сделайте это быстро.

Я предсказываю вы найдете несколько возможностей для повышения производительности в стороне от вещей, которые уже имеют рамки пула как JDBC соединение, но не принимать мои слова для него - проверить по своему усмотрению. :-)

fwiw, с компилятором hotspot и современной сборкой мусора JVM все это работает очень хорошо.

радужные: Вступление в Java от C++ вы будете иметь более глубокое понимание управления памятью, чем многие Java программистов достичь, которая будет служить вам хорошо, если вы хотите интегрировать вне виртуальной машины Java, чтобы такие вещи, как JNI (https://en.wikipedia.org/wiki/Java_Native_Interface)

Просто для удовольствия вы можете наслаждаться чтением Информационного бюллетеня по настройке производительности Java: http://www.javaperformancetuning.com/news/news179.shtml

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