Book Image

Java Projects - Second Edition

By : Peter Verhas
Book Image

Java Projects - Second Edition

By: Peter Verhas

Overview of this book

Java is one of the most commonly used software languages by programmers and developers. In this book, you’ll learn the new features of Java 11 quickly and experience a simple and powerful approach to software development. You’ll see how to use the Java runtime tools, understand the Java environment, and create a simple namesorting Java application. Further on, you'll learn about advanced technologies that Java delivers, such as web programming and parallel computing, and will develop a mastermind game. Moving on, we provide more simple examples, to build a foundation before diving into some complex data structure problems that will solidify your Java 11 skills. With a special focus on the features of new projects: Project Valhalla, Project Panama, Project Amber, and Project Loom, this book will help you get employed as a top-notch Java developer. By the end of the book, you’ll have a firm foundation to continue your journey toward becoming a professional Java developer.
Table of Contents (12 chapters)

Getting started with Java

It is like going through a path in a forest. You can focus on the gravel of the road, but it is pointless. Instead, you can enjoy the view, the trees, the birds, and the environment around you, which is more enjoyable. This book is similar, as I won't be focusing only on the language. From time to time, I will cover topics that are close to the road and will give you some overview and directions on where you can go after you finish this book. I will not only teach you the language but also talk a bit about algorithms, object-oriented programming principles, tools that surround Java development, and how professionals work. This will be mixed with the coding examples that we will follow. Lastly, the final chapter will be fully devoted to the topic, what to learn next, and how to go further to become a professional Java developer.

By the time this book gets into print, Java will have completed 22 years (http://www.oracle.com/technetwork/java/javase/overview/javahistory-index-198355.html). The language has changed a lot during this period and got better. The real question to ask is not how long it has been here, but how long will it stay? Is it still worth learning this language? There are numerous new languages that have been developed since Java was born (http://blog.takipi.com/java-vs-net-vs-python-vs-ruby-vs-node-js-who-reigns-the-job-market/). These languages are more modern and have functional programming features, which, by the way, Java has also had since version 8. Many say that Java is the past—the future is Scala, Swift, Go, Kotlin, JavaScript, and so on. You can add many other languages to this list, and for each, you can find a blog article that celebrates the burial of Java. There are two answers to this concern: one is a pragmatic business approach, and the other is more regarding engineering:

  • Considering that COBOL is still actively used in the finance industry and COBOL developers are perhaps better paid than Java developers, it is not too risky to say that, as a Java developer, you will find positions in the next 40 years. Personally, I would bet more than 100 years, but considering my age, it will not be fair predicting more than 20 to 40 years ahead.
  • Java is not only a language, it is also a technology that you will learn a bit about from this book. The technology includes the Java Virtual Machine (JVM), which is usually referred to as JVM, and gives the runtime environment for many languages; Kotlin and Scala, for example, cannot run without JVM. Even if Java will be adumbrated, JVM will still be a number one player in the enterprise scene.

To understand and learn the basic operation of JVM is almost as important as the language itself. Java is a compiled and interpreted language. It is a special beast that forges the best of both worlds. Before Java, there were interpreted and compiled languages.

Interpreted languages are read from the source code by the interpreter, and then the interpreter executes the code. In each of these languages, there is some preliminary lexical and syntax analysis steps; however, after that, the interpreter, which, as a program itself, is executed by the processor, and the interpreter continuously interprets the program code to know what to do. Compiled languages are different. In such a case, the source code is compiled to binary (.exe file on Windows platforms), which the operating system loads and the processor directly executes. Compiled programs usually run faster, but there is usually a slower compilation phase that may make the development slower, and the execution environment is not so flexible. Java combined the two approaches.

To execute a Java program, the Java source code has to be compiled to the JVM bytecode (.class file), which is loaded by JVM and is interpreted or compiled. Hmm…is it interpreted or compiled? The thing that came with Java is the Just in Time (JIT) compiler. This makes the phase of the compilation that is calculation-intensive and the compilation for compiled languages relatively slow. JVM first starts to interpret the Java bytecode and, while doing that, it keeps track of execution statistics. When it gathers enough statistics about code executions, it compiles to native code (for example, x86 code on an Intel/AMD platform) for direct execution of the parts of the code that are executed frequently and keeps interpreting the code fragments that are rarely used. After all, why waste expensive CPU time to compile some code that is hardly ever used? (For example, code that reads configuration during startup and does not execute again unless the application server is restarted.) Compilation to the bytecode is fast, and code generation is done only for the segments that pay off.

It is also interesting that JIT uses the statistics of the code execution to optimize the code. If, for example, it can see that some conditional branch is executed in 99% of the cases and the other branch is executed only in 1%, it will generate native code that runs fast, thus favoring the frequent branch. If the behavior of that part of the program changes by time and the statistic shows that the ratios changed, the JIT automatically recompiles the bytecode from time to time. This is all automatic and behind the scenes.

In addition to the automatic compilation, there is also an extremely important feature of JVM—it manages the memory for the Java program. The execution environment of modern languages does that, and Java was the first mainstream language that had an automatic garbage collection (GC). Before Java, I was programming in C for 20 years, and it was a great pain to keep track of all memory allocation and not to forget to release the memory when the program no longer needed it. Forget memory allocation at a single point in the code, and the long-running program eats up all memory slowly. Such problems practically ceased to exist in Java. There is a price that we have to pay for it—GC needs processor capacity and some extra memory, but that is something we are not short of in most of the enterprise applications. Some special programs, like real-time embedded systems that control the brakes of a heavy-duty lorry, may not have that luxury.

Those are still programmed in assembly or C. For the rest of us, we have Java, and though it may seem strange for many professionals, even almost-real-time programs, such as high-frequency trading applications, are written in Java.

These applications connect through the network to the stock exchange, and they sell and buy stock responding to market changes in milliseconds. Java is capable of doing that. The runtime environment of Java that you will need to execute a compiled Java code, which also includes the JVM itself, contains code that lets Java programs access the network, files on disks, and other resources. To do this, the runtime contains high-level classes that the code can instantiate, execute, and which do the low-level jobs. You will also do this. It means that the actual Java code does not need to handle IP packets, TCP connections, or even HTTP handling when it wants to use or provide a REST service in some microservices architecture. It is already implemented in the runtime libraries, and all the application programmer has to do is include the classes in the code and use the APIs they provide on an abstraction level that matches the program. When you program in Java, you can focus on the actual problem you want to solve, which is the business code and not the low-level system code. If it is not in the standard library, you will find it in some product in some external library, and it is also very probable that you will find an open source solution for the problem.

This is also a strong point of Java. There are a vast number of open source libraries available for all the different purposes. If you cannot find a library fitting your problem and you start to code some low-level code, then you are probably doing something wrong. There are topics in this book that are important, such as class loaders or reflection, not because you have to use them every day but because they are used by frameworks, and knowing them helps you understand how these frameworks work. If you cannot solve your problem without using reflection or writing your own class loader or program multithread directly, then you probably chose the wrong framework. There is almost certainly a good one; Apache project, Google, and many other important players in the software industry publish their Java libraries as open source.

This is also true for multithread programming. Java is a multithread programming environment from the very beginning. The JVM and the runtime support programs that execute the code. The execution runs parallel on multiple threads. There are runtime language constructs that support the parallel execution of programs. Some of these constructs are very low level, and others are at a high abstraction level. Multithread code utilizes the multicore processors, which are more effective. These processors are more and more common. 20 years ago, only high-end servers had multiple processors and only Digital Alpha processors had 64-bit architecture and CPU clock above 100 MHz. 10 years ago, a multiprocessor structure was common on the server side, and about 5 years ago, multicore processors were on some desktops and on notebooks; today, even mobile phones have them. When Java was started in 1995, the geniuses who created it had seen this future.

They envisioned Java to be a write once, run anywhere language. At that time, the first target for the language was applet running in the browser. Today, many think (and I also share this opinion) that applets were a wrong target, or at least things were not done in the right way. As of now, you will meet applets on the internet less frequently than Flash applications or dinosaurs. What's more, the applet interface was deprecated already in Java 9, creating the opinion that applets are not good officially.

However, at the same time, the Java interpreter was also executing server and client applications without any browser. Furthermore, as the language and the executing environment developed, these application areas became more and more relevant. Today, the main use of Java is enterprise computing and mobile applications mainly for the Android platform. For the future, the use of the environment is growing in embedded systems as the Internet of things (IoT) comes more and more into the picture.

Version numbers

Java versioning is constantly changing. It does not only mean that the version numbers are changing from one release to the other. That is kind of obvious; that is what version numbers are for, after all. In the case of Java, however, the structure of the version numbers is also changing. Java started with version 1.0 (surprise!) and then version 1.1 shortly followed. The next release was 1.2, and it was so much different from the previous versions that people started calling it Java 2. Then, we had Java 1.3 till Java 1.8. This was a stable period as far as we consider the structure of the version number. However, the next Java version was named Java 9 instead of 1.9 last year, in 2017. It makes sense, because after 22 years of development and nine releases, the 1. part of the version number did not really make much sense. Nobody was expecting a "real" Java 2.0 that is so much different from any other releases that it deserved the 2. version prefix. In reality, the Java versions were really 1, 2, 3 and so on; they were just named as 1.1, 1.2, 1.3, and so on.

You could expect that after this huge change in the release number format, the next release of Java would be Java 10. Not at all. Oracle decided to use date-based release numbers. The first part of the release number before the dot will be the two digit year, like 18 for versions released in 2018. The part after the dot is the number of the month, usually 3 for March and 9 for September. Thus, when you look at Java version number 18.3, you immediately know that this version was released March 2018, which is actually Java 10 when following the old nomenclature.