Working with SI units in Java

Dr. Viktor Sirotin
CodeX
Published in
4 min readJul 20, 2023
The SI system and the relationships between units of physical quantities.

The KotUniL library, originally developed in Kotlin has recently become cross-platform. Specifically, it is now available in JavaScript, as discussed here.

But why is this library needed?

When programming in a traditional way, it is easy to overlook the units of measurement associated with the numbers we operate on. For example, you could add meters to liters, and the compiler wouldn’t help us in this case. This is a real problem that has already led to accidents costing millions of dollars (one of the stories is mentioned here). To avoid such issues, special libraries that handle physical units in the SI system, such as meters or watts, as well as other units like currencies or items, can be utilized. One such library is KotUniL (si-units).

Using Kotlin Multiplatform technology allows obtaining code for a wide range of platforms, including JVM, from Kotlin code. Consequently, the functionality provided by the library can be used in Java programs as well. Although achieving this could be possible without using Kotlin Multiplatform, doing so automatically provides JVM libraries along with other variants, saving effort.

So, how do we use it?

To use the library in Java, you can add it as a dependency in your project:

repositories {
mavenCentral()
}

dependencies {
implementation("eu.sirotin.kotunil:kotunil-jvm:<version>")
}

At the time of writing this article, the latest version was 4.1.1.

What are the differences between the Kotlin and Java versions?

Unfortunately, there are two significant distinctions between the Kotlin and Java versions of library.

Firstly, Java does not support operator overloading, which makes the code less elegant than in Kotlin. For example, consider the following problem: Masha was cleaning the outside of an aquarium when she accidentally bumped into a nearby vase, causing the aquarium glass to break, and the water to spill out. Before this mishap, the aquarium contained 32 liters of water. Masha’s room has a length of 4 meters and a width of 4.3 meters. At what height in millimeters is the water currently located in the room, assuming it remains there and doesn’t leak out?

In Kotlin, the solution looks like this:

val s = 4.m * 4.3.m
val h = 32.l / s

In Java, instead of using arithmetic operations with dimensional units, we have to use functions:

Expression s = m.times(4).times(m.times(4.3));
Expression v = L.times(32);
Expression h = v.div(s);

However, all the other advantages of KotUniL are preserved. You cannot add amperes to seconds, but you can multiply and divide them.

Secondly, when transforming Kotlin code into Java code, the transpiler generates two Java classes for one Kotlin class from the library. Therefore, when working with meters, for example, we need to add the following import in Java:

import static eu.sirotin.kotunil.base.MetreKt.*;

Further information about KotUniL can be found in the repository on GitHub (see detailed examples of working with SI units in Java in the app/jvm/java-console module).

You can also read about the theoretical foundations and peculiarities of using KotUniL in this series:

KotUniL = SI Units + Kotlin. Part One: Introduction to KotUniL (this)

KotUniL = SI Units + Kotlin. Part Two: Advanced Features

KotUniL = SI Units + Kotlin. Part Three: When only one unit test is enough

Are there alternatives?

As for alternatives, I developed KotUniL because none of the existing libraries at the time satisfied me. In the Java community, there is JSR 385, where the developers followed a path of dimensionality separation. They have Quantity<Volume>, Unit<Length>, and so on. Naturally, it’s impossible to cover all possible combinations this way, but it should be sufficient for many applications. There’s an article on Baeldung that provides an overview of working with the library.

However, I found the design of the library less appealing. For example, consider the conversion of meters to kilometers taken from the recommended article:

double distanceInMeters = 50.0;
UnitConverter metreToKilometre = METRE.getConverterTo(MetricPrefix.KILO(METRE));
double distanceInKilometers = metreToKilometre.convert(distanceInMeters);

Using KotUniL, you can write it like this:

val d = 50.m
val x = d.km

I understand that the advantage of JSR 385 lies in detecting type errors at compile time, not in the visual conciseness of the code. In this article, I demonstrate that all KotUniL formulas are checked for type errors with just one unit test while maintaining code readability similar to technical and scientific articles.

Why hasn’t the standard SI system been implemented in Kotlin? As of now, there is no such library among the existing and developing Kotlin standard libraries.

I proposed to the language developers to include this functionality (not necessarily KotUniL) as part of the libraries that come with the language (KT-55556). However, I have not convinced them yet. But perhaps, dear readers, if you actively support this proposal (and also support KotUniL on GitHub :-), the situation may change.

--

--

Dr. Viktor Sirotin
CodeX
Writer for

I love programming, UML, model-driven software engineering, DSL, philosophy, mathematics, modern history and really good music. My homepage: www.sirotin.eu