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