A better list for this discussion is amber-dev. Regards, Paul
On 5/26/26, 8:28 PM, "[email protected] <mailto:[email protected]>" <[email protected] <mailto:[email protected]>> wrote: Hi all, I am a long‑term Java application developer. I would like to share my intuitive thinking about null design from a pure object‑oriented programming perspective. From my understanding of OOP, once a variable is declared as a certain type, it should always represent a valid instance of that type. However, in current Java, when I declare an object variable without immediately constructing a valid instance, it is assigned null by default. In my opinion, null does not belong to this type at all; it is an external state outside the entire object system. This is the root cause of NullPointerException and numerous redundant null checks, which goes against natural OOP intuition. Meanwhile, I really dislike nullable type syntax such as Type?. It artificially splits a single type into two contradictory states, which only confuses code logic and increases developers’ mental burden. My simple expectation for Java is as follows: Instead of assigning an irrelevant null to an uninitialized object field, the language should provide a built‑in none instance that strictly belongs to the target type. This none instance should satisfy the following conditions:1 1. It is exactly an instance of the type itself 2. It is a valid object so all methods can be called safely 3. It supports natural chaining and automatic short‑circuit when empty Such a design not only returns to the essence of OOP, but also fits naturally with current streaming and functional programming styles, resulting in cleaner and more consistent code. Here are practical examples from daily development to illustrate my idea clearly: Current cumbersome Java code (null checks are mandatory to avoid NPE) // Declared only, default value is null User user; // Direct call will throw NPE String username = user.getName(); // Verbose defensive null check String username = ""; if (user != null) { username = user.getName(); } // Awkward Optional wrapping Optional<User> optUser = Optional.ofNullable(user); String username = optUser.map(User::getName).orElse(""); optUser.ifPresent(System.out::println); // Return null when no matching data found public User findUser(Long id) { return null; } My ideal natural style with built‑in none instance // Uninitialized, default is the native none instance of User, not null User user; // Safe direct call with no exception String username = user.getName(); // Native fluent chaining with automatic short‑circuit String username = user.map(User::getName).orElse(""); // Execute logic only when a valid instance exists user.ifPresent(System.out::println); // Check for native none instance if (user.isNone()) { // Business logic for uninitialized state } // Return type-owned none instance instead of null public User findUser(Long id) { return User.None; } Confusing Type? design (type splitting leads to high mental load) // One single type is split into User and User? User? user = null; // Constantly need to handle nullable differences String username = user?.getName(); // Developers always struggle to judge whether it is a valid object // Essentially still dealing with non‑object null state, not real OOP To sum up: In object‑oriented design, the empty state of a type should still be an instance of that type, rather than a meaningless null pointer or a confusing split‑type syntax. This is only my personal experience and intuitive design idea as an application developer. I do not discuss any underlying implementation details. I look forward to community discussion and feedback. Best regards A Java Backend Developer
