Type qualifier annotations for the Checker Framework static analysis tool
—
Units annotations provide dimensional analysis and physical unit checking to prevent unit conversion errors and ensure dimensional consistency in calculations involving physical quantities.
Annotations for fundamental SI base units.
/**
* Length measurement (base unit: meter)
*/
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER})
@UnitsRelations(org.checkerframework.checker.units.qual.m.class)
public @interface Length {}
/**
* Mass measurement (base unit: kilogram)
*/
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER})
@UnitsRelations(org.checkerframework.checker.units.qual.kg.class)
public @interface Mass {}
/**
* Time measurement (base unit: second)
*/
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER})
@UnitsRelations(org.checkerframework.checker.units.qual.s.class)
public @interface Time {}
/**
* Electric current (base unit: ampere)
*/
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER})
@UnitsRelations(org.checkerframework.checker.units.qual.A.class)
public @interface Current {}
/**
* Temperature (base unit: kelvin)
*/
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER})
@UnitsRelations(org.checkerframework.checker.units.qual.K.class)
public @interface Temperature {}
/**
* Amount of substance (base unit: mole)
*/
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER})
@UnitsRelations(org.checkerframework.checker.units.qual.mol.class)
public @interface Substance {}
/**
* Luminous intensity (base unit: candela)
*/
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER})
@UnitsRelations(org.checkerframework.checker.units.qual.cd.class)
public @interface Luminance {}Usage Examples:
import org.checkerframework.checker.units.qual.*;
public class BaseUnitsExample {
// Method that requires length measurements
public @Area double calculateArea(@Length double width, @Length double height) {
return width * height; // Length × Length = Area
}
// Method that requires mass and acceleration
public @Force double calculateForce(@Mass double mass, @Acceleration double acceleration) {
return mass * acceleration; // Mass × Acceleration = Force
}
// Method that requires time measurements
public @Speed double calculateSpeed(@Length double distance, @Time double time) {
return distance / time; // Length ÷ Time = Speed
}
public void example() {
@Length double width = 5.0; // 5 meters
@Length double height = 3.0; // 3 meters
@Mass double mass = 10.0; // 10 kilograms
@Time double time = 2.0; // 2 seconds
@Area double area = calculateArea(width, height); // 15 m²
@Speed double speed = calculateSpeed(width, time); // 2.5 m/s
@Acceleration double accel = 9.8; // 9.8 m/s²
@Force double force = calculateForce(mass, accel); // 98 N
}
}Annotations for derived units computed from base units.
/**
* Area measurement (Length²)
*/
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER})
public @interface Area {}
/**
* Volume measurement (Length³)
*/
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER})
public @interface Volume {}
/**
* Speed measurement (Length/Time)
*/
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER})
public @interface Speed {}
/**
* Acceleration measurement (Length/Time²)
*/
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER})
public @interface Acceleration {}
/**
* Force measurement (Mass × Length/Time²)
*/
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER})
public @interface Force {}
/**
* Angular measurement
*/
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER})
public @interface Angle {}Usage Examples:
import org.checkerframework.checker.units.qual.*;
public class DerivedUnitsExample {
// Physics calculations with proper unit checking
public @Volume double calculateVolume(@Length double length, @Length double width, @Length double height) {
return length * width * height; // Length³ = Volume
}
public @Acceleration double calculateAcceleration(@Speed double initialVelocity,
@Speed double finalVelocity,
@Time double time) {
return (finalVelocity - initialVelocity) / time; // (Speed - Speed) / Time = Acceleration
}
// Circular motion calculations
public @Speed double calculateCircularSpeed(@Length double radius, @Angle double angularVelocity, @Time double time) {
return radius * (angularVelocity / time); // Length × (Angle/Time) = Speed
}
public void physicsExample() {
// Geometric calculations
@Length double length = 10.0; // meters
@Length double width = 5.0; // meters
@Length double height = 2.0; // meters
@Volume double volume = calculateVolume(length, width, height); // 100 m³
// Motion calculations
@Speed double initialSpeed = 0.0; // m/s
@Speed double finalSpeed = 20.0; // m/s
@Time double accelerationTime = 4.0; // seconds
@Acceleration double acceleration = calculateAcceleration(initialSpeed, finalSpeed, accelerationTime); // 5 m/s²
// Force calculation
@Mass double mass = 5.0; // kg
@Force double force = mass * acceleration; // 25 N
}
}Annotations for specific unit values and prefixes.
/**
* Meters (base length unit)
*/
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER})
@UnitsMultiple(quantity = Length.class, prefix = Prefix.one)
public @interface m {}
/**
* Kilometers (1000 meters)
*/
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER})
@UnitsMultiple(quantity = Length.class, prefix = Prefix.kilo)
public @interface km {}
/**
* Square kilometers
*/
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER})
@UnitsMultiple(quantity = Area.class, prefix = Prefix.kilo)
public @interface km2 {}
/**
* Cubic kilometers
*/
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER})
@UnitsMultiple(quantity = Volume.class, prefix = Prefix.kilo)
public @interface km3 {}
/**
* Kilograms (base mass unit)
*/
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER})
@UnitsMultiple(quantity = Mass.class, prefix = Prefix.one)
public @interface kg {}
/**
* Grams (0.001 kg)
*/
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER})
@UnitsMultiple(quantity = Mass.class, prefix = Prefix.milli)
public @interface g {}
/**
* Seconds (base time unit)
*/
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER})
@UnitsMultiple(quantity = Time.class, prefix = Prefix.one)
public @interface s {}
/**
* Hours (3600 seconds)
*/
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER})
@UnitsMultiple(quantity = Time.class, prefix = Prefix.one)
public @interface h {}
/**
* Minutes (60 seconds)
*/
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER})
@UnitsMultiple(quantity = Time.class, prefix = Prefix.one)
public @interface min {}
/**
* Kilometers per hour
*/
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER})
public @interface kmPERh {}
/**
* Meters per second
*/
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER})
public @interface mPERs {}
/**
* Newtons (force unit)
*/
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER})
@UnitsMultiple(quantity = Force.class, prefix = Prefix.one)
public @interface N {}
/**
* Kilonewtons
*/
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER})
@UnitsMultiple(quantity = Force.class, prefix = Prefix.kilo)
public @interface kN {}Usage Examples:
import org.checkerframework.checker.units.qual.*;
public class SpecificUnitsExample {
// Method that converts between different length units
public @m double convertToMeters(@km double kilometers) {
return kilometers * 1000.0; // km to m conversion
}
public @kg double convertToKilograms(@g double grams) {
return grams / 1000.0; // g to kg conversion
}
// Speed conversion
public @mPERs double convertSpeed(@kmPERh double kmPerHour) {
return kmPerHour / 3.6; // km/h to m/s conversion
}
public void conversionExample() {
// Distance measurements
@km double distanceKm = 5.0; // 5 kilometers
@m double distanceM = convertToMeters(distanceKm); // 5000 meters
// Mass measurements
@g double massGrams = 2500.0; // 2500 grams
@kg double massKg = convertToKilograms(massGrams); // 2.5 kilograms
// Time measurements
@h double timeHours = 2.0; // 2 hours
@min double timeMinutes = timeHours * 60; // 120 minutes
@s double timeSeconds = timeMinutes * 60; // 7200 seconds
// Speed measurements
@kmPERh double speedKmh = 72.0; // 72 km/h
@mPERs double speedMs = convertSpeed(speedKmh); // 20 m/s
// Force measurements
@N double forceNewtons = 100.0; // 100 Newtons
@kN double forceKiloNewtons = forceNewtons / 1000.0; // 0.1 kN
}
}Meta-annotations for defining unit relationships and prefixes.
/**
* Defines relationships between units
*/
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface UnitsRelations {
Class<? extends Annotation>[] value();
}
/**
* Defines unit multiples and prefixes
*/
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface UnitsMultiple {
Class<? extends Annotation> quantity();
Prefix prefix();
}
/**
* SI prefixes for unit scaling
*/
public enum Prefix {
yocto, zepto, atto, femto, pico, nano, micro, milli, centi, deci,
one,
deca, hecto, kilo, mega, giga, tera, peta, exa, zetta, yotta
}
/**
* Indicates unknown units
*/
@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER})
@DefaultQualifierInHierarchy
public @interface UnknownUnits {}
/**
* Bottom type for units hierarchy
*/
@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER})
@SubtypeOf({Length.class, Mass.class, Time.class, Current.class, Temperature.class, Substance.class, Luminance.class})
public @interface UnitsBottom {}
/**
* Mixed or incompatible units
*/
@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER})
@SubtypeOf(UnknownUnits.class)
public @interface MixedUnits {}
/**
* Polymorphic unit qualifier
*/
@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER})
@PolymorphicQualifier(UnknownUnits.class)
public @interface PolyUnit {}Usage Examples:
import org.checkerframework.checker.units.qual.*;
// Define a custom unit with relationships
@UnitsRelations({m.class, km.class})
@Target({ElementType.TYPE_USE})
@Retention(RetentionPolicy.RUNTIME)
public @interface Distance {}
// Define a custom prefixed unit
@UnitsMultiple(quantity = Length.class, prefix = Prefix.milli)
@Target({ElementType.TYPE_USE})
@Retention(RetentionPolicy.RUNTIME)
public @interface mm {}
public class UnitFrameworkExample {
// Polymorphic method that preserves unit types
public @PolyUnit double scale(@PolyUnit double value, double factor) {
return value * factor;
}
// Method that handles mixed units safely
public double convertToBaseUnits(@MixedUnits double value, String unitType) {
switch (unitType) {
case "km": return value * 1000.0; // Convert km to m
case "cm": return value / 100.0; // Convert cm to m
case "mm": return value / 1000.0; // Convert mm to m
default: return value; // Assume base unit
}
}
public void frameworkExample() {
@m double meters = 100.0;
@km double kilometers = 2.0;
// Polymorphic scaling preserves units
@m double scaledMeters = scale(meters, 1.5); // 150 m
@km double scaledKm = scale(kilometers, 0.5); // 1 km
// Handle mixed units when necessary
@MixedUnits double mixedValue = 500.0;
double normalized = convertToBaseUnits(mixedValue, "cm"); // 5 m
}
}Annotations for angular quantities and rotational calculations.
/**
* Angle in degrees
*/
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER})
@UnitsMultiple(quantity = Angle.class, prefix = Prefix.one)
public @interface degrees {}
/**
* Angle in radians
*/
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER})
@UnitsMultiple(quantity = Angle.class, prefix = Prefix.one)
public @interface radians {}Usage Examples:
import org.checkerframework.checker.units.qual.*;
public class AngularExample {
public @radians double degreesToRadians(@degrees double degrees) {
return degrees * Math.PI / 180.0;
}
public @degrees double radiansToDegrees(@radians double radians) {
return radians * 180.0 / Math.PI;
}
// Trigonometric functions with unit checking
public double sine(@radians double angle) {
return Math.sin(angle); // Math.sin expects radians
}
public @Length double calculateArcLength(@Length double radius, @radians double centralAngle) {
return radius * centralAngle; // s = r × θ (in radians)
}
public void trigonometryExample() {
@degrees double angleDeg = 45.0; // 45 degrees
@radians double angleRad = degreesToRadians(angleDeg); // π/4 radians
double sinValue = sine(angleRad); // sin(π/4) = √2/2
@Length double radius = 10.0; // 10 meters
@Length double arcLength = calculateArcLength(radius, angleRad); // ~7.85 meters
@degrees double backToDegrees = radiansToDegrees(angleRad); // 45 degrees
}
}Install with Tessl CLI
npx tessl i tessl/maven-org-checkerframework--checker-qual