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

10 Things I Hate About Java

10 Things I Hate About Java

Avatar for Adele Carpenter

Adele Carpenter

September 24, 2025
Tweet

More Decks by Adele Carpenter

Other Decks in Technology

Transcript

  1. It is NOT about hating Java • An honest look

    at some frustrating aspects of Java • Context to decisions made with respect to design philosophy • Compare choices with C# What is this talk about? https://www.reddit.com/r/ProgrammerHumor/comments/ddc4b0/microso ft _java/
  2. // Java public class Main { public static void main(String[]

    args) { System.out.println("Hello, world!"); } } # Python print("Hello, world!")
  3. // C++ #include <iostream> int main() { std::cout << "Hello,

    world!" << std::endl; return 0; } // Java public class Main { public static void main(String[] args) { System.out.println("Hello, world!"); } }
  4. Smalltalk Earliest and purest OOP language Mesa Structured exception handling,

    concurrency, portable byte code Cedar GC, modularity, type safety and integrated development environment! https://xeroxnostalgia.com/2020/05/24/parc-celebrates-50-years/
  5. 2. Robust and Secure • Automatic garbage collection • Borrowed

    from Cedar and SmallTalk • Java innovations: generational and stop the world collection, heap segmentation, safe points and write barriers • All picked up by C# • Strong compile-time and runtime checking • Borrowed from Cedar and Mesa • Sandbox model • Bytecode veri fi er
  6. Java 1.0 Design goals 1. Simple, Object-Oriented, and Familiar 2.

    Robust and Secure 3. Architecture-Neutral and Portable
  7. 3. Architecture-Neutral and Portable • Java Bytecode • Java Virtual

    Machine (JVM) Speci fi cation • Each OS has own implementation • Similar approach adopted by C# • Microso ft Intermediate Language and Common Language Runtime (CLR)
  8. Java 1.0 Design goals 1. Simple, Object-Oriented, and Familiar 2.

    Robust and Secure 3. Architecture-Neutral and Portable 4. Highly Performant
  9. 4. Highly Performant • Bytecode instruction set compact and e

    ffi cient for interpretation • Just in Time (JIT) compiler • JIT compiler converts bytecode into native machine code at runtime • Not in Java 1.0 • But the design made room for it in future versions • C# 1.0 did ship with JIT compiler • …when it was released 6 years a ft er Java 1.0
  10. Java 1.0 Design goals 1. Simple, Object-Oriented, and Familiar 2.

    Robust and Secure 3. Architecture-Neutral and Portable 4. High Performance 5. Interpreted, Threaded, and Dynamic
  11. 5. Interpreted, Threaded, and Dynamic • Multi-threading that “just worked”

    • Allowed a high degree of interactivity for the end user • Threading model based on Cedar and Mesa • Classes loaded dynamically at runtime via the ClassLoader • C# uses reflection, assemblies, and optional dynamic typing instead
  12. Java 1.0 Design goals 1. Simple, Object-Oriented, and Familiar 2.

    Robust and Secure 3. Architecture-Neutral and Portable 4. High Performance 5. Interpreted, Threaded, and Dynamic https://www.oracle.com/java/technologies/language-environment.html
  13. public class Box<T> { private T value; public Box(T value)

    { this.value = value; } public void printValue() { Console.WriteLine($"Value: {value}"); } public void printType() { Console.WriteLine($"Type of T is: {typeof(T)}"); } }
  14. public class Box<T> { public T Value { get; set;

    } public void PrintValue() { Console.WriteLine($"Value: {Value}"); } public void PrintType() { Console.WriteLine($"Type of T is: {typeof(T)}"); } }
  15. public class BoxPrintDemo { public static void run() { var

    intBox = new Box<int>(42); var stringBox = new Box<string>("Hello"); intBox.printType(); stringBox.printType(); intBox.printValue(); stringBox.printValue(); } }
  16. public class Box<T> { private T value; public Box(T value)

    { this.value = value; } public void printValue() { println("Value: " + value); } public void printType() { println("Type of T is: " + value.getClass()); } }
  17. Box<Integer> intBox = new Box<>(42); Box<String> stringBox = new Box<>("Hello");

    println(intBox.getClass() == stringBox.getClass()); // true // Java
  18. Box<?> intBox = new Box<Integer>(42); if (intBox instanceof Box<Integer>) {

    intBox.printValue(); // compile time error!! // java.lang.Object cannot be safely cast to // javasucks.Box<java.lang.Integer> } // Java
  19. String json = "{\"value\":\"hello\"}"; Box<String> box = mapper.readValue(json, new TypeReference<Box<String>>()

    {}); // Will compile but unsafe Box<String> box = mapper.readValue(json, Box.class); // Java
  20. Box<String> box = mapper.readValue(json, new TypeReference<Box<String>>() {}); // Defines a

    type that extends TypeReference class MyBoxTypeReference extends TypeReference<Box<String>> {} // Jackson then uses reflection TypeReference<Box<String>> ref = new MyBoxTypeReference(); Type type = ref.getType(); // Java
  21. “As sort of a design principle for something lots of

    people were going to use, I’d rather keep the hole with a label on it than do something I know is wrong.” James Gosling Faces of Open Source / Peter Adams
  22. Green Team member “We were right about needing to fi

    nish the language even though it had missing features… there was only about a three month window in which the whole Java phenomenon could have happened. We barely made it… [but] Bill was absolutely right about what Java needs long term.”
  23. “As soon as you get a community around something, you

    have to have conversations with people about how to do this, how to do that. If you do the wrong thing, people get very upset. Once upon a time it was just me, and if I wanted to make a major change to the language, it’d take 10 minutes.” James Gosling Faces of Open Source / Peter Adams
  24. “[the supported proposal] involves no changes at all to the

    VM speci fi cation, and it has a really nice migration story… because the sort of parameterized versions of classes and the non- parameterized versions are compatible in an elegant kind of way.” James Gosling Faces of Open Source / Peter Adams
  25. “Getting a dozen JVM vendors to agree on if, and

    how, type information would be rei fi ed at runtime was a highly questionable proposition.” Brian Goetz, Java Language Architect at Oracle Photo courtesy of Devoxx Belgium 2023: https://www.flickr.com/photos/bejug/53236104163/in/album-72177720311726414
  26. Type Erasure Was The Choice At the given time, with

    the given amount of java code in the world, and the given importance of backwards compatibility, by the given community, generics with type erasure was the choice
  27. • CLR allowed pre- and post-generic code to run side

    by side • Had to recompile or manually cast to expected type • Adding generics to the CLR was a decision that only Microso ft had to make What about C#? They’re all smug af
  28. static String parseSchoolName(String school) throws SchoolParseException { // code goes

    here } static String fetchStudentSchoolName(String studentId) throws IOException { // code goes here }
  29. List<String> localSchools = List.of("SOME SCHOOL", "THE SCHOOL", "A SCHOOL"); List<String>

    studentIds = List.of("student1", "student2", “student3"); return studentIds.stream() .map(SchoolService::fetchStudentSchoolName) .map(SchoolService::parseSchoolName) .filter(localSchools::contains) .toList() .size();
  30. List<String> localSchools = List.of("SOME SCHOOL", "THE SCHOOL", "A SCHOOL"); List<String>

    studentIds = List.of("student1", "student2", “student3"); return studentIds.stream() .map(SchoolService::fetchStudentSchoolName) .map(SchoolService::parseSchoolName) .filter(localSchools::contains) .toList() .size();
  31. static String parseSchoolName(String school) throws SchoolParseException { // code goes

    here } static String fetchStudentSchoolName(String studentId) throws IOException { // code goes here }
  32. return studentIds.stream() .map(student -> { try { return fetchStudentSchoolName(student); }

    catch (IOException e) { throw new RuntimeException(e.getMessage()); } }) .map(school -> { try { return parseSchoolName(school); } catch (SchoolParseException e) { throw new RuntimeException(e.getMessage()); } }) .filter(localSchools::contains) .toList() .size();
  33. Faces of Open Source / Peter Adams “In Java you

    can ignore exceptions, but you have to wilfully do it. You can't accidentally say, "I don't care." You have to explicitly say, "I don't care.” James Gosling
  34. “You don't want a program where in 100 di ff

    erent places you handle exceptions and pop up error dialogs… That's just terrible. The exception handling should be centralised, and you should just protect yourself as the exceptions propagate out to the handler.” Anders Hejlsberg Photo: DBegley, CC BY 2.0, via Wikimedia Commons
  35. @FunctionalInterface public interface ThrowingFun<T, R, E extends Exception> { R

    apply(T t) throws E; } static <T, R> Function<T, R> checkedWrapper(ThrowingFun<T, R, Exception> throwingFun) { return t -> { try { return throwingFun.apply(t); } catch (Exception e) { throw new RuntimeException(e.getMessage()); } }; } int localStudentCount(List<String> studentIds, List<String> localSchools) { return studentIds.stream() .map(checkedWrapper(SchoolService::fetchStudentSchoolName)) .map(checkedWrapper(SchoolService::parseSchoolName)) .filter(localSchools::contains) .toList() .size(); }
  36. package checkedexceptions.utils; import java.util.function.Function; public class CheckedWrapper { public static

    <T, R> Function<T, R> checkedWrapper(ThrowingFun<T, R, Exception> throwingFun) { return t -> { try { return throwingFun.apply(t); } catch (Exception e) { throw new RuntimeException(e.getMessage()); } }; } @FunctionalInterface public interface ThrowingFun<T, R, E extends Exception> { R apply(T t) throws E; } }
  37. static int CountLocalStudents(List<string> studentIds, List<string> localSchools) { using (var context

    = new SchoolDbContext()) { return context.Students // DbSet<Student> .Where(s => studentIds.Contains(s.Id)) .AsEnumerable() .Select(s => SchoolService.ParseSchoolName(s.SchoolName)) .Where(localSchools.Contains) .Count(); } }
  38. static int CountLocalStudents(List<string> studentIds, List<string> localSchools) { using (var context

    = new SchoolDbContext()) { return context.Students // DbSet<Student> .Where(s => studentIds.Contains(s.Id)) .AsEnumerable() .Select(s => SchoolService.ParseSchoolName(s.SchoolName)) .Where(localSchools.Contains) .Count(); } }
  39. static int CountLocalStudents(List<string> studentIds, List<string> localSchools) { using (var context

    = new SchoolDbContext()) { return context.Students // DbSet<Student> .Where(s => studentIds.Contains(s.Id)) .AsEnumerable() .Select(s => SchoolService.ParseSchoolName(s.SchoolName)) .Where(localSchools.Contains) .Count(); } }
  40. And the birth of Java’s type system • Cost of

    memory fetch close to that of arithmetic operations • “Everything is an object” became • “Everything the user can de fi ne is an object” • 8 primitives The 1990s
  41. • Not limited by memory • Performance is hit by

    memory layout and indirection Today Photo: https://local.microso ft .com/nl/blog/frequently-asked-questions-about-our-datacenters/
  42. “We’ve been working on this 10 years which is kind

    of appalling” Brian Goetz at JVM Language Summit 2024 Photo courtesy of Devoxx Belgium 2023: https://www.flickr.com/photos/bejug/53236104163/in/album-72177720311726414
  43. Project Valhalla Deliverables 10 years, *4 JEPs • JEP 401

    (Preview, Java 26?): Value Classes and Objects • Objects that lack identity, and consequentially optimised encodings • JEP 402: Enhanced Primitive Boxing • Allows primitives to be treated more like objects • JEP dra ft : Null-Restricted Value Class Types • Improves the performance of fi elds and arrays with null- restricted value class types • JDK-8303099: Null-Restricted and Nullable Types • Language support for null-aware types and runtime enforcement of null restrictions *plus many more JEPs with preparatory and supporting work
  44. • It’s annoying quirky • It’s evolving - albeit slowly

    • Healthy and mature ecosystem • It’s a product of decisions past • It’s still everywhere Do I really Hate Java? Perhaps, in the same way that I “hate” legacy flagship so ft ware
  45. Resources Demos • https://github.com/adele97/javasucks • https://github.com/adele97/SoCSharpDidntHaveTo Faces of Open Source

    • https://www.facesofopensource.com/james-gosling-2/ • https://www.facesofopensource.com/bill-joy/ 10 things I Hate about You poem • https://poppoetry.substack.com/p/10-things-i-hate-about-you
  46. Resources 1990s / Early Java • https://www.oracle.com/java/technologies/language-environment.html • https://www.infoworld.com/article/2169448/javaone-conference-report.html •

    https://sdtimes.com/browsers/twenty-years-of-java-through-its-creators-eyes/ • https://www.landley.net/history/mirror/java/javaorigin.html • https://web.archive.org/web/20000816155304/http://java.sun.com/features/ 1999/08/futures.html • http://sunsite.uakom.sk/sunworldonline/swol-06-1996/swol-06-java2.html • https://web.archive.org/web/20010105194400/http://java.sun.com/javaone/ javaone96/Gosling.Baratz.html • https://web.archive.org/web/19961020124245/http://www.sun.com/960416/ javaone.html
  47. Resources Type Erasure • https://openjdk.org/projects/valhalla/design-notes/in-defense-of-erasure • https://pizzacompiler.sourceforge.net/doc/pizza-translation.pdf • https://web.archive.org/web/20010803054958/http://jcp.org/jsr/detail/ 14.jsp

    • https://web.archive.org/web/20000305044304/http://www.sys-con.com/java/ javaone/interviews/gosling.html Checked Exceptions • https://www.reddit.com/r/java/comments/1cct4iq/ if_everyone_hates_checked_exceptions_wheres_the/ • https://www.artima.com/articles/failure-and-exceptions
  48. Resources Project Lambda • https://cr.openjdk.org/~briangoetz/lambda/lambda-state- fi nal.html • https://docs.oracle.com/javase/8/docs/api/java/util/function/package- summary.html

    Project Loom (Virtual Threads) • https://openjdk.org/jeps/444 • https://openjdk.org/jeps/491 • https://netflixtechblog.com/java-21-virtual-threads-dude-wheres-my- lock-3052540e231d
  49. Resources Project Valhalla • https://cr.openjdk.org/~jrose/values/values-0.html • https://openjdk.org/projects/valhalla/design-notes/state-of-valhalla/01-background • https://www.youtube.com/watch?v=IF9l8fYfSnI •

    https://www.infoworld.com/article/2337986/project-valhalla-a-look-inside-javas- epic-refactor.html • https://bugs.openjdk.org/browse/JDK-8303099 • https://openjdk.org/projects/valhalla/ • https://openjdk.org/jeps/401 • https://openjdk.org/jeps/402 • https://openjdk.org/jeps/8316779