Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Null pointer exception on contains on set #1186

Closed
1 task done
PGSmink opened this issue Oct 26, 2024 · 4 comments
Closed
1 task done

Null pointer exception on contains on set #1186

PGSmink opened this issue Oct 26, 2024 · 4 comments
Labels
question Further information is requested

Comments

@PGSmink
Copy link

PGSmink commented Oct 26, 2024

Please provide a brief summary of the bug

    Set<String> failSet = Set.of("fail");
    Set<String> okSet= new HashSet<>();
    okSet.add("ok");
    System.out.println(okSet.contains(null)); // print false
    System.out.println(failSet.contains(null)); // NPE this should also print false
    
    Despite Set.of(null) is not allowed, contains(null) should not crash

Did you test with the latest update version?

  • Yes

Please provide steps to reproduce where possible

No response

Expected Results

print false

Actual Results

Cannot invoke "Object.equals(Object)" because "o" is null
java.lang.NullPointerException: Cannot invoke "Object.equals(Object)" because "o" is null
at java.base/java.util.ImmutableCollections$Set12.contains(ImmutableCollections.java:817)

What Java Version are you using?

openjdk 23.0.1 2024-10-15 OpenJDK Runtime Environment Temurin-23.0.1+11 (build 23.0.1+11) OpenJDK 64-Bit Server VM Temurin-23.0.1+11 (build 23.0.1+11, mixed mode, sharing)

What is your operating system and platform?

Ubuntu 24.04 .1LTS

How did you install Java?

No response

Did it work before?

No response

Did you test with other Java versions?

No response

Relevant log output

No response

@PGSmink PGSmink added the bug Something isn't working label Oct 26, 2024
@jerboaa jerboaa added question Further information is requested and removed bug Something isn't working labels Oct 29, 2024
@jerboaa
Copy link

jerboaa commented Oct 29, 2024

Please see the Javadocs:

Set.of() javadoc reads:

Returns an unmodifiable set containing one element. See Unmodifiable Sets for details.

... which links to the javadoc of Unmodifiable Sets, which specifically says:

- [...]
- They disallow null elements. Attempts to create them with null elements result in NullPointerException. 
- [...]

As they disallow null elements, it makes no sense to allow checking for null. Either way, please bring this issue to [email protected] upstream. This is where you ought to discuss changes to core collections. Thank you!

@jerboaa jerboaa closed this as completed Oct 29, 2024
@blacelle
Copy link

As they disallow null elements, it makes no sense to allow checking for null.

I do not understand this logic. As they do not allow null elements, any operation trying to insert a null should throw. Though, read operations should just read. But as you say, this is a matter for upstream.

@PGSmink
Copy link
Author

PGSmink commented Nov 20, 2024

The point is I use the Set interface, so I have no Idea the set was created using Set.Of(). It can contain null if created by other Set implementations. I worked around it by using streams. (So it breaks the Set interface)

@blacelle
Copy link

(I'm also moving various usages away from java.util.Set.of() due to such behavior).

It can contain null if created by other Set implementations.

I guess not. The issue is not creating a Set with null. The issue is reading a Set (not holding nulls) with .contains(null), the null-ref coming from possibly anywhere.

This is also referred in https://stackoverflow.com/questions/70838768/why-list-containsnull-throwing-null-pointer-exception

The valid point is in https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/util/Collection.html#optional-restrictions:

Attempting to query the presence of an ineligible element may throw an exception, or it may simply return false; some implementations will exhibit the former behavior and some will exhibit the latter.

I have hard times understanding the benefits of throwing rather than returning false, especially in the era of lambda and the ability to call Set.contains as a Predicate. The flexibility of the contract (and and differing behavior through the JDK) leads to such inconsistant behaviors.

Though, it is a feature as per OpenJDK choices, and not a bug in Adoptium binaries. (Just to make it clear to future readers, including myself when I'll get hit again by this item).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
question Further information is requested
Projects
None yet
Development

No branches or pull requests

3 participants