Core Java Language Surface
java.lang.*, java.util.* and java.time.* types implemented by the Picodroid JVM. See Java API overview for the full API index.
The build checks an app against this surface: verifyApiContract rejects a java.* class or member the runtime does not serve, naming the call site. The compatibility matrix lists the divergences row by row.
java.lang.String
The JVM provides built-in support for java.lang.String. All methods work on ASCII strings; multi-byte UTF-8 sequences are passed through unchanged but byte-indexed (not character-indexed).
String s = "Hello, Pico!";
// Length and accessint len = s.length(); // 12char ch = s.charAt(7); // 'P'boolean e = s.isEmpty(); // false
// Comparisonboolean eq = s.equals("Hello, Pico!"); // trueboolean eqi = s.equalsIgnoreCase("hello, pico!"); // trueint cmp = s.compareTo("Hello, Pico!"); // 0
// Predicatesboolean sw = s.startsWith("Hello"); // trueboolean ew = s.endsWith("Pico!"); // trueboolean co = s.contains("Pico"); // true
// Searchint idx = s.indexOf(','); // 6int idx2 = s.indexOf("Pico"); // 7int li = s.lastIndexOf('!'); // 11
// Transforms — return new String valuesString sub = s.substring(7, 11); // "Pico"String tail = s.substring(7); // "Pico!"String tr = " hi ".trim(); // "hi"String upper = "pico".toUpperCase(); // "PICO"String lower = "PICO".toLowerCase(); // "pico"
// Static factory — valueOf covers int, long, boolean, char, float, doubleString vi = String.valueOf(42); // "42"String vl = String.valueOf(9000L); // "9000"String vb = String.valueOf(true); // "true"String vc = String.valueOf('X'); // "X"String vf = String.valueOf(3.14f); // "3.14"String vd = String.valueOf(2.71828); // "2.71828"String vo = String.valueOf(obj); // obj.toString(), or "null"
// Extended methodsString[] parts = "a,b,c".split(","); // ["a", "b", "c"]String r = "foo bar".replace(' ', '_'); // "foo_bar"String c = "Hello, ".concat("World"); // "Hello, World"String j = String.join(", ", "a", "b", "c"); // "a, b, c"String j2 = String.join("/", new String[] {"x", "y"}); // "x/y"char[] chs = "abc".toCharArray(); // {'a', 'b', 'c'}int h = "abc".hashCode(); // standard Java String hashString r2 = "a-b".replace("-", "+"); // "a+b" — the CharSequence formbyte[] raw = "abc".getBytes(); // the string's bytes (UTF-8)String back = new String(raw); // also new String(raw, off, len)
// Formatted strings — String.format(String, Object...)String msg = String.format("Score: %d (%.1f%%)", 42, 87.5); // "Score: 42 (87.5%)"String.format supports the conversions %s %d %x %X %o %c %b %f %e %g %n %% with the flags
- 0 + (space) , #, plus width and precision (e.g. %-8s, %08.2f). Floating conversions round
HALF_UP, as Java’s Formatter does (%.2f of 1.005 is "1.01"). A bad format throws the
IllegalFormatException subclass Java names: MissingFormatArgumentException,
IllegalFormatPrecisionException (a precision on %d %x %o %c),
IllegalFormatConversionException or UnknownFormatConversionException.
String.join(delimiter, …) takes varargs, a String[], or an ArrayList<String>
(Iterable); the elements must be String or null.
split takes a literal delimiter, not a regular expression, and drops trailing empty strings as
Java does ("a,b,,".split(",") is ["a", "b"]). Strings are built from byte[] only: there is
no String(char[]) constructor, so build one from characters with StringBuilder.append(char).
java.lang.StringBuilder
StringBuilder sb = new StringBuilder(); // emptyStringBuilder sb = new StringBuilder("prefix="); // with initial content
sb.append("text"); // append Stringsb.append(42); // append intsb.append(3.14f); // append float (formats as "3.14")sb.append(2.71828); // append doublesb.append(100L); // append longsb.append(true); // append "true" or "false"sb.append('x'); // append charsb.append(obj); // append Object — its toString(), or "null"
int len = sb.length(); // current content lengthchar ch = (char) sb.charAt(2); // byte at position 2
String s = sb.toString(); // intern result as a StringEvery
StringBuilderowns its buffer, so builders interleave freely andsb.append(sb)appends a copy of the current content; a buffer the heap cannot grow throwsOutOfMemoryErrorfromappend.
java.lang.Math
Standard math functions. All methods are static. Math.PI and Math.E are compile-time constants inlined by javac.
// Constants (inlined by the compiler — no runtime cost)double pi = Math.PI; // 3.141592653589793double e = Math.E; // 2.718281828459045
// abs — int, long, float, doubleint ai = Math.abs(-7); // 7long al = Math.abs(-9000L); // 9000float af = Math.abs(-3.14f); // 3.14double ad = Math.abs(-1.0); // 1.0
// min / max — int, long, float, doubleint lo = Math.min(4, 9); // 4double hi = Math.max(1.5, 2.5); // 2.5
// Roundingdouble fl = Math.floor(2.9); // 2.0double ce = Math.ceil(2.1); // 3.0int ri = Math.round(2.6f); // 3 (float → int)long rl = Math.round(2.5); // 3 (double → long)
// Powers / rootsdouble sq = Math.sqrt(2.0); // ≈ 1.4142135double pw = Math.pow(2.0, 10.0); // 1024.0
// Floor division and the exact-arithmetic helpers (int and long forms)int fd = Math.floorDiv(-7, 2); // -4 (rounds toward negative infinity; -7 / 2 is -3)int fm = Math.floorMod(-7, 2); // 1 (takes the divisor's sign; -7 % 2 is -1)long ex = Math.multiplyExact(1L << 20, 1L << 20); // ArithmeticException on overflowint ie = Math.toIntExact(42L); // ArithmeticException when the long does not fit
// Trigonometry (arguments in radians)double s = Math.sin(Math.PI / 2.0); // ≈ 1.0double c = Math.cos(0.0); // 1.0double t = Math.tan(0.0); // 0.0double a2 = Math.atan2(1.0, 1.0); // ≈ PI/4
// Angle conversiondouble rad = Math.toRadians(90.0); // ≈ PI/2double deg = Math.toDegrees(Math.PI); // 180.0
// Logarithms / exponentialdouble ln = Math.log(Math.E); // ≈ 1.0double lg = Math.log10(100.0); // ≈ 2.0double ex = Math.exp(1.0); // ≈ 2.71828java.util.ArrayList
Dynamic list backed by a per-instance heap buffer.
import java.util.ArrayList;
// Raw type (stores any Object — String, custom objects, null)ArrayList list = new ArrayList();list.add("alpha");list.add("beta");list.add("gamma");
int sz = list.size(); // 3boolean mt = list.isEmpty(); // false
String item = (String) list.get(1); // "beta"String old = (String) list.set(0, "ALPHA"); // returns "alpha"String removed = (String) list.remove(2); // returns "gamma"
boolean found = list.contains("ALPHA"); // trueboolean gone = list.remove("beta"); // remove(Object): drops the first equal elementObject[] copy = list.toArray(); // always a fresh Object[] of the list's lengthlist.clear();
// Indexed insertlist.add(0, "first"); // insert at position 0
// Generic type with autoboxing (Integer, Boolean, Long, Float, Double)ArrayList<Integer> nums = new ArrayList<Integer>(); // or new ArrayList<Integer>(16)nums.add(10); // autoboxes int → Integernums.add(20);int n = nums.get(0); // auto-unboxes Integer → int (10)boolean has = nums.contains(20); // true — value equality for wrapperslist.sort(comparator) sorts in place; list.sort(null) uses the natural ordering. toArray(T[]) ignores its argument: it neither fills nor returns the array passed in, and the result is an Object[].
Autoboxing:
ArrayList<Integer>works as expected —add(42)andcontains(42)both box viaInteger.valueOf. For rawArrayList, store and retrieve Object references (String, custom class instances); do not store bare primitives without explicit boxing (Integer.valueOf(42), etc.).
java.util.HashMap and java.util.HashSet
Hash-table-backed associative containers. Keys are compared by equals() / hashCode(); autoboxed primitives (Integer, Long, Boolean, String) all work as keys.
import java.util.HashMap;import java.util.HashSet;import java.util.Map;
HashMap map = new HashMap();map.put("one", Integer.valueOf(1));map.put("two", Integer.valueOf(2));
Integer v = (Integer) map.get("one"); // 1boolean has = map.containsKey("two"); // trueint n = map.size(); // 2Integer d = (Integer) map.getOrDefault("nope", Integer.valueOf(0)); // 0boolean hv = map.containsValue(Integer.valueOf(2)); // truemap.remove("one");
// Iterate keys / values / entries (keySet(), values() and entrySet() are Iterable)for (Object k : map.keySet()) { Log.i("TAG", (String) k); }for (Object val : map.values()) { Log.i("TAG", String.valueOf((Integer) val)); }for (Map.Entry<String, Integer> e : map.entrySet()) { Log.i("TAG", e.getKey() + "=" + e.getValue()); }
HashSet set = new HashSet();set.add("a");set.add("b");boolean inSet = set.contains("a"); // trueset.remove("a");Both also have isEmpty(), size() and clear(), and the (int initialCapacity) and (int initialCapacity, float loadFactor) constructors. A Map.Entry answers getKey() and getValue(); there is no setValue.
java.util.Iterator and the enhanced for loop
ArrayList, HashMap (via keySet(), values(), entrySet()), HashSet, and any class of your own that implements Iterable work with the enhanced for loop and an explicit Iterator. LinkedHashMap/LinkedHashSet are accepted as aliases of HashMap/HashSet (no insertion order — see the compatibility matrix).
import java.util.ArrayList;import java.util.Iterator;
ArrayList items = new ArrayList();items.add("a"); items.add("b"); items.add("c");
// Enhanced for-eachfor (Object o : items) { Log.i("TAG", (String) o);}
// Explicit iteratorIterator it = items.iterator();while (it.hasNext()) { Log.i("TAG", (String) it.next());}Iterator.remove() is served as well.
java.util.Arrays and java.util.Collections
Stable mergesort and a small set of list utilities, with java.util.Comparator for an ordering of your own. Mirrors the most-used subset of the Java standard library.
import java.lang.Comparable;import java.util.ArrayList;import java.util.Arrays;import java.util.Collections;
// Object[] sort — element type must implement ComparableString[] words = { "echo", "alpha", "delta", "bravo" };Arrays.sort(words); // in-place stable mergesortString dump = Arrays.toString(words); // "[alpha, bravo, delta, echo]"
// Primitive sort (int/long/double/float/short/byte/char overloads), fill, copyOfint[] nums = { 3, 1, 2 };Arrays.sort(nums); // {1, 2, 3}int[] zeros = new int[4];Arrays.fill(zeros, 7); // {7, 7, 7, 7}int[] grown = Arrays.copyOf(nums, 5); // {1, 2, 3, 0, 0}
// Collections — operate on java.util.List (ArrayList implements it)ArrayList<Integer> nums = new ArrayList<Integer>();nums.add(3); nums.add(1); nums.add(2);Collections.sort(nums); // [1, 2, 3]Collections.reverse(nums); // [3, 2, 1]
// Comparator — a lambda, or a class that implements java.util.ComparatorArrays.sort(words, (a, b) -> b.compareTo(a)); // descendingCollections.sort(nums, (a, b) -> a.compareTo(b));| Method | Description |
|---|---|
Arrays.sort(Object[] a) | In-place stable mergesort. Elements must implement Comparable. |
Arrays.sort(int[] a) | In-place sort of a primitive array (long/double/float/short/byte/char overloads too). |
Arrays.fill(a, value) | Fill every element with value (primitive overloads). |
Arrays.copyOf(a, newLength) | Copy, truncating or zero-padding to newLength (primitive overloads). |
Arrays.sort(T[] a, Comparator<? super T> c) | Stable sort by c; null means the natural ordering. |
Arrays.toString(Object[] a) | "[a, b, c]" rendering using each element’s toString (primitive-array overloads too). |
Collections.sort(List) | Stable mergesort over a List. Elements must implement Comparable. |
Collections.sort(List<T> list, Comparator<? super T> c) | Stable sort by c; null means the natural ordering. |
Collections.reverse(List) | Reverse the list in place. |
java.util.Objects
The null-safe static helpers, shipped as a real class in the SDK so that equals, hashCode and
toString dispatch to your own overrides:
import java.util.Objects;
boolean same = Objects.equals(a, b); // true when both null, else a.equals(b)int h = Objects.hash(name, id, 3); // 31·h + hashCode over the boxed argumentsint h0 = Objects.hashCode(null); // 0String s = Objects.toString(null, "none"); // "none"; toString(o) is String.valueOf(o)Objects.requireNonNull(cfg, "cfg"); // throws NullPointerException("cfg")if (Objects.nonNull(x) && Objects.isNull(y)) { /* ... */ }hash(Object...) boxes its arguments; prefer hashCode(o) for a single value on a hot path.
java.util.zip.CRC32
The JDK’s CRC-32, with its Checksum interface: the IEEE polynomial, reflected, so "123456789"
checks to 0xCBF43926. The per-byte loop is native; the running value and the API are a real class
in the SDK, so a Checksum reference dispatches like any other object.
import java.util.zip.CRC32;
CRC32 crc = new CRC32();crc.update(header); // byte[]crc.update(body, 0, bodyLen); // byte[], off, lencrc.update(0x0A); // one byte, the low eight bitslong value = crc.getValue(); // unsigned 32-bit checksum in a longcrc.reset(); // back to an empty stream| Method | Description |
|---|---|
update(byte[] b), update(byte[] b, int off, int len) | Feed bytes; the range form throws ArrayIndexOutOfBoundsException for a range off the array. |
update(int b) | Feed one byte. One native call per byte: hand whole arrays over on a hot path. |
getValue() | The checksum of everything fed since construction or reset(), as a long in 0..2^32. |
reset() | Start over. |
SharedPreferences verifies and signs its file with it; a preferences load on the RP2350 lost some
40 ms of interpreted bytecode when the loop moved out of Java.
java.time
The JDK’s date-time classes, ported to the SDK so an app stops doing epoch arithmetic by hand:
LocalDate, LocalTime, LocalDateTime, Instant, Duration, ZoneOffset, ZoneId,
Month, DayOfWeek, Year, DateTimeFormatter, ChronoUnit, and java.util.TimeZone for
the default zone. The methods keep their JDK signatures, so the code you would write on Android
compiles and runs unchanged:
import java.time.*;import java.time.format.DateTimeFormatter;import java.time.temporal.ChronoUnit;import java.util.TimeZone;
// The wall clock is the platform's: the time service anchors it from the network after the// join, and the zone is what the user picked in Settings → Date & time. Nothing to set up.LocalDateTime now = LocalDateTime.now(); // in the platform zone// TimeZone.setDefault still overrides the zone for this process, as on Android:TimeZone.setDefault(TimeZone.getTimeZone("GMT+05:30"));String clock = now.format(DateTimeFormatter.ofPattern("HH:mm"));String date = now.toLocalDate().format(DateTimeFormatter.ofPattern("EEE, d MMM yyyy"));
Instant resetAt = Instant.ofEpochSecond(json.getLong("resets_at"));Duration left = Duration.between(Instant.now(), resetAt);long hours = left.toHours(), minutes = left.toMinutes() % 60;
LocalDate due = LocalDate.of(2026, Month.SEPTEMBER, 23).plusMonths(1); // 2026-10-23long days = ChronoUnit.DAYS.between(LocalDate.now(), due);LocalDateTime local = LocalDateTime.ofInstant(resetAt, ZoneId.systemDefault());What is not there, and what to do instead:
| Missing | Instead |
|---|---|
Region zones (ZoneId.of("Europe/London") throws DateTimeException), daylight saving | A fixed offset: ZoneOffset.ofHours(1), ZoneId.of("UTC+01:00"). TimeZone.getDefault() / ZoneId.systemDefault() is the platform zone (UTC until the user picks one in Settings → Date & time; its id reads UTC or GMT+05:30), stored across reboots and the same for every app; setDefault overrides it for the process. |
ZonedDateTime, OffsetDateTime, Period, TemporalField / ChronoField, TemporalAdjusters | LocalDateTime.ofInstant(instant, zone) and toInstant(offset) cross between the time-line and local fields; ChronoUnit.X.between and plusX cover the arithmetic. |
Locale-aware text, DateTimeFormatter.ofLocalizedDate, parsing with a pattern | ofPattern with y u M L d D E a H h m s S and '…' literals (English month and day names); LocalDate.parse and friends read ISO-8601. |
Clock, Instant.now() before the clock is set | now() reads System.currentTimeMillis(), which counts from boot until the platform’s time service anchors it (seconds after a WiFi board joins) or SystemClock.setCurrentTimeMillis does. |
The package is left out of the testbench_rp2040 image (framework_class_excludes, about 67 KB
of class files it does not have room for), where verifyApiContract --board rejects an app that uses it.
examples/timedemo exercises the port; its expectations were checked against the JDK’s own
java.time on a host.
java.lang.Comparable
public class Score implements Comparable<Score> { int value; public int compareTo(Score other) { return this.value - other.value; }}Used by Arrays.sort and Collections.sort. Boxed numerics (Integer, Long, Float, Double) and String already implement it.
Interface-typed collections
List<E>, Set<E>, Collection<E>, Map<K,V> and Iterable<E> all work as declared types, parameter types and return types — Map<String, String> m = new HashMap<>(); compiles and runs, as do interface-typed fields, instanceof, casts and the enhanced for loop:
Map<String, Integer> scores = new HashMap<>(); // interface-typedList<String> names = new ArrayList<>();Set<String> seen = new HashSet<>();Collection<String> asCollection = names; // widening worksIterable<String> asIterable = seen;
static int total(Collection<Integer> values) { ... } // interface parameterstatic Map<String, Integer> build() { ... } // interface returnThese interfaces are built into the JVM rather than shipped as SDK source: your app compiles against the JDK’s own java.util declarations, and at run time the call dispatches on the receiver’s actual class (ArrayList, HashMap, HashSet, or a class of your own). ArrayList is the only concrete List in v1.
The catch: because the compiler sees the JDK’s full interfaces, it will also accept members picodroid does not implement (map.forEach, list.removeIf, Map.putAll, new TreeMap<>()), which fail at run time instead of at build time. Stick to the members listed in the compatibility matrix.
java.lang.Class
Class literals (MyType.class) and reflection-lite: getName(), forName(String) and newInstance(). There is no Field, Method or Constructor API, no member discovery and no access check.
Class<?> c = String.class;String name = c.getName(); // "java.lang.String"boolean same = (s.getClass() == String.class); // true — Class instances are interned
// Each evaluation of `T.class` returns the same Class instanceboolean stable = (Direction.class == Direction.class); // true
// By name, as getName() spells it (so it holds when the shrinker renames the app's classes):Class<?> k = Class.forName(Gauge.class.getName()); // ClassNotFoundException if not packedObject g = k.newInstance(); // the public no-argument constructor; // InstantiationException otherwisetoString() is "class " + getName(). forName finds a class packed with the app or the framework (every class is in flash already; nothing is loaded) and newInstance() runs the no-argument constructor, initialising the class first if it never was. This is what the framework uses to construct a ViewModel (ViewModelProvider.NewInstanceFactory), a saved Fragment (the default FragmentFactory) and a custom view a layout names (LayoutInflater), as Android does, so none of those needs a factory of the app’s own. IllegalAccessException is declared but never thrown: there are no access checks.
Object.getClass() returns the runtime Class<?> of any reference. Useful for type-safe equality (.getClass() == Foo.class) and for log dispatch keyed by class identity.
java.lang.AutoCloseable and try-with-resources
public interface AutoCloseable { void close() throws Exception;}Any class that implements AutoCloseable works in try-with-resources — the compiler calls close() on exit (normal or exceptional). The picodroid.pio.* peripheral handles all implement it, so the idiomatic pattern is:
try (Gpio led = pm.openGpio("GP25")) { led.setDirection(Gpio.DIRECTION_OUT_INITIALLY_LOW); led.setValue(true);} // led.close() runs here.Multiple resources in one try close in reverse-declaration order. See examples/trywithresourcesdemo/ for a worked example.
java.io streams
The java.io stream hierarchy, as pure-Java classes on every board: InputStream and
OutputStream (abstract), ByteArrayInputStream / ByteArrayOutputStream, Reader and
Writer (abstract), InputStreamReader, BufferedReader with readLine(),
OutputStreamWriter and PrintWriter. picodroid.io.FileInputStream / FileOutputStream,
picodroid.net.HttpInputStream / HttpOutputStream and Socket.getInputStream() /
getOutputStream() are java.io streams, so the Android idioms work as written:
import java.io.BufferedReader;import java.io.ByteArrayOutputStream;import java.io.InputStream;import java.io.InputStreamReader;import java.io.PrintWriter;
// Lines from an HTTP body, a file or a socketBufferedReader r = new BufferedReader(new InputStreamReader(conn.getInputStream()));String line;while ((line = r.readLine()) != null) { Log.i("NET", line);}
// Every byte of a streamstatic byte[] readAll(InputStream in) throws IOException { ByteArrayOutputStream out = new ByteArrayOutputStream(); byte[] buf = new byte[64]; int n; while ((n = in.read(buf)) != -1) { out.write(buf, 0, n); } return out.toByteArray();}
// Lines to a socketPrintWriter out = new PrintWriter(socket.getOutputStream(), /*autoFlush=*/true);out.println("HELLO");An app’s own stream subclasses InputStream and implements read(); read(byte[]), skip
and the rest come from the base class, as in the JDK (override read(byte[], int, int) for
speed). InputStream, OutputStream, Reader and Writer implement java.io.Closeable, which
is an AutoCloseable, so every stream works in try-with-resources.
Strings are UTF-8 bytes. charAt and length() count bytes, and a reader decodes UTF-8
(the default charset, and what every charset name decodes): an ASCII byte is one char, a
two- or three-byte sequence one char of the BMP, a malformed byte U+FFFD. A writer encodes
each char back to UTF-8, so a String’s chars (already UTF-8) pass through one to one. The
charset-name constructors (InputStreamReader(in, "UTF-8"), OutputStreamWriter(out, "UTF-8"))
accept any name and report it from getEncoding(); UnsupportedEncodingException is declared,
never thrown. A UTF-8 line comes out of readLine() byte for byte, so it logs and displays
correctly; ByteArrayOutputStream.toString() builds its string the way new String(byte[]) does
(valid UTF-8 kept, each byte of an invalid sequence ?). PrintWriter ends lines with \n and
never throws IOException — a failed write sets the flag checkError() reports.
BufferedReader’s default buffer is 128 chars (pass a size for larger reads). On
testbench_rp2040 the reader and writer classes are dropped from the framework (InputStream,
OutputStream and the ByteArray* streams stay); verifyApiContract --board testbench_rp2040
rejects an app that uses them there. Not provided:
FileReader / FileWriter (wrap picodroid.io.FileInputStream in an InputStreamReader, or
FileOutputStream in an OutputStreamWriter), DataInputStream, BufferedInputStream,
StringReader / StringWriter, and java.nio.charset.
Enums
Java enum declarations are supported. Each enum constant is a singleton; values(), valueOf(String), name(), ordinal(), and switch (myEnum) all work. valueOf throws IllegalArgumentException for a name that is not a constant, as in Java.
public enum Direction { NORTH, EAST, SOUTH, WEST }
Direction d = Direction.NORTH;String name = d.name(); // "NORTH"int ord = d.ordinal(); // 0Direction w = Direction.valueOf("WEST");for (Direction dir : Direction.values()) { Log.i("TAG", dir.name());}
switch (d) { case NORTH: Log.i("TAG", "up"); break; case SOUTH: Log.i("TAG", "down"); break; default: Log.i("TAG", "side"); break;}Boxed primitives (wrapper classes)
Integer, Long, Short, Byte, Float, Double, Boolean, and Character are available as
object wrappers. Each supports valueOf(primitive), the matching unboxing accessor, and toString():
Integer boxed = Integer.valueOf(42);int back = boxed.intValue(); // 42String s = boxed.toString(); // "42"
Boolean b = Boolean.valueOf(true); boolean bv = b.booleanValue();Long l = Long.valueOf(9000L); long lv = l.longValue();Float f = Float.valueOf(3.14f); float fv = f.floatValue();Double d = Double.valueOf(2.71828); double dv = d.doubleValue();Character c = Character.valueOf('X'); char cv = c.charValue();You rarely call these directly: ArrayList<Integer> and HashMap keys/values autobox through
valueOf and auto-unbox through the *Value() accessors.
Parsing and comparing:
int n = Integer.parseInt("42"); // NumberFormatException for text that is not a numberlong l2 = Long.parseLong("9000");double d2 = Double.parseDouble("2.5"); // Float.parseFloat, Short.parseShort, Byte.parseByte tooboolean t = Boolean.parseBoolean("true");Integer b2 = Integer.valueOf("42"); // valueOf(String) on every numeric wrapperString s2 = Integer.toString(42); // the static toString(x) of each numeric wrapperint c2 = Integer.compare(3, 7); // negative; compare(x, y) and compareTo on every wrapper
boolean dg = Character.isDigit('7'); // isLetter, toUpperCase, toLowerCase — ASCII onlyThe numeric wrappers convert through byteValue(), shortValue(), intValue(), longValue(),
floatValue() and doubleValue() as Java does. Float.isNaN / Double.isNaN / isInfinite are
not served: test f != f for NaN.
Float.floatToIntBits(f) and Float.intBitsToFloat(i) round-trip the IEEE-754 bit pattern — for a
bit-exact equals/hashCode, or to keep a float in an int slot.
Exceptions
java.lang.Throwable, Exception, and RuntimeException are supported, each with the standard
no-arg and (String message) constructors. Standard subclasses such as IllegalArgumentException
and IllegalStateException are also throwable with a message. Define your own by extending
Exception (or RuntimeException), then throw / catch as usual — catch matches subclasses
of the declared type:
public class AppException extends Exception { public AppException(String message) { super(message); }}
try { if (bad) throw new AppException("bad input");} catch (AppException e) { Log.i("TAG", "caught an AppException");}The runtime throws the standard unchecked exceptions where Java does, and each can be caught by
name: NullPointerException, ArithmeticException, ArrayIndexOutOfBoundsException,
StringIndexOutOfBoundsException, IndexOutOfBoundsException, NegativeArraySizeException,
ArrayStoreException, ClassCastException, NumberFormatException,
UnsupportedOperationException, IllegalMonitorStateException, IllegalThreadStateException,
java.util.NoSuchElementException and java.util.ConcurrentModificationException, with the
checked InterruptedException and java.io.IOException, and the errors OutOfMemoryError,
StackOverflowError and ExceptionInInitializerError.
The message and cause passed to a constructor are captured by the runtime: getMessage(),
getCause(), addSuppressed() and getSuppressed() read them back, and an uncaught throw prints
them. Caveat: there is no stack-trace API (getStackTrace() / printStackTrace()) — the trace
is printed by the runtime when a throw goes uncaught. See
examples/exceptiondemo/.
java.util.Random
A seedable pseudo-random generator. A fixed seed gives a reproducible stream.
import java.util.Random;
Random r = new Random(); // or new Random(42L) for a fixed seedr.setSeed(42L);
int i = r.nextInt(); // any intint i2 = r.nextInt(100); // 0..99long l = r.nextLong();boolean b = r.nextBoolean();float f = r.nextFloat(); // [0.0, 1.0)double d = r.nextDouble(); // [0.0, 1.0)double g = r.nextGaussian(); // mean 0.0, stddev 1.0byte[] buf = new byte[8];r.nextBytes(buf); // fill with random bytesSee examples/randomdemo/.
java.lang.System and java.lang.Runnable
System.currentTimeMillis() returns wall-clock milliseconds (see
System & concurrency for the full timing surface, including
SystemClock). System.arraycopy(src, srcPos, dest, destPos, length) copies between arrays of
the same element type (ArrayStoreException otherwise, IndexOutOfBoundsException for a range
off either array); an overlapping copy within one array is safe. java.lang.Runnable is the
standard void run() interface — used by Thread, Executors, and (historically) view callbacks:
Runnable task = () -> Log.i("TAG", "ran");task.run();Lambdas and method references
A lambda or a method reference can stand in for any interface with a single abstract method —
Runnable, Comparator, a listener, or an interface of your own. Lambdas may capture local
variables. Method references resolve to static methods, bound and unbound instance methods,
constructors and the built-in classes’ methods:
interface Fn<A, R> { R apply(A a); }interface Factory<T> { T create(); }
Fn<Integer, Integer> twice = MyApp::twice; // static methodFn<Integer, Integer> add = this::instanceAdd; // bound instance methodFn<String, Integer> length = String::length; // unbound, on a built-in classFactory<Counter> counter = Counter::new; // constructorThere is no java.util.function package (Function, Supplier, Predicate, …): declare the
single-method interface you need. See
examples/lambdademo/.
See also: System & concurrency · Peripherals · Storage · Networking · Graphics & UI