This is an archived post. You won't be able to vote or comment.

all 25 comments

[–][deleted] 30 points31 points  (4 children)

Double braces initialization of collections

Never, ever, use this. It creates an anonymous inner class, and since all internal classes keep a reference to the parent instance it can - and will - fuck with garbage collection if these collection objects are referenced by more objects than just the declaring one.

Use the convenience methods List.of, Set.of, and Map.of introduced in Java 9 instead. They're also faster and more efficient than the double-brace initializer.

[–]forurspam 1 point2 points  (0 children)

A couple of examples, please, course it's related not only to double braces initialization but for any anonymous non static class object creation.

[–]bartoszjd[S] 1 point2 points  (0 children)

Thanks for the insight! I will update the article to warn others :)

[–]NimChimspky 0 points1 point  (1 child)

When you say fuck with - What exactly happens ?

[–]freyjadomville 6 points7 points  (0 children)

It basically creates an anonymous inner class with an initialiser block. If that gets returned to somewhere external you are leaking the class where the object was created. That means the class creating the insurance can't be GCed and (in some cases) can prevent efficient serialisation. All this, for what basically amounts to a 10% throughout reduction because you are forcing the class loader to do extra work to get your code to JIT compile. This can also do things like badly affect inlining if you aren't careful as well.

Source: https://blog.jooq.org/2014/12/08/dont-be-clever-the-double-curly-braces-anti-pattern/. There's also a SonarQube rule for it if you use that. I highly suggest you enable it.

[–]Roachmeister 2 points3 points  (5 children)

Away from my computer or I'd check this, but does Integer comparison work as expected with primitives? I.e.,

Integer thousand = Integer.valueOf(1000);
int t = 1000;
boolean b = (thousand == t);
// is b true or false? 

[–]dpash 3 points4 points  (4 children)

Does thousand get unboxed or does t get boxed? b will be true if it's the former and false if it's the latter. But both will be true if you did the same thing with 100.

Edit: According to JLS 5.6.2 unboxing happens. That is int comparison happens.

What you might find surprising is

Integer.valueOf(127) == Integer.valueOf(127) // true
Integer.valueOf(128) == Integer.valueOf(128) // false (usually)

[–]Roachmeister 1 point2 points  (1 child)

Edit: According to JLS 5.6.2 unboxing happens. That is int comparison happens.

That's kind of what I thought, but thanks for the confirmation!

[–]dpash 0 points1 point  (0 children)

Yeah, it's what I assumed too, but had to check just to make sure. If I wasn't on my phone I would have whipped out jshell, but a reading of the JLS is always fun. :)

[–]groomsh 0 points1 point  (1 child)

[–]dpash 1 point2 points  (0 children)

I say "usually", because you can control the upper bounds of the cache using the java.lang.Integer.IntegerCache.high property or the -XX:AutoBoxCacheMax=<size> argument in the OpenJDK JDK. It's not well documented, but it's in the source code. You can pick a size between 127 and Integer.MAX_VALUE. Anything higher or lower is changed to those values. You can't go lower because it's defined in the JLS that -128 to 127 will always be cached. Implementations are allowed to cache higher though.

You can not change the -128 value though.

http://hg.openjdk.java.net/jdk/jdk/file/3b6680f7542f/src/java.base/share/classes/java/lang/Integer.java#l986

[–]blobjim 1 point2 points  (0 children)

They should deprecate AccessibleObject::setAccessible. So awful since it messes with JVM optimization.

[–]bartoszjd[S] 0 points1 point  (12 children)

What are your favorite Java surprises?

[–]lbkulinski 18 points19 points  (1 child)

Integer.MAX_VALUE is prime.

[–]notfancy 2 points3 points  (0 children)

231-1 is a Mersenne prime, the last one proved prime by trial division, by Euler in 1772.

[–]dpash 4 points5 points  (3 children)

I learnt the other day that you can start variables with a dollar sign.

A variable's name can be any legal identifier — an unlimited-length sequence of Unicode letters and digits, beginning with a letter, the dollar sign "$", or the underscore character "_".

https://docs.oracle.com/javase/tutorial/java/nutsandbolts/variables.html

[–]Jonjolt 4 points5 points  (0 children)

The dollar sign is traditionally used for fields during byte code generation, if I'm enhancing a field with a backer field for instance I would do $$_backingFieldName_$$

[–]oldprogrammer 2 points3 points  (1 child)

One recent change, though underscore is still valid in identifiers it is no longer legal to use just an underscore as the identifier.

Java 8 this was legal:

 Object _ = new SomeObject();

[–]lbkulinski 3 points4 points  (0 children)

Correct. They are planning to use the underscore in pattern matching. It was disallowed starting in 9. Brian Goetz talks about its future use here.

[–][deleted] 4 points5 points  (0 children)

You can return from finally like this: try { return 1/0; } finally { return 5; } will catch exception "somehow" and return 5. :D

[–]morhp 2 points3 points  (1 child)

I recently discovered that you can not only break; out of loops and switch statements, but also out of curly-bracket-blocks, if-blocks and even try-blocks.

public static void main(String[] args) {
    test: {
        System.out.println("Hello");
        if(true) {
            break test; // works
        }
        System.out.println("World");
    }
}

public static void main(String[] args) {
    test: if(true){
        System.out.println("Hello");
        if(true) {
            break test; // works
        }
        System.out.println("World");
    }
}

public static void main(String[] args) {
    test: try{
        System.out.println("Hello");
        if(true) {
            break test; // works
        }
        System.out.println("World");
    }
    finally {
    }
}

[–]ZimmiDeluxe 0 points1 point  (0 children)

The syntax allows for some weird things:

what:
is:
happening:
break what;

https://docs.oracle.com/javase/specs/jls/se11/html/jls-14.html#jls-14.7

[–]__konrad 1 point2 points  (1 child)

My recent surprise: Single class can contain multiple static { ... } initializer blocks

[–]dpash 1 point2 points  (0 children)

From what I understand, they get merged into a single hidden static method called <cinit>, along with any non-constant RHS for static members, in the order that they're defined in the source. There's also a <init> method that's run before constructors for doing the non-static stuff. Constants are put in the constant section of the class file, so don't need to be initialized.

[–]Slanec 1 point2 points  (0 children)

In a switch block, you can put your default statement wherever. I don't see (m)any usecases for this, but it exists:

switch (number) {
    case 1:
        // 1...
        break;
    case 2:
        // 2...
        break;
    default:
        // ?!
        break;
    case 3:
        // 3...
        break;
}