using null type annotations in practice
play

Using null type annotations in practice Till Brychcy, Mercateo - PowerPoint PPT Presentation

Using null type annotations in practice Till Brychcy, Mercateo 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


  1. Using null type annotations in practice Till Brychcy, Mercateo EclipseCon Europe, 2017

  2. • 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 EclipseCon Europe, 2017

  3. 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") EclipseCon Europe, 2017

  4. Before null annotations /** * * @param catalogID * @param groupID * @param searchSpec * (may be null) * @param minIndex * @param maxIndex * @param sortBy * @param sortAscending * @return String */ EclipseCon Europe, 2017

  5. Null annotation advantages • One thing less to worry about • Code that is easier to understand, change and debug • No more NullPointerException • Fewer other bugs EclipseCon Europe, 2017

  6. Null annotations disadvantages • Compiler sometimes needs help: Avoid some code patterns • Syntax a bit ugly EclipseCon Europe, 2017

  7. Newer languages: nice syntax • kotlin • var x: String? = null; • swift • var x: String? = nil; • c# (announced for version 8) • string? x = null; EclipseCon Europe, 2017

  8. Null Annotations • Normal use: @NonNullByDefault + @Nullable • @NonNull: only for type parameters and during migration EclipseCon Europe, 2017

  9. 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 { } EclipseCon Europe, 2017

  10. 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; } } EclipseCon Europe, 2017

  11. 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; } } EclipseCon Europe, 2017

  12. 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; } } EclipseCon Europe, 2017

  13. @NonNullByDefault defaults public 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 }; } EclipseCon Europe, 2017

  14. 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" EclipseCon Europe, 2017

  15. Free Type variables and extends @Nullable With 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 EclipseCon Europe, 2017

  16. 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) EclipseCon Europe, 2017

  17. @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 EclipseCon Europe, 2017

  18. 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 EclipseCon Europe, 2017

  19. EclipseCon Europe, 2017

  20. EclipseCon Europe, 2017

  21. Why custom annotations • Di ff erent defaults for @NonNullByDefault (e.g. exclude FIELD) • @Retention(RUNTIME) for testing framework • Easier to accept for users of other IDEs EclipseCon Europe, 2017

  22. Workspace-wide EEA for the JDK EclipseCon Europe, 2017

  23. EclipseCon Europe, 2017

  24. EclipseCon Europe, 2017

  25. 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 EclipseCon Europe, 2017

  26. 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) EclipseCon Europe, 2017

  27. 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 EclipseCon Europe, 2017

  28. 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 EclipseCon Europe, 2017

  29. 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 EclipseCon Europe, 2017

  30. @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) EclipseCon Europe, 2017

  31. 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 EclipseCon Europe, 2017

Download Presentation
Download Policy: The content available on the website is offered to you 'AS IS' for your personal information and use only. It cannot be commercialized, licensed, or distributed on other websites without prior consent from the author. To download a presentation, simply click this link. If you encounter any difficulties during the download process, it's possible that the publisher has removed the file from their server.

Recommend


More recommend