Completing the Syntactic Comparison of Java and C/C++

This is the second half of the two-part series on the syntactic comparison of Java and C/C++. Before we begin, I’d like to encourage you to read its first part if by any chance you’ve missed it. It is called “Syntactic Comparison of Java and C/C++” and it’s published right here. You shouldn’t miss it because grasping the basics is crucial.

In the first part I showed you the main differences as far as data types, classes, and some additional important details on the semantics of those two languages. Now we’re going to discuss more thoroughly the topics of classes, command line arguments, unconditional transfers of control (goto, labels, break, continue), and so forth.

Moreover, before finishing this article I’ll point out the features that are present in C/C++ but missing from Java and vice versa. Furthermore, you might be expecting some kind of conclusion or final words at the end. I definitely won’t conclude that one is better than the other but I’m determined to give you my personal opinions regarding these two languages.

Now the time has come for us to begin. Ready, Steady, Go!


I’ve mentioned in my previous article that a class is one of the most important concepts in Java. That’s because everything must take part of a class. This wasn’t fashionable with C/C++. Even though classes have critical importance in C/C++ too, they aren’t necessary. In Java they are required and everything happens around them.

Should you desire to create global functions and use global variables, you are going to encapsulate everything inside a class. You do this by creating static methods and static data that ultimately are placed inside a class. Of course, encapsulation into multiple classes is possible too. Additionally, it is worth mentioning that there is a huge family of classes that has a so-called superclass (ancestor), the Object class.

Java also has a long list of access modifiers that can be implemented to classes, constructors, methods, etc. Each of these has their very own rules according to which they can be implemented. For example, out of the following 3 modifiers only one should be used when declaring a method: private, public, protected; or methods that have modified as abstract or native should have no body.

A final note on access modifiers is that they do not interfere with inheritance by prevention. On the other hand, they do affect which parts you can or cannot see within a subclass. Speaking of inheritance, another significant difference is that multiple inheritances aren’t allowed in Java. But there’s a so-called interface structure that is not a class but can inherit from a base class (superclass).

However, there is a workaround by implementing multiple interfaces. An interface is a class that contains nothing but abstract methods. Hence, their body must be defined in the inherited classes.

{mospagebreak title=Classes continued}

In Java to set the relationship between a parent and child class you need to use the extends keyword. Likewise, the keyword this works the same as it does in C/C++; it stands for referring to the method itself. Additionally, Java has super that is used when you want to refer to a method that’s within a parent class.

Now let’s talk about constructors and destructors. A constructor is a method that basically defines the way an/more object(s) should be created. These do not return any kinds of values. Each class in Java can contain one or more constructors. We all know that in C/C++ destructors were used to free up the memory that was allocated to a particular object. However, this isn’t the way Java works. Destructors aren’t required.

In Java there’s a new addition called garbage collection. What this collector does is quite simple to understand. On a very frequent basis it verifies all of the references in all objects; due to this, it classifies each of them as either live or dead. References that do not exist (cannot be reached) are rapidly freed up from the memory.

As a result, destructors aren’t necessary anymore. Garbage collector (GC) does it more efficiently than any coder could explicitly do it in C/C++. It won’t free up live objects by mistake, nor will it forget to perform the task of freeing memory and thus leave dead objects further clogging up the memory. Once you get the hang of Java you’ll realize that GC is great!

Nevertheless, nobody prevents you from explicitly freeing up the objects. There’s a method called finalize() that indeed finalizes an object. Each class can contain the finalize method because it’s defined within the Object superclass, therefore every class inherits it. Calling finalize is akin to freeing up the object before it gets collected by the GC (read as: freed up automatically).

{mospagebreak title=Other Distinctions}

In my previous article I mentioned that the developers of Java constantly focused on portability (being able to run the code on various platforms). C and C++ are programming languages that allow heavy usage of preprocessors. A preprocessor changes the mechanism of how a program runs; it defines constants, includes additional source files (header files), specifies compilation particulars, and so forth.

Preprocessors are certainly very useful and any C-coder knows that. However, they can be a source of many problems, especially when considering portability. You may be faced with a #define that changes a variable throughout the whole source code, for example, or an #include that adds header files that are required, leaving you with problems if they aren’t reachable, and many other issues.

Therefore, there are absolutely no preprocessors in Java. Developers considered them to be a hit on cross-platform (and -compiler) portability and thus implemented other workarounds. In Java you do not #include a header file to gain access to its constants and functions, because you import what you need.

Imports fold the required constants, functions, etc. into your code instead of the header files as a whole. Should you need to define a constant as you did “#define A 50” in C, you approach the situation differently in Java. There is a Globals class (in Java everything is inside classes, remember?) that holds your public constants and static methods. In that class you’d write: “public static final int A = 50;” (without the quotation marks).

Since there are no preprocessors the usage of #if and #ifdef isn’t allowed either. Conditional compiling is most often used for cross-platform portability and thus isn’t required in Java, but it can be used for debugging or to create particular interfaces for specific platforms. It works a tad bit differently and so it is beyond this article’s scope.

I’ve recently mentioned constants. In Java each variable that’s declared final is a constant. Let’s consider the following example. We’re going to define Pi as: “public static double PI = 3.14159;”. This type of declaration does not prevent changing its value. Literally we could change its value to 1000. Needless to say, we want a constant and that’s why we’re going to declare Pi as: “public static final double PI = 3.14159;”.

Speaking of Pi we shouldn’t forget that it’s already declared in the java.lang.Math class. By importing that class you will be allowed to use it throughout your code as Math.PI, not necessarily typing its whole name. Allowing shorter names is a really useful feature.

Moving on… another deviation from good old C and C++ is related to goto. In Java goto isn’t allowed. However, it is a reserved name but it is not implemented. The workaround to unconditional jumps is using labeled breaks and continues. The aforementioned two work exactly as they do in C/C++ but additionally you can link them with labels. For example: “break label1;” or “continue label2;”.

Java is a multithreading programming language. Consequently, it has a feature that can be used to prevent simultaneous access to a particular “crucial block of code” from multiple threads; it maintains memory consistency. The keyword is synchronized. Don’t forget that constructors cannot be synchronized (you’d get a syntax error) because it’d be worthless; a constructor is accessed only by the single thread that created it.

{mospagebreak title=Conclusion}

As I promised, I won’t finish this two-part series without enumerating a few of the features that are missing from Java but present in C. Dozens of features were intentionally “left out” from Java. Let’s name a few: structs, unions, friend functions, and so forth. There are well-rationalized reasons for not implementing these.

Needless to say, in most cases there are other, better ways to accomplish the same algorithmic requirements that are safer and more robust. Java focuses mostly on maintaining portability and enhanced security. Therefore, many of the features that allowed programmers to create “havoc” either by mistake or design were removed.

Hopefully I’ve pointed out enough distinctions between Java and C/C++ for you to get excited about. It certainly isn’t a hard language; many experienced coders or even newcomers have a positive attitude toward Java — some go so far as to cheer “It’s fun!”

If you currently have experience with C and/or C++ then picking up Java won’t be hard. All you need to do is actually get familiar with its particular class-like inner workings and practice — a lot! Within a few days you could find yourself porting your favorite source codes into Java just for the sake of it.

Java, as a programming language, was created to help programmers. Its main purpose therefore is to assist programmers to code with ease while maintaining a very high level of portability. As a result, Java is a very powerful and useful language.

Nevertheless, it is not suited for all kinds of applications. We shouldn’t forget that Java is half-interpreted. Moreover, coding something in Java does not always result in an efficient way of programming that specific application. With C/C++ you also have more permission to access the system’s resources (i.e., direct memory access) and significantly faster execution speed. By no means should C++ be tossed out or forgotten.

Java is not a replacement or one-does-it-all programming language. It’s really useful to be familiar with it and use it for well-thought-out specific purposes; it also looks good on a resume or CV. From time to time you might run into projects that would work more efficiently when coded in C++; these are the cases when you should leave Java alone. Forcing a particular language on a project it does not fit won’t work well at all.

With these things said, I am now ending this series. I truly believe that you could extract valuable information from it; that would mean it has served its purpose well.

Don’t ever forget — learn, practice, and practice. It’s simple: keep coding!

Google+ Comments

Google+ Comments