This training course walks you through many of the commonly used Java programming techniques such as autoboxing and unboxing. We’ll also cover several of the SDK base libraries and utility classes for working with Java primitives, Strings and DateTimes, etc.
Learning Objectives
- Understand what wrapper classes are and when to use them
- Be able to explain autoboxing and unboxing
- Be able to work with and define enumerations
- Make use of static imports
- Explain the core DateTime classes
- Modify and format DateTime values
- Work with time zone information
- Format Strings using the formatter syntax
- And be able to confidently use System.out and System.format to print out strings
Prerequisites
- A basic understanding of software development
- A basic understanding of the software development life cycle
Intended Audience
- Software Engineers interested in learning Java to develop applications
- Software Architects interested in learning Java to design applications
- Anyone interested in basic Java application development and associated tooling
- Anyone interested in understanding the basics of the Java SDK
- [Instructor] Okay, welcome back. In this lecture, we'll explore several of the Java utility classes and related techniques. We'll cover items such as an introduction to the Wrapper Classes. We'll explain Autoboxing and Unboxing. We'll go through converting string representations of primitive numbers into their corresponding wrappers, converting string representation of primitive numbers into their primitive types. We'll go through defining enumerations, and finally, we'll show you static imports. There are many times when a primitive isn't adequate. The Java language provides wrapper classes that wrap the primitive up into a real object. It still holds the primitive within but now has all of the characteristics of an object plus a host of methods that can act on the primitive. Wrapper classes have been defined for each primitive: integer, long, short, double, float, byte, Boolean, and character. Wrapper classes serve two primary purposes. They allow primitives to be wrapped into object types, and they provide conversions to and from other types. Any time you need to convert from a string into the appropriate corresponding type, use the pass-x method, where x is the appropriate type. These are static methods, so they can be invoked without having to instantiate a wrapper class. All the pass methods throw a Number Format Exception if the string does not hold a valid number. This is an unchecked exception, and the code will compile without it. However, due to the potential for number formatting exceptions, you should always perform these operations within a try-catch block to more gracefully handle such errors. Autoboxing is the conversion process that Java uses at compile time to convert a primitive type into its corresponding object type using the correct object wrapper classes. Why and when would autoboxing be used? Well, as seen here in the example, the list interface has an add method which takes a single input of type object.
With autoboxing, you can simply pass the primitive in and have the compiler perform the conversion for you at compile time. Again, autoboxing is simply leveraging the compiler to convert from the primitive to its respective object wrapper class. That is an Int is converted into integer, or a double becomes a double and so on. If the conversion goes the other way, this is called unboxing. When working with autoboxing and unboxing, consider the following things. Objects are not primitives. Trying to unbox a null results in a Null Pointer Exception at runtime. There is a performance penalty due to the creation and garbage collection of objects. It can be fast but should not be used in places where performance is critical. And finally, use autoboxing and unboxing wisely. Use it when an object is required but only a primitive is available, and do not use it in calculation or performance-sensitive code. Anyone who has tried to do precise arithmetic with a floating point type will realize the value of the big decimal type. You can precisely calculate any precision you desire. Big decimal is especially useful with SQL databases. Big decimal provides precise control over operations with decimal points. It extends number, and note that arithmetic operations do not get affected by the original object. Enumerations. APIs often rely on a set predefined constants. For example days of the week, suits within a deck of cards. Legacy APIs rely on the Constant Interface Pattern. The Constant Interface Pattern's biggest problem was type safety, because the constants were primitives it was difficult to guarantee their use. As you can see in this example, the get coffee method has an input parameter of type Int. Meaning that you can pass in any valid Int to the method which has the potential to break the contract of the coffee size interface. In Java 5, the Enum keyword was introduced. Besides classes and interfaces, developers can now develop class files containing enumeration definitions. Java enumerations are full implementations of classes as we'll see during this lecture. The example shown here, shows the simplest form of a Java enumeration, a comma-separated list of enumeration values. Enumerations can also be used within switch statements, as the example shows.
When a switch is defined on a variable of Enum type, all case statements must be defined using one of the valid values of the Enum type on which the switch takes place. All Java enumerations implicitly extend the Java.lang.Enum class. As a result, a Java Enum cannot extend other classes or enumerations. However it is possible for an Enum to implement one or more interfaces. Every enumeration has predefined convenience methods. The values method, returns an array of all the valid Enum values. By using the value of method, a string value can be converted into an Enum value. The string value must be exactly the name of the Enum value otherwise an exception is thrown. Enumerations cannot be instantiated using the new keyword, however it is possible to define additional methods in the Enum class of override methods like to string for example. The example shown here shows a more complex enumeration. An Enum can have a constructor, that accepts parameters. However, the access modifier must be either private or default. When defining possible Enum values, each value must invoke the constructor of this Enum. In other words, all parameter values of the constructor must be specified when defining Enum values. The constructor parameters become instance variables of Enum which can be read using the getter methods as shown by the second code example. Enumerations are a better class type than the constant interface pattern in the type safe Enum pattern shown earlier. Enumerations can contain constructors, state and behavior just like other classes. With the exception that the constructor of an Enum must be declared as private or default. Enumerations can implement interfaces but cannot extend other classes as already discussed because they implicitly extend Java.lang.Enum. By default, an enumeration implements the serializable and comparable interfaces.
Until the introduction of static imports, referencing static fields or methods of another class could only be accomplished by referencing the field or method using the class name of the class on which the field or method was defined. In order to make code more readable, static imports were introduced in Java 5. Just like importing other classes in order to make sure that developers would not have to reference other classes using their fully qualified name, static imports can be used to allow developers to reference static fields and methods without having to define the fully qualified class name of the class on which the static field or method is defined. Static fields or methods can be imported using import static followed by the fully qualified name of the class on which the feudal method is defined, followed by an Asterix to import all static members of a class. As the example shows here, once the static import has been added the static members of the other class can now be used without the prefix. Instead of importing all static members of a class using the Asterix notation, developers can choose to import only one specific static field of a class. In the example here, only the static field is imported, as a result is no longer possible to invoke, for example, the static get age method. When only a static method is to be imported, the input should contain only the method name without parentheses. In the second example, only the static method is imported. As a result the static field is no longer recognized. In general, having a large number of static methods is an indication that the code is becoming more procedural instead of object orientated. So having a lot of static imports is often a bad sign. Also, code tints become more difficult to read when methods and variables which are reference are not declared in the enclosing class. You should therefore be very careful when using a lot of static imports in your code. The code example shown here, uses the calendar class. The implementation of the calendar class relies heavily on the static fields that are defined within the calendar class. This is one example where using static imports of these fields might make your code easier to read. Okay and consider the following questions to test yourself on the content that we've just reviewed. The answers to the above questions are: one, the wrapper classes allow primitive values to be passed unto methods that require object types. Two, yes all of the primitive wrappers support string parsing. Three, constructors and methods can be used within enumerations in the same way as a normal class except that the Constructors cannot be declared public or protected. Four, enumerations are concrete classes. Five, the static values method returns an array of Enums from the current enumeration type. Six, private data can be defined in an enumeration. Seven, enumerations implicitly implement serializable and comparable interfaces. Eight, static imports are defined using the static keyword after the import keyword in the import section outside of the class or interface definition. Okay that completes this lecture, go ahead and close it and we'll see you shortly in the next one.
Jeremy is a Content Lead Architect and DevOps SME here at Cloud Academy where he specializes in developing DevOps technical training documentation.
He has a strong background in software engineering, and has been coding with various languages, frameworks, and systems for the past 25+ years. In recent times, Jeremy has been focused on DevOps, Cloud (AWS, Azure, GCP), Security, Kubernetes, and Machine Learning.
Jeremy holds professional certifications for AWS, Azure, GCP, Terraform, Kubernetes (CKA, CKAD, CKS).