Java has been a mainstay for connecting legacy enterprise systems to highly dynamic web interfaces, giving it broad use in the enterprise world. It has the backing of a lot of major corporations and is heavily used in their stack. Companies that use Java include:
The Developer’s Perspective
Compiled vs. Interpreted
This is an important nuance of the language that has sizable amount of implications for developers. In the olden days, interpreted language meant slower performance, which is (for the most part) no longer the case. But performance aside, there is one essential distinction in the workflow when code is run and tested.
Compiled languages like Java will check the code of an entire project while optimizing and converting scribbles into byte code that can be read by the Java Virtual Machine (JVM) at a later date. It will catch a healthy amount of syntactical errors and alert coders to that effect at the compile time. From that point on, the coder will be operating with a compressed package of byte codes like Java Archive (JAR) or Web Archive (WAR) in case of a web application. This package then can be executed by a virtual machine or a web container that will open it, load it in memory, find an entry point, and bring it to live on somebody’s desktop or server. This does not prevent you from making programming logic errors, but at the very least you have an opportunity to correct all of the syntactical errors right out of the gate.
Security of the intellectual property is also an issue that is solved by many compiled languages. Java compilation does not intrinsically protect your code from decompilation, but there are ways of protecting your output outlined in various resources on the Internet.
As for security of intellectual property, there is really no good way to obfuscate or encrypt your code well enough to make it executable yet inaccessible. This applies specifically to anything you would deploy to users’ computer or run in a web browser. There are “minifiers,” “uglyfiers” and other obfuscation packages, but none of them will scramble your code enough to be ultimately unreadable. The reason for it is that your code needs to be readable in its original form by the interpreter at the time of execution. So while the obfuscation package can get rid of all spaces, carriage returns and tabs, turn local scope variables to one character names and generally make it look like a chunk of mess, it has to keep a lot of original elements in.
Strongly Typed vs. Dynamically Typed
Java – a strongly typed language – locks all of its variables into a particular type. If you define an object of a particular type or create a variable of a set primitive type, that variable is locked into its identity. You will know about any mismatches at compile time. You will not be able to produce byte codes or execute your code until you fix the issue. There is limited flexibility in this matter achieved through polymorphism and every class being automatically derived from an ominous Object class. That is still however very restrictive and a subject for a different conversation. There is a lot of value in this constraint as it forces good coding habits and requires that intentions align throughout any Java project.
The possible negative to this language feature is a good deal of ceremony around strong typing. Since new public methods and properties for any object need to be a part of a public interface you often have to define those elements throughout the inheritance tree. This complicates expansion of various object definitions throughout the development process. This makes prototyping harder and potentially slows down rapid development at the early stages of product creation.
Object Oriented Programming
Java has its own, albeit limited, answer to functional programming. Java introduces lambdas in Java 1.8 (“Java 8”), which are a great powerful way to filter and manipulate collections of data. That being said the applicability of lambdas is very much restricted to data manipulation and does not step much beyond that.
Libraries and Frameworks
Many languages are defined by the suite of libraries that are available for them. Those libraries make or break the language, no matter the capabilities. The most elaborate, flexible and well thought-out language in the world pales in comparison to a language with wide support and braintrust.
In addition to library support, Integrated Development Environments (IDEs) can make or break the language. A good IDE helps developers to rapidly traverse through the code base. It also has to have helpful assistants like Intellisense (inline lookup similar to Google suggested search terms), context highlighting, error highlighting (underline code that needs correction before it is compiled or sent for interpretation), and refactor assist tools.
Java has a good plethora of offerings such as Eclipse, NetBeans, and IntelliJ IDEA. Some of the tools are free while others are reasonably priced for the value that they offer. Just like Java, all of these tools run on a variety of platforms.
Java sports a great deal of tools – many well-integrated with IDEs – which is great for test development. JUnit is one of those frameworks. You can review individual test results in a dedicated window in an IDE of your choice, and you can click through and debug each individual unit test. If configured with Maven, the system will also run all of your unit tests each time you compile your project.
Build and Delivery Automation
This toolset mostly comes at the final stages of software development cycle. It is of interest to developers as it governs portability of the code base between computers of various developers on the team as well as continuous testing and delivery of the software in the test and production environments.
On the Java side, Maven will perform most of the aforementioned things. Maven integrates with most Java IDEs and makes developer’s lives considerably easier.
As for development and production server delivery, the majority of Continuous Integration tools will support both stacks seamlessly.