The last time we looked at C# vs. Java, we focused on the respective languages’ performance. This time we're going to look at yet another aspect of the languages: the runtime libraries—what exactly the libraries are, how they are called, and what features the languages provide for calling into them. The APIs aren't built into the languages themselves, but are libraries of classes compiled down to bytecode. You can actually use any number of languages that target the runtimes. Most people targeting Microsoft's Common Language Runtime (CLR) and its .NET framework use C#, but some use Visual Basic.NET or F# or IronPython. There are even implementations of Java that target .NET. Further, there are multiple implementations of the common language runtime; Microsoft started it with their own, but the Mono Project has created an open-source version that runs on Linux and Windows. The Java Virtual Machine is a separate runtime, with its most common language being Java. But you can use other languages in a similar way. For example, Scala is a language that is becoming popular. Other languages include Jython (an implementation of Python), JRuby, and Clojure. And similarly, Sun (now Oracle) has provided Java with a large library of classes in the form of an API. The APIs are really just code written in different languages and compiled to target the CLR or the JVM. The most common API for the CLR is Microsoft's .NET framework. Other independent third parties have released different APIs for both platforms. But here we're looking at the official Java API now owned by Oracle, as well as the official .NET API owned by Microsoft.

Huge Libraries

When Java first appeared two decades ago, it was a welcome relief to many of us who were tired of having to write low-level code in C or C++ to accomplish everyday programming tasks. C++ has evolved and matured considerably since then; but at the time, it was a bit of a nightmare to code even simple tasks. A string type wasn't built into the language, and instead you had to deal with pointers to characters and some third-party libraries that implemented string and other classes. Higher-level tasks in C++, such as connecting to a Web server and pulling down a Webpage, caused a lot of premature baldness. (The Web was still new, of course, but TCP/IP connections weren't.) Then Java came along and everything became so much easier. If you needed to pull text data from a remote server, it was easy to make the connection, open a string-stream, and pull the text down into a variable. A string type was built into the language, as well, so once you saved the text into a string variable, you could easily manipulate it without having to fight with third-party libraries. Of course, this meant using built-in features of the language such as a string type, and the huge API library that wasn't actually part of the language itself, but was nevertheless present and powerful. Then along came Microsoft's response to Java: C#. C# was the brainchild of a man named Anders Hejlsberg, who had previously given us Borland's Delphi and its speedy TurboPascal compiler. C# looked very similar in syntax to Java (and some have speculated that it was originally going to be an implementation of Java). Since then, both languages have evolved independently. But both include huge APIs. Just as Java started out with some powerful libraries that made programming far easier, the .NET library also had a huge number of features. Both libraries are also broken down using namespaces or packages. For example, the Java regular expression classes live in the package called java.util.regex, while in .NET, regular expressions live in the namespace called System.Text.RegularExpressions. Knowing this, we can see a pretty clear overview of the different types of classes available. In terms of direct comparison, both libraries contain the essential features modern programmers require. If your code needs to pull down a Web page from a remote server, you can do it with just a couple lines of code in either language. If you need to create a Web server, again, you can create a minimal one in a few lines of code. It would be silly to attempt a direct feature-by-feature comparison between the APIs—not just because the existing APIs are so complete, but because third parties have filled in any gaps between features. (Examples there would be ZIP and PDF libraries.) Both APIs provide classes and packages for features such as:
  • Desktop applications, including window management, and creating control
  • Server-side applications
  • Connectivity – direct connections, SOAP, and so on.
  • Database access
  • Language reflection
  • I/O (files, streams, and so on)
  • Security
  • Cryptography
  • Imaging, Drawing, and Graphics
  • Text processing
  • XML processing
  • Printing
  • Collections and containers (e.g. Linked lists, stacks, queues, and so on)
Additionally, there are mobile versions of the libraries. Java exists on Android phones, and Microsoft has .NET available on their Windows phones.

Calling into APIs

From a coding level, the approach to calling into the APIs depends largely on the language at hand. With Java, the usual approach is to create an instance of a class, and then call that instance's member functions. Often (especially when dealing with streams) you'll create an instance of once class, and pass that instance to another class to create a second instance that provides additional capabilities over the first class. In the .NET world, many of the API classes work the same way, whereby you create an instance of a class and then call the instance's members. However, another common practice in .NET is to provide a class with static functions that you can call directly without needing to create an instance first. While this is possible in Java as well, the API doesn't use this approach as much as it's used in .NET. Different people have different feelings about whether static functions are good or bad, but it's largely subjective. One interesting aspect is how exceptions are handled. Java has a reputation of forcing users to wrap code heavily around try/catch blocks. Of course, this isn't necessarily a bad thing, because C# code doesn't make this requirement, and if unexpected errors occur, the C# app can crash and immediately shut down, leaving the user wondering what on earth happened. The C# language itself includes a keyword called using, which allows you to call into an API function, and be assured that at the end of your block of code, the API will do any necessary cleanups, such as closing stream connections. This is optional; you're not required to use it, but it makes life a little easier, taking care of cleanups so you don't have to. Until recently, Java didn't have anything similar. In Java, the typical approach was to include a “finally” block after your try/catch blocks to handle any cleanups. Java version 7 release 6 now includes a feature called “Automatic Resource Management,” which allows for auto-closeable classes. Using this feature, the objects you're using can clean up themselves without you having to worry about it. (Note that in C# with the using statement, and in Java with the auto-closeable classes, you can also create your own classes that implement the cleanup features, and then use them accordingly. These features don't only exist in the APIs.)

Language-Specifics and API calls

Although the APIs operating independently of the languages, there are some interesting tidbits included in both languages that give you direct access to the APIs through the language syntax itself, without requiring you to use the traditional approach of creating an instance of a class and calling the instance's methods. Value Types The CLR supports the creation of custom value types that can be passed into functions completely by value, instead of passing a pointer or reference to the object. The JVM, however, does not have this support. The JVM only supports value types on its atomic types. However, there is ongoing research at Oracle to add support for custom value types. There are arguments about why this would be a good thing, but there are also arguments about why it's not really necessary. Most of the arguments for it come down to performance. There are researchers at Oracle looking into adding value types to Java in the future. But whether they do or not, you can still accomplish the same tasks, just with a little bit of different programming. So the lack of custom value types in Java really doesn't mean it's any less of a language and shouldn't be used. Properties The C# language includes a feature called properties. Really, it's just a syntax wrapper around setters and getters, allowing you to call functions but use a syntax like you're setting or getting a member variable's value, like this:

myobj.width = 10

Generally speaking, the API makes use of properties in the case where you supply a class or object; but the classes in the API typically don't make use of properties. And really, it's just quick syntax. Frankly, there's little benefit to that line I just showed you over this:
myobj.setwidth(10);
Data Access Microsoft has spent a lot of time putting together a technology they call LINQ for easily accessing data in a manner similar to SQL. LINQ support is built right into the C# language, although under the hood ultimately you're calling into functions in the API. Anecdotally speaking, most people I've worked with and met who code in C# seem to like it, and find the performance to be good. The syntax looks like this:
var results = from p in db.Employee

        where p.department == "IT"

        select p;

The “var” keyword was added at the same time as LINQ, because the actual type you get back from this type of call is sometimes complex. The compiler will figure out the type and internally create the results variable with the correct type. It's just a shorthand, really. Under the hood, of course, this code is still calling into the API functions. If you prefer, you can rewrite this code making function calls. Java doesn't really have an analogy to the LINQ syntax; however, the data access APIs are complete, and you can effectively accomplish the same thing. But what's interesting is there are Java libraries people have put together that do allow you to make calls similar to the function version in C#. Regular Expressions While we're talking specifically about the Java and C# languages apart from the API, I wanted to mention that both APIs have strong support for Regular Expressions. However, neither language supports regular expressions directly. Perl is probably the best example of regular expressions are integrated right into the language. Accessing the regular expressions from Java and C# is relatively easy in that you can access them as you would any other API calls. But in my humble opinion, I would like to see both languages include regular expressions directly. (But I do admit that it's really just syntax sugar, considering it's easy to create a new regular expression object and call its methods.) In Perl, you can easily test whether a string matches a pattern, or if a string contains a pattern, like so:
if ($name =~ m/slashdot/) { print "slashdot!"; }
But that said, Java does have regular expression support built right into the string type. This allows you to perform occasional regular expressions with a very small amount of code where it's not necessary to compile your regular expressions. In other words, the performance isn't the best—but if you only need one here and there, this will do the job. Otherwise you can call into the framework and get access to compiled regular expressions. The regular expression libraries in both cases are quite complete. The .NET framework's regular expression classes are a bit odd, as Microsoft, as usual, has taken some freedoms to expand on the more common regular expression engines. However, you can for the most part use the popular Perl-style regular expressions for your patterns in the .NET framework. Templates and Generics Programmers often need to place items in a container, while maintaining strong typing. For example, you might want to create a linked list that can only hold instances of a class you created. C++ gave us the concept of templates, which allows for this parameterized typing. C# added a templating mechanism of sorts, except one important difference is the resulting types based on the templates in C++ are created at compile time, whereas in C#, the CLR creates the types at runtime. But conceptually, they work similarly, even with similar syntax. In C#, the term used is “generic.” Using generics in C#, you can make use of the container classes in the API, allowing for strong typing. And even though the mechanism operates at runtime, strong type checking takes place at compile time, preventing you from inserting, for example, an integer into a list declared to hold strings. Shortly before C# was given Generics, Java was given a mechanism that is almost identical, allowing for a similar purpose when dealing with container classes. Here's an example of a Java line of code that is basically the same as what you would find in C#:
List<String> list = new ArrayList<String>();
Java, however, uses a method called type erasure. Essentially, the type checking only happens at compile time. The actual container types internally could still hold any type, but the compiler explicitly stops you from attempting to put other types into the containers. The end result is that in C# you can use type reflection at runtime to determine the type that the class holds. Is this even useful? It is in niche situations, such as if you need to build a JSON representation at runtime of an object and you want to accept generic container classes. You can use reflection to determine the type. If the type of the container had been erased and is no longer present at runtime, you would have to manually check the objects in the container. In other words, you can still accomplish the same tasks, whether you're using Java or C#; you would just take different approaches.

Conclusion

The languages provide some powerful ways to call into the APIs. The APIs themselves are complete and offer the essential tools for modern software development. The languages differ on what features they provide for calling into the APIs; for example, Microsoft has its LINQ technology. Further, Microsoft makes more liberal use of static members. Both languages now allow for automatic resource management, and both languages support parameterized types called generics. The APIs are complete. So is one better than the other? I would call it a tie.   Image: Jeff Wasserman/Shutterstock.com