Thu 08 Mar 2018 — Sun 11 Mar 2018

Java

These notes are about newish features in Java, not the basics.

Unsigned integer arithmetic

While there aren't any unsigned types built into Java, you can use the signed integer and long types as if they were.

You can use add, multiply and subtract unsigned numbers safely as normal. The Integer and Long classes contain static functions to handle unsigned division:

  • divideUnsigned()
  • remainderUnsigned()

And also some useful utility functions for the same:

  • compareUnsigned()
  • toUnsignedString()
  • parseUnsigned()

Floats and doubles don't do unsigned arithmetic.

Type inference

Java 7 added the automatic inference of generics by writing <> instead of <A, B, C>.

Java 10 will add var from C#.

Dates and Times

There are three Java date and time libraries of consequence:

Original standard library
deprecated
Joda Time
I usually use this
New standard library
I don't like it. Too complicated and poorly documented. Probably the right thing to use if you have complicated timezone issues.

IO

Originally, Java used subclasses of Stream to provide blocking IO. This might still be the best approach if you just want to read from or write to one place synchronously.

NIO lets you do non-blocking IO with interrups. It has helpers for combining multiple data sources or sinks.

Core NIO classes:

Buffer
a chunk of memory with a data type.
  • Can be in read or write mode — switch between these using .flip().
  • In between re-using write mode you also need to call .clear() or .compact(). The latter is useful if you still want to read some of the data from the previous write.
Channel
move data from buffers.
Selector
multiplexes channels. Lets you wait for the next one to become available.
Pipe
send messages from one thread to another

NIO also provides Path, Paths and Files, which replace File and are usually more convenient.

Try-Catch

Java 7 added a couple of nice features to try-catch blocks:

  • Multiple exception types in one catch block.
  • Try-with-resources and AutoCloseable interface.
try (
     // This is a try-with-resource style for when we have things
     // other than memory which we want to live with block scope.
     AutoCloseable thing = new AutoCloseable(){}
     ){

    // Your actual logic goes here.

} catch (ExceptionType one | ExceptionType two) {
    // Some code because we've had one of the two kinds of error listed.

} catch (ExceptionType three) {
    // Some different code because we've had a different kind of error.

} finally {
    // Anything you write here always happens, whether or not.
    // AutoCloseable.close() is called here.
}

Interface methods

Also called virtual extension methods or default methods.

You define a method in an interface, but write the word default immediately before the return type.

Your interface still isn't allowed to have any state in it.

Despite the name, they aren't the same as C# extension methods, which are syntactic sugar for calling static functions.

Functional Programming

Java has a couple of different ways of writing anonymous functions. You can make an interface with only one method (a functor) and implement it as an anonymous inner class. You can also create a lambda using the arrow (->) syntax :

(TypeOne argOne, TypeTwo argTwo) -> doSomethingTo(argOne, argTwo)

Lambdas in Java still need an interface to inherit from. It provides some standard interfaces:

Predicate<InputType>
Function<InputType,ResultType>

Streams

These are a rubbish version of Linq from .NET.

You can call .stream() or .parallelStream() on any collection to get a stream object. Alternatively, call Stream.of(el, el, el).

To get back from a stream to an object, call .collect(Collectors.someThing()).

There are special streams to work on primitive types.

You can do .map(transformElement), .filter(includeElement?) and so on to a stream.

As with Linq, streams are lazy. You may sometimes need to force evaluation, for example to make sure you fetch all your results from a database query before you close the connection.

There's a class Supplier which provides streams. This is useful if you need to iterate over the same collection multiple times.

Immutable Data Structures

There have been Java libraries that provide immutable collections for a while (for example: Guava). Java now has some of its own.

List, Set and Map all have some functions to create these for us. Here are the examples for List:

List.of(el, el, el)
static function
List.copyOf(coll)
static function
toUnmodifiableList()
instance method

Modules

Modules are a replacement for making libraries available by putting them on the classpath.

Motivations:

  • Less chance of stupid diamond dependency problems on the classpath.
  • Build a smaller version of the JVM (or some big framework) which doesn't include all the modules.
  • Less easy to use sneaky reflection to get access to things you shouldn't be able to.
  • Things that you declare public are only public inside that module, or if you deliberately export them.

A module requires some types from other modules, and exports some types of its own. You usually define it in a module-info.java file:

module a.b.c {
    requires x.y.z;
    requires public u.v.w; // Also re-exports u.v.w
    exports a.b.c.c1;
    exports a.b.c.c2;
}

Modules form a dependency graph. Only one version of each dependency exists in the output.

The Java standard library has been rewritten using modules. View them with java --list-modules. Examine one with java --describe-module some.module.

The jlink command introduces a link phase which is between compile and run.

JMOD files are an alternative to JAR files. They can additionally include statically linked native code (C or C++) and configuration files. They can't be run directly. You could use them to distribute a library, and then the consumer of that library would use jlink to include what they need from your JMOD file into their JAR.