2

I'm a C++ developer moving into Java. Drawing parallels between the two languages, I have some doubts about heap usage in java.

If I don't need to persist a variable beyond the scope of a function in C++, I would just allocate it on the stack, and let the call stack take care of cleaning it up. Thus this code is perfectly legal in C++,

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

In Java though, if I write a similar code,

HashMap<String, Integer> map;

The compiler gives me a warning, that value of map is uninitialized. To suppress the warning, I have to use,

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

My questions is, is it a Java convention to new up every object, even if I don't need to persist it beyond the call stack?

  • 4
    It is not a convention. It is what you have to do to instantiate an object. – juanchopanza Dec 26 '15 at 22:58
  • 1
    Nearby all objects in Java are instantiated with `new`. You can't avoid it. – khelwood Dec 26 '15 at 23:02
  • 2
    Yes, Java only has (smart) pointers (garbage collected references) to heap objects for user defined types It is not possible to instantiate them on the stack. – Galik Dec 26 '15 at 23:53

5 Answers5

5

Java doesn't allocate map at all with C++ style code and is warning you. And you should program to the interface Map. You can overcome that warning with something like

Map<String, Integer> map = null;

or, as in your example,

Map<String, Integer> map = new HashMap<>();
Community
  • 1
  • 1
Elliott Frisch
  • 198,278
  • 20
  • 158
  • 249
4
Map<String, Integer> map;

just declares a variable, without initializing it (also without allocating memory). It gives an error if you try to use it before assigning something to it.

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

Creates a HashMap object, allowing you to call all the HashMap methods and access the data.

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

Creates a Map object, generalizing the HashMap. You lose access to some HashMap-specific methods (you can check the docs), but if you don't need them, it's better this way (usually the more general, the better, as mentioned in other answers).

Map<String, Integer> map = null;

Assigns null to the map variable. It'll shut the compiler up, but if you try to do anything on it before calling the constructor, you'll get NullPointerException and your program will crash.

Luke
  • 1,284
  • 1
  • 12
  • 34
2

In Java, you deal with references to Objects, so you need to either use new or somehow assign to another existing object, or the variable will be null, like an uninitialized pointer in C++.

The variable will go out of scope at the end of the block like in C++ and be eligible for garbage collection. That is, unless some other code holds a reference to it, for example by returning it from the function or placing it in a list or map.

Robert
  • 7,394
  • 40
  • 45
  • 64
  • 1
    Just to reinforce this idea, you can also do `HashMap map = null;` to remove the compiler warning. You get no object in this case, but there's at least an initial value. It's better though to not allocate variables until you are going to use them, imo. – markspace Dec 26 '15 at 23:05
2

To embrace the Java you will give up some (a lot?) of control over memory management compared to C++. The good news is you (eventually) won't miss it.

Write your code the "easy" way initially, then profile it for performance and take countermeasures if you find bottlenecks. Follow the mantra: make it run, make it right, make it fast.

I predict you will find FEW opportunities to improve performance aside from things that already have pooling frameworks like jdbc connections, but don't take my word for it - verify on your own. :-)

fwiw, with the hotspot compiler and contemporary JVM garbage collection it all performs pretty well.

silver lining: Coming into Java from C++ you will have a deeper understanding of memory management than many Java programmers attain, which will serve you well if you ever want to integrate outside of JVM to things like JNI ( https://en.wikipedia.org/wiki/Java_Native_Interface )

Just for fun, you may enjoy reading the Java Performance Tuning Newsletter: http://www.javaperformancetuning.com/news/news179.shtml

jgreve
  • 1,225
  • 12
  • 17
1

In Java, (almost) every object is on the "heap" and, if there are not any variables in scope that reference the object, objects are automatically deleted from the heap when the garbage collector runs.

Similar to C++, variables for objects do not have values until they are instantiated. Hence why your compiler warns you that Map<String, Integer> map; is uninitialized. This is merely a warning, though. The compiler is warning you that it may have been a mistake your missed. To get past this, you need to assign the variable some value. This can done either by initializing the object (saying: ... = new HashMap<>();) or by manually assigning it the default value for uninitialized objects (null, saying: null).

Spencer D
  • 3,376
  • 2
  • 27
  • 43