Upgrade to Pro — share decks privately, control downloads, hide ads and more …

2025-java-does-what-now.pdf

Avatar for Jeanne Boyarsky Jeanne Boyarsky
September 11, 2025
6

 2025-java-does-what-now.pdf

Avatar for Jeanne Boyarsky

Jeanne Boyarsky

September 11, 2025
Tweet

Transcript

  1. https://linktr.ee/jeanneboyarsky 1 Java Does What Now? Java 21 25 edition

    Jeanne Boyarsky 9/11/25 Boston JUG speakerdeck.com/boyarsky
  2. @jeanneboyarsky Scoped Values are Immutable 4 public class ScopedMapMutable1 {

    static final ScopedValue<List<String>> SCOPE = ScopedValue.newInstance(); public static void main(String[] args) { var list = new ArrayList<String>(); list.add("tea party ship"); ScopedValue.where(SCOPE, list).run(() -> { list.remove(0); System.out.println(SCOPE.get()); }); } } Output: []
  3. @jeanneboyarsky Scoped Values are … 5 public class Scoped {

    static final ScopedValue<String> SCOPE = ScopedValue.newInstance(); public static void main(String[] args) { ScopedValue.where(SCOPE, "tea party ship").run(() -> { System.out.println(SCOPE.get()); }); } } Output: tea party ship
  4. @jeanneboyarsky Behavior Explanation 6 1.ScopedValue only provides a getter 2.However

    underlying value is mutable Bonus: same for records public record Mutable(List<String> list) {}
  5. @jeanneboyarsky All you need in the file 8 import module

    java.sql; public class ImportDatabase { public static void main(String[] args) { Date date = new Date(0); System.out.println(date.getClass()); } } Output: java.sql.Date
  6. @jeanneboyarsky All you need in the file 9 import module

    java.sql; import java.util.*; public class ImportDatabase { public static void main(String[] args) { Date date = new Date(0); System.out.println(date.getClass()); } } Output: java.util.Date
  7. @jeanneboyarsky All you need in the file 10 import module

    java.sql; import java.util.*; import java.sql.Date; public class ImportDatabase { public static void main(String[] args) { Date date = new Date(0); System.out.println(date.getClass()); } } Output: java.sql.Date
  8. @jeanneboyarsky All you need in the file 13 void main()

    { IO.println("Intro"); } Output: Intro
  9. @jeanneboyarsky Flexible Constructors 14 public class Flexible { private int

    count; String s = "hello"; Flexible() { count = 0; System.out.print("prolog "); super(); System.out.print("epilog"); } public static void main(String[] args) { Flexible f = new Flexible(); } } Output: prolog epilog
  10. @jeanneboyarsky Traditional Switch 16 String food = "clam chowder"; switch

    (food) { case "clam chowder": System.out.println("get a spoon"); case "pizza": System.out.print("hands good"); } Output: get a spoon hands good
  11. @jeanneboyarsky Null Check 17 String food = "clam chowder"; switch

    (food) { case null: System.out.println("unknown type"); case "clam chowder": System.out.println("get a spoon"); case "pizza": System.out.print("hands good"); } Output: Compiler error
  12. @jeanneboyarsky Switch Expression 18 String food = "clam chowder"; String

    tool = switch (food) { case null -> "unknown type"; case "clam chowder" -> "get a spoon"; case "pizza" -> "hands good"; default -> "unknown type"; }; System.out.println(tool); Output: get a spoon
  13. @jeanneboyarsky Behavior Explanation 19 1.Traditional switch needs break for fall

    through 2.No null when matching String because not non-null compile time expression 3.Null allowed in pattern matching
  14. @jeanneboyarsky Switch Expression 20 String food = "clam chowder"; String

    tool = switch (food) { case null -> "unknown type"; case "clam chowder" -> "get a spoon"; case "pizza" -> "hands good"; }; System.out.println(tool); Output: Compiler error - doesn’t cover all possible inputs
  15. @jeanneboyarsky Switch Expression 21 String food = "clam chowder"; String

    tool = switch (food) { case null -> "unknown type"; case "clam chowder" -> "get a spoon"; case "pizza" -> "hands good"; case Object o -> "unknown type"; }; System.out.println(tool); Output: get a spoon
  16. @jeanneboyarsky Switch Expression 22 String food = "clam chowder"; String

    tool = switch (food) { case null -> "unknown type"; case "clam chowder" -> "get a spoon"; case "pizza" -> "hands good"; case Object _ -> "unknown type"; default -> "unknown type"; }; System.out.println(tool); Output: compile error - unconditional pattern and default label
  17. @jeanneboyarsky Switch Expression 24 public static void main(String[] args) {

    enum Season { WINTER, SPRING, SUMMER, FALL; } var cold = Season.WINTER; var wear = switch (cold) { case WINTER -> "dress warm"; case SPRING, Season.FALL -> "in between"; case Season.SUMMER -> "swim time"; }; System.out.println(wear); } Output: dress warm
  18. @jeanneboyarsky Switch Expression 26 enum Season { WINTER, SPRING, SUMMER,

    FALL; } var cold = Season.WINTER; switch (cold) { case WINTER -> System.out.println("dress warm"); case Season.SUMMER -> System.out.println("swim time"); }; Output: dress warm
  19. @jeanneboyarsky Null vs Default 28 String fish = null; System.out.println(switch

    (fish) { case "Clownfish" -> "Hello"; case null -> "What type of fish are you"; default -> "Goodbye"; }); Output: What type of fish are you?
  20. @jeanneboyarsky Null vs Default 29 String fish = null; System.out.println(switch

    (fish) { case "Clownfish" -> "Hello"; case null -> "What type of fish are you"; }); Output: Compiler error - doesn’t cover all possible inputs
  21. @jeanneboyarsky Null vs Default 30 String fish = null; switch

    (fish) { case “Clownfish": System.out.println(“Hello"); break; case null: System.out.println( "What type of fish are you”); break; default: System.out.println(“Goodbye"); break; } Output: What type of fish are you?
  22. @jeanneboyarsky Null vs Default 31 String fish = null; switch

    (fish) { case “Clownfish": System.out.println(“Hello"); break; case null: System.out.println( "What type of fish are you”); break; } Output: Compiler error - doesn’t cover all possible inputs
  23. @jeanneboyarsky Order 33 Number fish = 10; String name =

    switch(fish) { default -> "default"; case Integer _ -> ""; }; System.out.println(name); Output: compiler error - default dominates
  24. @jeanneboyarsky Order 34 int numFish = 1; switch(numFish) { default:

    System.out.println(“default"); break; case 2: System.out.println("2"); }; Output: default
  25. @jeanneboyarsky Removing in a Loop 37 List<String> list = new

    ArrayList<>(); list.add("red"); list.add("alliance"); list.add("blue"); list.add("alliance"); for(String current : list) { list.remove(current); } System.out.println(list); Output: ConcurrentModificationException
  26. @jeanneboyarsky Removing in a Loop 38 List<String> list = new

    ArrayList<>(); list.add("red"); list.add("alliance"); for(String current : list) { list.remove(current); } System.out.println(list); Output: [alliance]
  27. @jeanneboyarsky Behavior Explanation 39 1.List starts as [red, alliance] 2.First

    iteration through loop, current = red 3.In loop, remove red 4.Now list is [alliance] 5.For loop checks size. 6.Size = 1; already saw one element 7.Done!
  28. @jeanneboyarsky Behavior Explanation 40 1.vs List as [red, alliance, blue,

    alliance] 2.Size = 3 after removal and saw one 3.Not Done! 4.Exception
  29. @jeanneboyarsky Removing in a Loop 41 List<String> list = new

    CopyOnWriteArrayList<>(); list.add("red"); list.add("alliance"); list.add("blue"); list.add("alliance"); for(String current : list) { list.remove(current); } System.out.println(list); Output: []
  30. @jeanneboyarsky Creating a Set 44 String[] words = { "all",

    "the", "words", "in", "the", "world" }; Set<String> set = new HashSet<>( Arrays.asList(words)); System.out.println(set); Output like: [all, the, world, in, words]
  31. @jeanneboyarsky Creating a Set 45 String[] words = { "all",

    "the", "words", "in", "the", "world" }; Set<String> set = Set.of(words); System.out.println(set); Output: IllegalArgumentException: duplicate element: the
  32. @jeanneboyarsky Collector 48 var list = List.of("Tea", "Coffee"); var result

    = list.stream() .sorted() .collect(Collectors.toList()); result.addFirst("Milk"); System.out.println(result); [Milk, Coffee, Tea]
  33. @jeanneboyarsky ToList 49 var list = List.of("Tea", "Coffee"); var result

    = list.stream() .sorted() .toList(); result.addFirst("Milk"); System.out.println(result); UnsupportedOperationException
  34. @jeanneboyarsky Behavior Explanation 50 1.collector(toList()) returns mutable list ex: ArrayList

    2.toList() returns immutable class ex: ImmutableCollections$ListN 3.Be careful for IDE refactor suggestion
  35. @jeanneboyarsky Collection 52 Map<String, String> map = new HashMap<>(); map.put("Red

    Sox", "Boston"); map.put(“Yankees", "NYC"); Set<String> keys = new HashSet<>(map.keySet()); keys.remove(“Yankees"); System.out.println(map); {Yankees=NYC, Red Sox=Boston}
  36. @jeanneboyarsky Collection 53 Map<String, String> map = new HashMap<>(); map.put("Red

    Sox", "Boston"); map.put("Yankees", "NYC"); Set<String> keys = map.keySet(); keys.remove(“Yankees"); System.out.println(map); {Red Sox=Boston}
  37. @jeanneboyarsky Set 56 var nums = new HashSet<>(); nums.add(Math.min(5, 3));

    nums.add(3); System.out.println(nums); Output: [3]
  38. @jeanneboyarsky Set 57 var nums = new HashSet<>(); nums.add(Math.min(5, 3));

    nums.add(Math.round(3.14)); System.out.println(nums); Output: [3, 3]
  39. @jeanneboyarsky var and inference 59 List<Integer> x1 = List.of(); List<Integer>

    x2 = List.of(1, 2, 3); Stream.of(x1, x2) .flatMap(x -> x.stream()) .map(x -> x + 1) .forEach(System.out::print); Output: 234
  40. @jeanneboyarsky var and inference 60 List<Integer> x1 = List.of(); var

    x2 = List.of(1, 2, 3); Stream.of(x1, x2) .flatMap(x -> x.stream()) .map(x -> x + 1) .forEach(System.out::print); Output: 234
  41. @jeanneboyarsky var and inference 61 var x1 = List.of(); var

    x2 = List.of(1, 2, 3); Stream.of(x1, x2) .flatMap(x -> x.stream()) .map(x -> x + 1) .forEach(System.out::print); Compiler error: Operator ‘+’ cannot be applied to capture<?>, int
  42. @jeanneboyarsky Behavior Explanation 62 1.var x2 = List.of(1,2,3) 2.x2 is

    a List<Integer> 3.var x1 = List.of() 4.x1 is a not a List<Integer> 5.Stream.of(x1, x2) is a Stream<List<? extends Object>> 6.flatMap makes Stream<? extends Object> 7.Object doesn’t go with +
  43. @jeanneboyarsky Sorting Characters 64 Stream<String> ohMy = Stream.of( "lions", "tigers",

    "bears"); Comparator<Character> c = Comparator.naturalOrder(); System.out.println(ohMy.collect( Collectors.groupingBy(String::length, Collectors.mapping(s -> s.charAt(0), Collectors.minBy(c))))); Output: {5=Optional[b], 6=Optional[t]}
  44. @jeanneboyarsky Sorting Characters 65 Stream<String> ohMy = Stream.of( "lions", "tigers",

    "bears"); System.out.println(ohMy.collect( Collectors.groupingBy(String::length, Collectors.mapping(s -> s.charAt(0), Collectors.minBy( Comparator.naturalOrder()))))); Compiler error No suitable method found for….
  45. @jeanneboyarsky The actual message 66 Error:(18, 51) java: no suitable

    method found for groupingBy(String::length,java.util.stream.Collector<java.lang.Object,capt ure#1 of ?,java.util.Optional<T>>) method java.util.stream.Collectors.<T,K>groupingBy(java.util.function.Function<? super T,? extends K>) is not applicable (cannot infer type-variable(s) T,K (actual and formal argument lists differ in length)) method java.util.stream.Collectors.<T,K,A,D>groupingBy(java.util.function.Function <? super T,? extends K>,java.util.stream.Collector<? super T,A,D>) is not applicable (inference variable U has incompatible upper bounds java.lang.Object,java.lang.Comparable<? super T>,T,T)…
  46. @jeanneboyarsky The other message 67 Error:(19, 52) java: cannot find

    symbol symbol: method charAt(int) location: variable s of type java.lang.Object
  47. @jeanneboyarsky Behavior Explanation 68 1.char != Character Inferred type check

    fails 2.Propagates error to other call 3.But, this suggests a workaround…
  48. @jeanneboyarsky Sorting Characters 69 Stream<String> ohMy = Stream.of( "lions", "tigers",

    "bears"); System.out.println(ohMy.collect( Collectors.groupingBy(String::length, Collectors.mapping((String s) -> s.charAt(0), Collectors.minBy( Comparator.naturalOrder()))))); Output: {5=Optional[b], 6=Optional[t]}
  49. @jeanneboyarsky Overloading 71 public void check(Number number) { System.out.print("Number ");

    } public void check(Integer integer) { System.out.print("Integer "); } public void delegator(Number number) { check(number); } Integer num = Integer.valueOf(42); Overloading target = new Overloading(); target.check(num); target.delegator(num); Output: Integer Number
  50. @jeanneboyarsky Overloading 72 public void check(Number number) { System.out.print(“Number ");

    } public void check(Integer integer) { System.out.print(“Integer "); } public void delegator(Number number) { check(number); } Number num = Integer.valueOf(42); Overloading target = new Overloading(); target.check(num); target.delegator(num); Output: Number Number
  51. @jeanneboyarsky Overloading 73 public void check(Number number) { System.out.print(“Number ");

    } public void check(Integer integer) { System.out.print(“Integer "); } public void delegator(Number number) { check(number); } var num = Integer.valueOf(42); var target = new Overloading(); target.check(num); target.delegator(num); Output: Integer Number
  52. @jeanneboyarsky Behavior Explanation 74 1.Method chosen at compile time, not

    runtime. 2.(vs polymorphism on objects) 3.var uses Integer so same as example 1
  53. @jeanneboyarsky Equality 76 var int1 = Integer.valueOf(8); var int2 =

    Integer.valueOf(8); System.out.println((int1 == int2) + " " + int1.equals(int2)); true true
  54. @jeanneboyarsky Equality 77 var int1 = Integer.valueOf(8_000); var int2 =

    Integer.valueOf(8_000); System.out.println((int1 == int2) + " " + int1.equals(int2)); false true
  55. @jeanneboyarsky URL Equality 80 var url1 = new URL("https://google.com"); var

    url2 = new URL("https://google.com"); System.out.println(url1.equals(url2)); Output: true
  56. @jeanneboyarsky URL Equality 81 var url1 = new URL("cloudURL"); var

    url2 = new URL("cloudURL"); System.out.println(url1.equals(url2)); Output: false if DNS resolution changes during program
  57. @jeanneboyarsky Behavior Explanation 82 1.URL’s equals method calls the URLStreamHandler’s

    equals method 2.Which uses DNS resolution 3.Cloud URLs change often Instead, use URI https://news.ycombinator.com/item? id=21765788
  58. @jeanneboyarsky Week of Year 84 var xmasEve = LocalDate.of(2025, Month.DECEMBER,

    24); var weekFields = WeekFields.of(Locale.getDefault()); int weekNumber = xmasEve.get( weekFields.weekOfWeekBasedYear()); int week = xmasEve.get( weekFields.weekOfYear()); System.out.println(weekNumber + " " + week); Output: 52 52
  59. @jeanneboyarsky Week of Year 85 var newYearsEve = LocalDate.of(2025, Month.DECEMBER,

    31); var weekFields = WeekFields.of(Locale.getDefault()); int weekNumber = newYearsEve.get( weekFields.weekOfWeekBasedYear()); int week = newYearsEve.get( weekFields.weekOfYear()); System.out.println(weekNumber + " " + week); Output: 1 53
  60. @jeanneboyarsky Behavior Explanation 86 1.Most years are 52 weeks +

    1 day 2.2025 started on a Wednesday. 3.The week based week starts the Sun before 4.Whereas weekOfYear() returns 1-54
  61. @jeanneboyarsky Week of Year 87 var xmasEve = LocalDate.of( 2025,

    Month.DECEMBER, 24); var format = DateTimeFormatter.ofPattern("yyyy-MM-dd"); var format2 = DateTimeFormatter.ofPattern("YYYY-MM-dd"); System.out.println(xmasEve.format(format) + " " + xmasEve.format(format2)); Output: 2025-12-24 2025-12-24
  62. @jeanneboyarsky Week of Year 88 var newYearsEve = LocalDate.of(2025, Month.DECEMBER,

    31); var format = DateTimeFormatter.ofPattern("yyyy-MM-dd"); var format2 = DateTimeFormatter.ofPattern("YYYY-MM-dd"); System.out.println( newYearsEve.format(format) + " " + newYearsEve.format(format2)); Output: 2025-12-31 2026-12-31
  63. @jeanneboyarsky Behavior Explanation 89 1.y is year 2.Y is week

    of year 3.Be careful with week of year!
  64. @jeanneboyarsky JDBC 91 PreparedStatement stmt = conn.prepareStatement( "update mytable set

    updated = now()"); try (stmt) { stmt.executeUpdate(); } “Good”
  65. @jeanneboyarsky JDBC 92 PreparedStatement stmt = conn.prepareStatement( "update mytable set

    updated = now()" + " where key = ?"); stmt.setString(1, "abc"); try (stmt) { stmt.executeUpdate(); } Resource leak!
  66. @jeanneboyarsky Behavior Explanation 93 1.What happens if an exception is

    thrown while calling the PreparedStatement setter? 2.The try-with-resources doesn’t run 3.Resource leak!
  67. @jeanneboyarsky JDBC 94 PreparedStatement stmt = conn.prepareStatement( "update mytable set

    updated = now()" + " where key = ?"); try (stmt) { stmt.setString(1, "abc"); stmt.executeUpdate(); } “good”
  68. @jeanneboyarsky IO 95 try (BufferedReader reader = Files.newBufferedReader(path)) { String

    line = null; while ((line = reader.readLine())!= null) { // process line } } No leak
  69. @jeanneboyarsky Behavior Explanation 97 1.Resource not closed by terminal operation

    2.Affects 1.find() 2.lines() 3.list() 4.newDirectoryStream() 5.walk()
  70. @jeanneboyarsky Behavior Explanation 102 1.Can’t do ++ twice 2.team++ +

    ++team means 1.5++ + ++5 2.5 + 7 3.12 4.And team is now 7