Top Banner
Using null type annotations in practice Till Brychcy, Mercateo EclipseCon Europe, 2017
34

Using null type annotations in practice...Using null type annotations in practice Till Brychcy, Mercateo EclipseCon Europe, 2017 EclipseCon Europe, 2017 • What they are, why and

May 22, 2020

Download

Documents

dariahiddleston
Welcome message from author
This document is posted to help you gain knowledge. Please leave a comment to let me know what you think about it! Share it to your friends and learn new things together.
Transcript
Page 1: Using null type annotations in practice...Using null type annotations in practice Till Brychcy, Mercateo EclipseCon Europe, 2017 EclipseCon Europe, 2017 • What they are, why and

Using null type annotations in practice

Till Brychcy, Mercateo

EclipseCon Europe, 2017

Page 2: Using null type annotations in practice...Using null type annotations in practice Till Brychcy, Mercateo EclipseCon Europe, 2017 EclipseCon Europe, 2017 • What they are, why and

EclipseCon Europe, 2017

• What they are,  why and when to use them

• @Nullable vs. java.util.Optional

• Configuration choices

• Switching from declaration annotations to type annotations

• How to get warning free code - Code Patterns and Antipatterns

• Free Type variables and extends @Nullable

• Arrays

• Improvements released with Oxygen

• Preview to  Photon

Page 3: Using null type annotations in practice...Using null type annotations in practice Till Brychcy, Mercateo EclipseCon Europe, 2017 EclipseCon Europe, 2017 • What they are, why and
Page 4: Using null type annotations in practice...Using null type annotations in practice Till Brychcy, Mercateo EclipseCon Europe, 2017 EclipseCon Europe, 2017 • What they are, why and

EclipseCon Europe, 2017

Some Statistics• First commit: Sep 18 2002

• First commit with null annotations: Jul 2 2012

• Switched to java 8 and null type annotations: Apr 15 2015

• Sample size: 7866 java files (approx. 20% of total code base)

• 3025 files use @NonNullByDefault (no package annotations)

• 10910 @Nullable annotation in 2175 files

• 1970 @NonNull annotations in 709 files

• 1070 @SuppressWarnings(„null")

Page 5: Using null type annotations in practice...Using null type annotations in practice Till Brychcy, Mercateo EclipseCon Europe, 2017 EclipseCon Europe, 2017 • What they are, why and

EclipseCon Europe, 2017

Before null annotations /** * * @param catalogID * @param groupID * @param searchSpec * (may be null) * @param minIndex * @param maxIndex * @param sortBy * @param sortAscending * @return String */

Page 6: Using null type annotations in practice...Using null type annotations in practice Till Brychcy, Mercateo EclipseCon Europe, 2017 EclipseCon Europe, 2017 • What they are, why and

EclipseCon Europe, 2017

Null annotation advantages

• One thing less to worry about

• Code that is easier to understand, change and debug

• No more NullPointerException

• Fewer other bugs

Page 7: Using null type annotations in practice...Using null type annotations in practice Till Brychcy, Mercateo EclipseCon Europe, 2017 EclipseCon Europe, 2017 • What they are, why and

EclipseCon Europe, 2017

Null annotations disadvantages

• Compiler sometimes needs help: Avoid some code patterns

• Syntax a bit ugly

Page 8: Using null type annotations in practice...Using null type annotations in practice Till Brychcy, Mercateo EclipseCon Europe, 2017 EclipseCon Europe, 2017 • What they are, why and

EclipseCon Europe, 2017

Newer languages: nice syntax• kotlin

• var x: String? = null;

• swift

• var x: String? = nil;

• c# (announced for version 8)

• string? x = null;

Page 9: Using null type annotations in practice...Using null type annotations in practice Till Brychcy, Mercateo EclipseCon Europe, 2017 EclipseCon Europe, 2017 • What they are, why and

EclipseCon Europe, 2017

Null Annotations

• Normal use: @NonNullByDefault + @Nullable

• @NonNull: only for type parameters and during migration

Page 10: Using null type annotations in practice...Using null type annotations in practice Till Brychcy, Mercateo EclipseCon Europe, 2017 EclipseCon Europe, 2017 • What they are, why and

EclipseCon Europe, 2017

Declaration vs. type annotations• Declaration annotation:

@Target({ FIELD, METHOD, PARAMETER, LOCAL_VARIABLE }) public @interface Nullable { }

• Type annotation:@Target({ TYPE_USE }) public @interface Nullable { }

• "Mixed" annotations are allowed by Java, but bad as null annotations:@Target({ TYPE_USE, FIELD, METHOD, PARAMETER, LOCAL_VARIABLE }) public @interface Nullable { }

Page 11: Using null type annotations in practice...Using null type annotations in practice Till Brychcy, Mercateo EclipseCon Europe, 2017 EclipseCon Europe, 2017 • What they are, why and

EclipseCon Europe, 2017

Declaration annotation usages@NonNullByDefault public class Example { @Nullable String field;

@Nullable String add(@Nullable String arg1, List<String> list, @Nullable String[] array) { // just to show the syntax (local variables usually don't need annotations) @Nullable String local = arg1;

list.add(null); // is this OK? if(array != null) { array[0] = null; // or this? }

return local; } }

Page 12: Using null type annotations in practice...Using null type annotations in practice Till Brychcy, Mercateo EclipseCon Europe, 2017 EclipseCon Europe, 2017 • What they are, why and

EclipseCon Europe, 2017

Equivalent with type annotations@NonNullByDefault({ FIELD, PARAMETER, RETURN_TYPE }) public class Example { @Nullable String field;

@Nullable String add(@Nullable String arg1, List<String> list, String @Nullable [] array) { // just to show the syntax (local variables usually don't need annotations) @Nullable String local = arg1;

list.add(null); // is this OK? if(array != null) { array[0] = null; // or this? }

return local; } }

Page 13: Using null type annotations in practice...Using null type annotations in practice Till Brychcy, Mercateo EclipseCon Europe, 2017 EclipseCon Europe, 2017 • What they are, why and

EclipseCon Europe, 2017

Completely annotated@NonNullByDefault({ FIELD, PARAMETER, RETURN_TYPE, ARRAY_CONTENTS, TYPE_ARGUMENT }) public class Example { @Nullable String field;

@Nullable String add(@Nullable String arg1, List<@Nullable String> list, @Nullable String @Nullable [] array) { // just to show the syntax (local variables usually don't need annotations) @Nullable String local = arg1;

list.add(null); // OK! if (array != null) { array[0] = null; // OK! }

return local; } }

Page 14: Using null type annotations in practice...Using null type annotations in practice Till Brychcy, Mercateo EclipseCon Europe, 2017 EclipseCon Europe, 2017 • What they are, why and

EclipseCon Europe, 2017

@NonNullByDefault defaultspublic enum DefaultLocation { PARAMETER, RETURN_TYPE, FIELD, TYPE_PARAMETER, TYPE_BOUND, TYPE_ARGUMENT, ARRAY_CONTENTS }

@Target({ ElementType.PACKAGE, ElementType.TYPE, ElementType.METHOD, ElementType.CONSTRUCTOR, ElementType.FIELD, ElementType.LOCAL_VARIABLE }) public @interface NonNullByDefault { DefaultLocation[] value() default { DefaultLocation.PARAMETER, DefaultLocation.RETURN_TYPE, DefaultLocation.FIELD, DefaultLocation.TYPE_ARGUMENT, DefaultLocation.TYPE_BOUND };

}

Page 15: Using null type annotations in practice...Using null type annotations in practice Till Brychcy, Mercateo EclipseCon Europe, 2017 EclipseCon Europe, 2017 • What they are, why and

EclipseCon Europe, 2017

Type bounds: "extends"

• Think in types: Object x = ""; // OK String s = new Object(); // error

@Nullable String s1 = ""; // OK @NonNull String s2 = null; // error

⇒"String extends Object" corresponds to "@NonNull String extends @Nullable String"

• So:"@NonNull String extends @NonNull Object""@NonNull String extends @Nullable Object""@Nullable String extends @Nullable Object"

Page 16: Using null type annotations in practice...Using null type annotations in practice Till Brychcy, Mercateo EclipseCon Europe, 2017 EclipseCon Europe, 2017 • What they are, why and

EclipseCon Europe, 2017

Free Type variables and extends @NullableWith standard @NonNullByDefault:

• class List<T> {…} T can be @Nullable or @NonNull

• user chooses List<@Nullable Integer> or List<String> (=List<@NonNull String>)

• class NumberList<T extends Number>{…} T must be @NonNull

• same as class NumberList<T extends @NonNull Number>

• same as NumberList<@NonNull T>

• class NumberList<@Nullable Number>: T must be @Nullable

• class NumberList<T extends @Nullable Number>: T can be @Nullable or @NonNull

Page 17: Using null type annotations in practice...Using null type annotations in practice Till Brychcy, Mercateo EclipseCon Europe, 2017 EclipseCon Europe, 2017 • What they are, why and

EclipseCon Europe, 2017

Principles• Warning free workspace

• @NonNullByDefault in new code

• Add @NonNullByDefault to existing code with other changes

• If necessary, annotate related code

• @SuppressWarnings("null") is OK in certain situations

• Must be easy to use with maven (now: no maven settings at all, IDE-only)

Page 18: Using null type annotations in practice...Using null type annotations in practice Till Brychcy, Mercateo EclipseCon Europe, 2017 EclipseCon Europe, 2017 • What they are, why and

EclipseCon Europe, 2017

@SuppressWarnings

• Generated code: hashCode & equals

• stream.filter(x->x != null).

• optional.orElse(null)

• Tests (still add @NonNullByDefault)

• Overrides for which we don’t want to add external annotations

Page 19: Using null type annotations in practice...Using null type annotations in practice Till Brychcy, Mercateo EclipseCon Europe, 2017 EclipseCon Europe, 2017 • What they are, why and

EclipseCon Europe, 2017

Configuration choices

• Enable annotations based analysis in workspace settings (not project)

• File template with @NonNullByDefault

• DefaultLocation as favorites

• External annotations added to the JDK in Workspace

• Hide INFO in problems view

Page 20: Using null type annotations in practice...Using null type annotations in practice Till Brychcy, Mercateo EclipseCon Europe, 2017 EclipseCon Europe, 2017 • What they are, why and

EclipseCon Europe, 2017

Page 21: Using null type annotations in practice...Using null type annotations in practice Till Brychcy, Mercateo EclipseCon Europe, 2017 EclipseCon Europe, 2017 • What they are, why and

EclipseCon Europe, 2017

Page 22: Using null type annotations in practice...Using null type annotations in practice Till Brychcy, Mercateo EclipseCon Europe, 2017 EclipseCon Europe, 2017 • What they are, why and

EclipseCon Europe, 2017

Why custom annotations

• Different defaults for @NonNullByDefault (e.g. exclude FIELD)

• @Retention(RUNTIME) for testing framework

• Easier to accept for users of other IDEs

Page 23: Using null type annotations in practice...Using null type annotations in practice Till Brychcy, Mercateo EclipseCon Europe, 2017 EclipseCon Europe, 2017 • What they are, why and

EclipseCon Europe, 2017

Workspace-wide EEA for the JDK

Page 24: Using null type annotations in practice...Using null type annotations in practice Till Brychcy, Mercateo EclipseCon Europe, 2017 EclipseCon Europe, 2017 • What they are, why and

EclipseCon Europe, 2017

Page 25: Using null type annotations in practice...Using null type annotations in practice Till Brychcy, Mercateo EclipseCon Europe, 2017 EclipseCon Europe, 2017 • What they are, why and

EclipseCon Europe, 2017

Page 26: Using null type annotations in practice...Using null type annotations in practice Till Brychcy, Mercateo EclipseCon Europe, 2017 EclipseCon Europe, 2017 • What they are, why and

EclipseCon Europe, 2017

Challenges when switching to type annotations

• Syntax for qualified names java.io.@Nullable File file (easy to fix)

• Syntax for Arrays (we used some regular expressions)

• Generics:

• Map.get() (configure external annotations)

• Generics that take a .class literal

Page 27: Using null type annotations in practice...Using null type annotations in practice Till Brychcy, Mercateo EclipseCon Europe, 2017 EclipseCon Europe, 2017 • What they are, why and

EclipseCon Europe, 2017

Arrays

• @Nullable String @NonNull [] x;

• Problem during migration from declaration annotations

• Problem: new @NonNull String[10] contains nulls

• methods that don't care about nullness about array contents

<T extends @Nullable String> @NonNull String concat(T[] strings)

Page 28: Using null type annotations in practice...Using null type annotations in practice Till Brychcy, Mercateo EclipseCon Europe, 2017 EclipseCon Europe, 2017 • What they are, why and

EclipseCon Europe, 2017

Observed null parameter handling

1. Don't think about it, let method caller guess

2. if(param==null) return null

3. Objects.requireNonNull(param)

4. try{…}catch(Exception e){…}

5. Assume nonnull, use javadoc for nullable

Page 29: Using null type annotations in practice...Using null type annotations in practice Till Brychcy, Mercateo EclipseCon Europe, 2017 EclipseCon Europe, 2017 • What they are, why and

EclipseCon Europe, 2017

Some Antipatterns• No correlation analysis

• boolean b=(x != null); if(b) {x.someMethod()}

• int length = array == null ? 0 : array.length; for (int i = 0; i < length; i++)…

• No intraprocedural analysis:

• init(…)-methods in constructor

• if(isValid(x)) { x.something() }

boolean isValid(Some x) {return x != null && …}

• Event callbacks without context: e.g., org.xml.sax.ContentHandler

• Struts form beans

• some builder patterns

Page 30: Using null type annotations in practice...Using null type annotations in practice Till Brychcy, Mercateo EclipseCon Europe, 2017 EclipseCon Europe, 2017 • What they are, why and

EclipseCon Europe, 2017

Some Good Patterns

• Empty string / collection / NOP-implementation instead of null

• final fields or even completely immutable fields

• Avoid null literals except to define class specific NULL constants

Page 31: Using null type annotations in practice...Using null type annotations in practice Till Brychcy, Mercateo EclipseCon Europe, 2017 EclipseCon Europe, 2017 • What they are, why and

EclipseCon Europe, 2017

@Nullable vs. java.util.Optional• Two solutions for the same topic.

• "Don't care": Convenient mapping to other Optionals

• Code with Optional gets reliable with @NonNullByDefault, so use both

• Use Optional only for return values

• Optional is not Serializable

• @Nullable better when overriding methods

• Problem Optional#orElse (Guava had: #orNull)

Page 32: Using null type annotations in practice...Using null type annotations in practice Till Brychcy, Mercateo EclipseCon Europe, 2017 EclipseCon Europe, 2017 • What they are, why and

EclipseCon Europe, 2017

Improvements in Oxygen• 54 bug fixes and enhancements related to null analysis and null annotations

• Quick Fix to move type annotations

• @NonNullByDefault

• DefaultLocation.ARRAY_CONTENTS implemented

• @Target(ElementType.FIELD) implemented

• @Target(ElementType.LOCAL_VARIABLE) implemented

• No warning for "T extends @Nullable String"

• Many quick assists avoid creating redundant @NonNull

Page 33: Using null type annotations in practice...Using null type annotations in practice Till Brychcy, Mercateo EclipseCon Europe, 2017 EclipseCon Europe, 2017 • What they are, why and

EclipseCon Europe, 2017

• extract local variable

• create local variable for missing symbol

• create field for missing symbol

• create parameter for missing symbol

• override method

• create method (parameters, details of return type)

• change method: (add parameter)

• change method: (change parameter)

• assign expression to new local variable

• create constructor using fields

• generate delegate methods

• create method

• type change and signature change

• introduce parameter object

• extract class

Page 34: Using null type annotations in practice...Using null type annotations in practice Till Brychcy, Mercateo EclipseCon Europe, 2017 EclipseCon Europe, 2017 • What they are, why and

EclipseCon Europe, 2017

Preview to Photon

• Quick fix to add @NonNullByDefault to package

• Java 9: @NonNullByDefault in module-info.java

• Maybe support 3rd-party NonNullByDefault variations (TypeQualifierDefault)

• More quick assists that avoid creating redundant @NonNull