Over a million developers have joined DZone.
{{announcement.body}}
{{announcement.title}}

Isn't Java a Civilised Language?

DZone's Guide to

Isn't Java a Civilised Language?

· Java Zone
Free Resource

Managing a MongoDB deployment? Take a load off and live migrate to MongoDB Atlas, the official automated service, with little to no downtime.

A few weeks ago I was given the opportunity to learn iOS programming. My current boss decided that I was more of a ‘computer scientist’ rather than a developer, which I thought was a nice compliment, and this meant that I could apply my knowledge to developing an iPad application or two - all I’d need to do was to learn Objective-C and the iOS SDK: how hard can it be?

Although I’ve done lots of C/C++ in the past, I’ve been doing Java since 2001, so I’d forgotten much of what I knew, and besides, Objective-C isn’t much like C++ anyway. The result is that you feel like you’ve washed up on a foreign shore unable to speak the language and you’re armed with nothing more than a sun tan and a dictionary.

In learning all this new stuff, I came to realise that Java is a VERY good language and the reason is, firstly and foremost, because you don’t have to think about memory allocation and deallocation, you can just get on with writing your application. In Objective-C, you have to both allocate memory for your objects and then clear up after yourself, returning memory back to the free-pool. This seems very old school for the second decade of the 21 st century. Furthermore, having allocated memory for an object, you have to keep track of the number of references there are to it - a practice known as reference counting, something I first came across in my previous life as a C++ programmer. The fundamental idea here is that every time you create a new reference to an object, you increment the reference counter and when you’ve finished with the object reference you decrement its reference counter. When the counter reaches zero, the the system releases the memory back to the free pool. In Objective-C, the function to decrement the reference count is called release; hence if Java had reference counting and if I wanted to ask an AddressService to find me an address, I’d need to do something like this:

    // create an object and set the reference count to 1
    AddressService addressService = new AddressService(); 
    // Use the object
    Address address = addressService.findAddress(id);
    // pass it to a method
    model.addAttribute("address", address);
    // free the memory
    addressService.release();

That’s the simple scenario, but what happens if some method or other passes you an object reference as a method argument? In that case you have to decide how you’re going to hang on to it and there seem to be two ways of doing this. The first is to make a copy of the object and the second is to increment its reference count. Making a copy is probably the safest idea, but consumes more memory and will be slower, whilst incrementing the reference count is quick but not as safe as some other part of the program may get the reference counting wrong and decrement the count one too many times, which means that you’ve got a reference to some memory that may have been released, and when you try to access your released object your program will crash.... Again, if Java had reference counting then a Spring Controller request handler method would look something like this:

  @RequestMapping(value = "/find", method = RequestMethod.GET)
  public String findAddress(@RequestParam("id") int id, Model model) {
   
    // increment the reference count - 'retain' is the Objective-C method for doing this.
    model.retain();   

    // create a new string object - with reference count of one
    String msg = new String().withFormat("Processing an address page request for address with id: " + id);
    // pass the string to the logger
    logger.info(msg);
    // release the string's memory
    msg.release();

    AddressService addressService = new AddressService();
    Address address = addressService.findAddress(id);
    model.addAttribute("address", address);
    addressService.release();

    // finished with the model
    model.release();
    return "address-display";
  }

There are a couple of points to note here - firstly, the handler method is passed a model object, so I increment the reference count by calling retain and then call release on the model when I’m finished with it at the end of the method. Secondly, even when creating trivial objects, like a message string that’s passed to a logger, you have to apply the reference counting rules and free the memory once you’ve finished with it.

The example below demonstrates the alternative to incrementing the reference count: making your own copy of an object...

  @RequestMapping(value = "/find", method = RequestMethod.GET)
  public String findAddress(@RequestParam("id") int id, Model model) {
   
    // increment the reference count - 'retain' is the Objective-C method for doing this.
    Model myModel = model.copy();   

    // As previous example
   
    // finished with the model
    myModel.release();
    return "address-display";
  }

These examples are only trivial, there’s a whole bunch of reference counting rules that you need to apply and if you get it wrong then Ka-Bam your program crashes and getting it wrong means either you try to access memory that’s already been freed, or slowly die due to a memory leak because you've forgotten to release some memory.

The code above is just a bit of scribble written to illustrate the point - it won’t compile. The code was actually taken from my Address sample on GitHub and in real life looks like this:
  @RequestMapping(value = "/find", method = RequestMethod.GET)
  public String findAddress(@RequestParam("id") int id, Model model) {

    logger.info("Processing an address page request for address with id: " + id);

    Address address = addressService.findAddress(id);
    model.addAttribute("address", address);

    return "address-display";
  }

...much smaller neater and more understandable. One last point, some of you will have noticed that in the reference counting example, I allocate (Objective-C word) a new AddressService - this is because iOS programming has nothing like dependency injection or a Spring framework, so you’re back to creating objects for yourself. (Note to the Guys at Spring: ‘Spring iOS’ - sounds like an idea to me...)

Those of you in the know will highlight the fact that Apple recently introduced something called ‘Automatic Reference Counting’. Whilst it isn’t garbage collection, it’s simplifies things in that iOS will now automatically keep track of your pointer references and free memory for you when the count reaches zero, which means that you don’t have to bother calling the retain and release methods.

Also, this blog isn’t trying to denigrate Objective-C - I quite like Objective-C. Its syntax seems rather arcane and feels verbose when compared to Java, but it forces you to be more disciplined in your programming technique, so if like me you believe that good programming is down to ‘clarity of thought’, then when writing an Objective-C program you have to think a little bit more clearly, and that I really like.

Finally, I’m just a ‘newbie’ when it comes to iOS programming, so if any iOS/Objective-C masters come across this blog - please let me know where I’m wrong.

 

From http://www.captaindebug.com/2012/02/isnt-java-civilised-language.html

MongoDB Atlas is the easiest way to run the fastest-growing database for modern applications — no installation, setup, or configuration required. Easily live migrate an existing workload or start with 512MB of storage for free.

Topics:

Opinions expressed by DZone contributors are their own.

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}