I was told by a colleague that in Java object creation is the most expensive operation you could perform. So I can only conclude to create as few objects as possible.

This seems somewhat to defeat the purpose of object oriented programming. If we aren't creating objects then we are just writing one long class C style, for optimization?

Your colleague has no idea what they are talking about.
Your most expensive operation would be listening to them. They wasted your time mis-directing you to information that is over a decade out of date (as of the original date this answer was posted) as well as you having to spend time posting here and researching the Internet for the truth.
Hopefully they are just ignorantly regurgitating something they heard or read from more than a decade ago and don't know any better. I would take anything else they say as suspect as well, this should be a well known fallacy by anyone that keeps up to date either way.
Everything is an Object ( except primitives )
Everything other than primitives ( int, long, double, etc ) are Objects in Java. There is no way to avoid Object creation in Java.
Object creation in Java due to its memory allocation strategies is faster than C++ in most cases and for all practical purposes compared to everything else in the JVM can be considered "free".
Early as in late 1990's early 2000s JVM implementations did have some performance overhead in the actual allocation of Objects. This hasn't been the case since at least 2005.
If you tune -Xms to support all the memory you need for your application to run correctly, the GC may never have to run and sweep most of the garbage in the modern GC implementations, short lived programs may never GC at all.
It doesn't try and maximize free space, which is a red herring anyway, it maximizes performance of the runtime. If that means the JVM Heap is almost 100% allocated all the time, so be it. Free JVM heap memory doesn't give you anything just sitting there anyway.
There is a misconception that the GC will free memory back to the rest of the system in a useful way, this is completely false!
The JVM heap doesn't grow and shrink so that the rest of the system is positively affected by free memory in the JVM Heap. -Xms allocates ALL of what is specified at startup and its heuristic is to never really release any of that memory back to the OS to be shared with any other OS processes until that instance of the JVM quits completely. -Xms=1GB -Xmx=1GB allocates 1GB of RAM regardless of how many objects are actually created at any given time. There are some settings that allow for percentages of the heap memory to be release, but for all practical purposes the JVM never is able to release enough of this memory for this to ever happen so no other processes can reclaim this memory, so the rest of the system doesn't benefit from the JVM Heap being free either. An RFE for this was "accepted" 29-NOV-2006, but nothing has ever been done about it. This is behavior is not considered a concern by anyone of authority.
There is a misconception that creating many small short lived objects causes the JVM to pause for long periods of time, this is now false as well
Current GC algorithms are actually optimized for creating many many small objects that are short lived, that is basically the 99% heuristic for Java objects in every program. Attempts at Object Pooling will actually make the JVM perform worse in most cases.
The only Objects that need pooling today are Objects that refer to finite resources that are external to the JVM; Sockets, Files, Database Connections, etc and can be reused. Regular objects can not be pooled in the same sense as in languages that allow you direct access to memory locations. Object caching is a different concept and may or may not be what some people naively call pooling, the two concepts are not the same thing and should not be conflated.
The modern GC algorithms don't have this problem because they don't deallocate on a schedule, they deallocate when free memory is needed in a certain generation. If the heap is big enough, then no deallocations happen long enough to cause any pauses.
Object Oriented Dynamic languages are beating C even now days on compute sensitive tests.
