Some Java oddities

I was recently asked for some simple pieces of code which some unusual uses of Java.

Here are some of my favourites ;)

Stateless Singleton implementing an interface

public enum RandomStrategy implements IntSupplier {
    INSTANCE;

    @Override
    public int getAsInt() {
        return ThreadLocalRandom.current().nextInt();
    }
}

This is useful for creating multiple implementations of a strategy pattern which share an interface. E.g. I have TimeProvider with 4 implementations depending on usage.

An example of where I use this is a TimeProvider which is basically

@FunctionalInterface
 public interface TimeProvider {

     long currentTimeMillis();

     default long currentTimeMicros() {
         return currentTimeMillis() * 1000;
     }

This has multiple enum implementations which share an interface so they can be used interchangably

TimeProvider

Usage

SetTimeProvider

a set time for unit testing.

SystemTimeProvider

uses the wall clock.

UniqueMicroTimeProvider

use wall clock except for the micro-second time always increases

LinuxTimeProvider (TBD)

Uses a microsecond resolution system call

Almost final

static final int l = printNM();
static final int n = 10;
static final int m = Math.min(10, 10);
static final int o = printNM();

static int printNM() {
    System.out.println(n + " " + m); // 10 0 then 10 10
    return 5;
}

Before a variable is assigned a value it is 0, false or null unless the value is known at compile time in which case it is also inlined.

Smiley faces

int ⁀‿⁀ = 0, ⁀⁔⁀ = 1, ¢ = 2;

if (⁀‿⁀ != ⁀⁔⁀)
    System.out.println(¢);

As _ and $ are allowed characters so all continuation and currency symbols are allowed.

Getting the top bit whether int or long.

int i = -1;
long l = -1;
System.out.println("sign(i)=" + (i >> -1));
System.out.println("sign(l)=" + (l >> -1));

The shift value is masked by the lower 5 bit for int or 6 bits for long. The upshot is that a shift by -1 is either 31 or 63 depending on the type.

A Throwable for tracing only

/**
 * Throwable created purely for the purposes of reporting a stack trace.
 * <p>
 * This is not an Error or an Exception and is not expected to be thrown or caught.
 * </p>
 */
public class StackTrace extends Throwable {
    public StackTrace() {
        this(null);
    }

    public StackTrace(String message) {
        this(message, null);
    }

    public StackTrace(String message, Throwable cause) {
        super(message, cause, false, false);
    }
}

We use this for tracing where resources are allocated and/or closed to reporting on multi-threaded resource management

No ConcurrentModificationException.

The check for iterations == size happens before the modification count for CME.

List<Integer> ints = new ArrayList<Integer>() {{
    add(1);
    add(2);
    add(3);
}};
for (int i : ints) // no exception
    if (i == 2)
        ints.remove(i);

Wrapper pooling covers the range -128 to 127 for Byte, Short, Character, Integer and Long. (Possibly higher for Integer depending on command line options.)

Character a1 = 127, a2 = 127;
Character b1 = 128, b2 = 128;
System.out.println(a1 == a2); // true
System.out.println(b1 == b2); // false
Detected assertions are on.
boolean debug = false;
assert debug = true;
if (debug)
   System.out.println("Assertions are on");

This shows you can easily determine is assertions are on for expensive checks. Another simple approach is:

public void method() {
    assert validate();
}

private boolean validate() {
    if (expensiveCheck())
        throw new AssertionError("details");
    return true;
}

Legacy arrays on methods are allowed as easier compilers allowed this.

static int fun(int[] ints)[] { return ints; }

public static void main(String... args) {
    System.out.println(fun(new int[1]).length);
}

char and floating point

The compound assignment operator casts to the wider type and then narrows it implicitly.

char ch = '1';
ch /= 0.9;
System.out.println(ch);

int and float

Wider types don’t always have more precision. A float is wider than an int or long, but has less precision for whole numbers inside the int and long ranges.

int i = Integer.MAX_VALUE;
i += 0.0f;
System.out.println(i == Integer.MAX_VALUE);
i -= 63;
i += 0.0f;
System.out.println(i == Integer.MAX_VALUE);
i -= 64;
i += 0.0f;
System.out.println(i == Integer.MAX_VALUE);

Unknown exit code

One of the threads in your ForkJoinPool.commonPoll() will be the first to call exit.

IntStream.range(0, 128)
        .parallel()
        .forEach(System::exit);

WindowsTF

Windows treats certain file names as special devices, even if a path or file extension is provided.

C:\Users\peter>more > A.java
class Nul { }
class Con { String s = "\nHello World\n"; }
^Z

C:\Users\peter>javac A.java (1)
╩■║╛   4 
           s Ljava/lang/String; <init> ()V Code LineNumberTable
SourceFile A.java    
Hello World
   Con java/lang/Object                       
   #     *╖ *╡ ▒                
C:\Users\peter>dir
 Volume in drive C is OS
 Volume Serial Number is 3EB6-6BBF

 Directory of C:\Users\peter

04/09/2018  13:51    <DIR>          .
04/09/2018  13:51    <DIR>          ..
04/09/2018  13:51                62 A.java (2)
               1 File(s)             62 bytes
               2 Dir(s)  670,935,572,480 bytes free
1 Compiling the code dumps the .class to the screen.
2 Note: no .class files are written.
Peter K Lawrey

Peter K Lawrey

Most answers for Java and JVM on StackOverflow.com (13K), "Vanilla Java" blog with four million views, founder of the Performance JUG, Java Champion

Read More
comments powered by Disqus
Some Java oddities
Share this