Communities

Writing
Writing
Codidact Meta
Codidact Meta
The Great Outdoors
The Great Outdoors
Photography & Video
Photography & Video
Scientific Speculation
Scientific Speculation
Cooking
Cooking
Electrical Engineering
Electrical Engineering
Judaism
Judaism
Languages & Linguistics
Languages & Linguistics
Software Development
Software Development
Mathematics
Mathematics
Christianity
Christianity
Code Golf
Code Golf
Music
Music
Physics
Physics
Linux Systems
Linux Systems
Power Users
Power Users
Tabletop RPGs
Tabletop RPGs
Community Proposals
Community Proposals
tag:snake search within a tag
answers:0 unanswered questions
user:xxxx search by author id
score:0.5 posts with 0.5+ score
"snake oil" exact phrase
votes:4 posts with 4+ votes
created:<1w created < 1 week ago
post_type:xxxx type of post
Search help
Notifications
Mark all as read See all your notifications »
Q&A

Welcome to Software Development on Codidact!

Will you help us build our independent community of developers helping developers? We're small and trying to grow. We welcome questions about all aspects of software development, from design to code to QA and more. Got questions? Got answers? Got code you'd like someone to review? Please join us.

Post History

66%
+2 −0
Q&A Trouble understanding java lambdas and generics

Unbounded wildcards are not equivalent to Object. When you give code a type, you are typing the variable, not the value. So Function<Object, Object> code means that it's valid to assign to t...

posted 11mo ago by r~~‭  ·  edited 11mo ago by r~~‭

Answer
#3: Post edited by user avatar r~~‭ · 2025-10-13T18:25:55Z (11 months ago)
Minor clarification
  • Unbounded wildcards are not equivalent to `Object`.
  • When you give `code` a type, you are typing the *variable*, not the *value*. So `Function<Object, Object> code` means that it's valid to assign to the `code` variable any function value that can accept an `Object` and return an `Object`, and therefore it's valid to apply `code` to any `Object` (which is, as you note, any non-primitive value). To emphasize: it *must* hold a function that can accept *any* `Object`, and the compiler will enforce this—it can't hold a function that only accepts `Double`s, for example, because such a function would complain if you gave it a `String`, even though all `String`s are `Object`s.
  • On the other hand, `Function<?, ?> code` means that it's valid to assign to the `code` variable any function... at all! It could be a function that can accept an `Object`. But it could also be a function that can *only* accept certain subtypes of `Object`, like `String` in your case. The *value* would have a more restrictive run-time type than the *variable* in that case, but that's legal, just like it's legal to assign a `String` value to a variable of type `Object`. So in your first commented line:
  • > ```java
  • > Object x = code.apply("xxx");
  • > ```
  • The compiler doesn't know that the value stored in `code` is expecting a `String`. It might accept a different type like `Double`. The type of `code` only promises that `code` is a function that takes... something!
  • In the second commented line:
  • > ```java
  • > Object x = code.apply((Object) "xxx");
  • > ```
  • The same objection applies. The value stored in `code` may not be accepting of any old `Object`, so you can't cast to `Object` and make `code` happy.
  • When typed as `Function<?, ?>`, the variable `code` could hold any function expecting any non-primitive type, and that means that as far as the compiler is concerned, it's unsafe to apply it to any value other than `null`, the only value that can be used when any (non-primitive) type at all is expected.
  • ---
  • **NERD ZONE**
  • Your intuition that `?` should be equivalent to `Object` is not entirely unfounded. Generic type parameters can have a property called ‘covariance’, meaning (approximately) that the parameter only appears in outputs of the generic interface, never in inputs. When an unbounded wildcard is used in a covariant type parameter, it *is* equivalent to using `Object`, because `Object` is the supertype of all non-primitive types.
  • There is a dual property called ‘contravariance’, meaning that the parameter only appears in *inputs* of the generic interface, never in outputs. In Java, there is no type that is the *subtype* of all non-primitive types, but in the Scala language, for example, there is a type called `Null` which serves this purpose (its only inhabitant is `null`). If Java also had the `Null` type in its type system, it would be valid to say that when the unbounded wildcard is used in a contravariant type parameter, it is equivalent to using `Null`.
  • (Not every type parameter is one or the other; parameters that are neither are called ‘invariant’.)
  • In the `Function<T, R>` interface, `T` is contravariant and `R` is covariant. So if you wanted to replace the wildcards in `Function<?, ?>`, you would have to write `Function<Null, Object>`—if you had a `Null` type to use. And that's another way to see why a `Function<?, ?>` variable can only accept `null`.
  • Unbounded wildcards are not equivalent to `Object`.
  • When you give `code` a type, you are typing the *variable*, not the *value*. So `Function<Object, Object> code` means that it's valid to assign to the `code` variable any function value that can accept an `Object` and return an `Object`, and therefore it's valid to apply `code` to any `Object` (which is, as you note, any non-primitive value). To emphasize: it *must* hold a function that can accept *any* `Object`, and the compiler will enforce this—it can't hold a function that only accepts `Double`s, for example, because such a function would complain if you gave it a `String`, even though all `String`s are `Object`s.
  • On the other hand, `Function<?, ?> code` means that it's valid to assign to the `code` variable any function... at all! It could be a function that can accept an `Object`. But it could also be a function that can *only* accept certain subtypes of `Object`, like `String` in your case. The *value* would have a more restrictive run-time type than the *variable* in that case, but that's legal, just like it's legal to assign a `String` value to a variable of type `Object`. So in your first commented line:
  • > ```java
  • > Object x = code.apply("xxx");
  • > ```
  • The compiler doesn't know that the value stored in `code` is expecting a `String`. It might accept a different type like `Double`. The type of `code` only promises that `code` is a function that takes... something!
  • In the second commented line:
  • > ```java
  • > Object x = code.apply((Object) "xxx");
  • > ```
  • The same objection applies. The value stored in `code` may not be accepting of any old `Object`, so you can't cast to `Object` and make `code` happy.
  • When typed as `Function<?, ?>`, the variable `code` could hold any function expecting any non-primitive type, and that means that as far as the compiler is concerned, it's unsafe to apply it to any value other than `null`, the only value that can be used no matter what (non-primitive) type is expected.
  • ---
  • **NERD ZONE**
  • Your intuition that `?` should be equivalent to `Object` is not entirely unfounded. Generic type parameters can have a property called ‘covariance’, meaning (approximately) that the parameter only appears in outputs of the generic interface, never in inputs. When an unbounded wildcard is used in a covariant type parameter, it *is* equivalent to using `Object`, because `Object` is the supertype of all non-primitive types.
  • There is a dual property called ‘contravariance’, meaning that the parameter only appears in *inputs* of the generic interface, never in outputs. In Java, there is no type that is the *subtype* of all non-primitive types, but in the Scala language, for example, there is a type called `Null` which serves this purpose (its only inhabitant is `null`). If Java also had the `Null` type in its type system, it would be valid to say that when the unbounded wildcard is used in a contravariant type parameter, it is equivalent to using `Null`.
  • (Not every type parameter is one or the other; parameters that are neither are called ‘invariant’.)
  • In the `Function<T, R>` interface, `T` is contravariant and `R` is covariant. So if you wanted to replace the wildcards in `Function<?, ?>`, you would have to write `Function<Null, Object>`—if you had a `Null` type to use. And that's another way to see why a `Function<?, ?>` variable can only accept `null`.
#2: Post edited by user avatar r~~‭ · 2025-10-13T18:07:52Z (11 months ago)
Add details about type parameter variance
  • Unbounded wildcards are not equivalent to `Object`.
  • When you give `code` a type, you are typing the *variable*, not the *value*. So `Function<Object, Object> code` means that it's valid to assign to the `code` variable any function value that can accept an `Object` and return an `Object`, and therefore it's valid to apply `code` to any `Object` (which is, as you note, any non-primitive value). To emphasize: it *must* hold a function that can accept *any* `Object`, and the compiler will enforce this—it can't hold a function that only accepts `Double`s, for example, because such a function would complain if you gave it a `String`, even though all `String`s are `Object`s.
  • On the other hand, `Function<?, ?> code` means that it's valid to assign to the `code` variable any function... at all! It could be a function that can accept an `Object`. But it could also be a function that can *only* accept certain subtypes of `Object`, like `String` in your case. The *value* would have a more restrictive run-time type than the *variable* in that case, but that's legal, just like it's legal to assign a `String` value to a variable of type `Object`. So in your first commented line:
  • > ```java
  • > Object x = code.apply("xxx");
  • > ```
  • The compiler doesn't know that the value stored in `code` is expecting a `String`. It might accept a different type like `Double`. The type of `code` only promises that `code` is a function that takes... something!
  • In the second commented line:
  • > ```java
  • > Object x = code.apply((Object) "xxx");
  • > ```
  • The same objection applies. The value stored in `code` may not be accepting of any old `Object`, so you can't cast to `Object` and make `code` happy.
  • When typed as `Function<?, ?>`, the variable `code` could hold any function expecting any non-primitive type, and that means that as far as the compiler is concerned, it's unsafe to apply it to any value other than `null`, the only value that can be used when any (non-primitive) type at all is expected.
  • Unbounded wildcards are not equivalent to `Object`.
  • When you give `code` a type, you are typing the *variable*, not the *value*. So `Function<Object, Object> code` means that it's valid to assign to the `code` variable any function value that can accept an `Object` and return an `Object`, and therefore it's valid to apply `code` to any `Object` (which is, as you note, any non-primitive value). To emphasize: it *must* hold a function that can accept *any* `Object`, and the compiler will enforce this—it can't hold a function that only accepts `Double`s, for example, because such a function would complain if you gave it a `String`, even though all `String`s are `Object`s.
  • On the other hand, `Function<?, ?> code` means that it's valid to assign to the `code` variable any function... at all! It could be a function that can accept an `Object`. But it could also be a function that can *only* accept certain subtypes of `Object`, like `String` in your case. The *value* would have a more restrictive run-time type than the *variable* in that case, but that's legal, just like it's legal to assign a `String` value to a variable of type `Object`. So in your first commented line:
  • > ```java
  • > Object x = code.apply("xxx");
  • > ```
  • The compiler doesn't know that the value stored in `code` is expecting a `String`. It might accept a different type like `Double`. The type of `code` only promises that `code` is a function that takes... something!
  • In the second commented line:
  • > ```java
  • > Object x = code.apply((Object) "xxx");
  • > ```
  • The same objection applies. The value stored in `code` may not be accepting of any old `Object`, so you can't cast to `Object` and make `code` happy.
  • When typed as `Function<?, ?>`, the variable `code` could hold any function expecting any non-primitive type, and that means that as far as the compiler is concerned, it's unsafe to apply it to any value other than `null`, the only value that can be used when any (non-primitive) type at all is expected.
  • ---
  • **NERD ZONE**
  • Your intuition that `?` should be equivalent to `Object` is not entirely unfounded. Generic type parameters can have a property called ‘covariance’, meaning (approximately) that the parameter only appears in outputs of the generic interface, never in inputs. When an unbounded wildcard is used in a covariant type parameter, it *is* equivalent to using `Object`, because `Object` is the supertype of all non-primitive types.
  • There is a dual property called ‘contravariance’, meaning that the parameter only appears in *inputs* of the generic interface, never in outputs. In Java, there is no type that is the *subtype* of all non-primitive types, but in the Scala language, for example, there is a type called `Null` which serves this purpose (its only inhabitant is `null`). If Java also had the `Null` type in its type system, it would be valid to say that when the unbounded wildcard is used in a contravariant type parameter, it is equivalent to using `Null`.
  • (Not every type parameter is one or the other; parameters that are neither are called ‘invariant’.)
  • In the `Function<T, R>` interface, `T` is contravariant and `R` is covariant. So if you wanted to replace the wildcards in `Function<?, ?>`, you would have to write `Function<Null, Object>`—if you had a `Null` type to use. And that's another way to see why a `Function<?, ?>` variable can only accept `null`.
#1: Initial revision by user avatar r~~‭ · 2025-10-13T17:52:35Z (11 months ago)
Unbounded wildcards are not equivalent to `Object`.

When you give `code` a type, you are typing the *variable*, not the *value*. So `Function<Object, Object> code` means that it's valid to assign to the `code` variable any function value that can accept an `Object` and return an `Object`, and therefore it's valid to apply `code` to any `Object` (which is, as you note, any non-primitive value). To emphasize: it *must* hold a function that can accept *any* `Object`, and the compiler will enforce this—it can't hold a function that only accepts `Double`s, for example, because such a function would complain if you gave it a `String`, even though all `String`s are `Object`s.

On the other hand, `Function<?, ?> code` means that it's valid to assign to the `code` variable any function... at all! It could be a function that can accept an `Object`. But it could also be a function that can *only* accept certain subtypes of `Object`, like `String` in your case. The *value* would have a more restrictive run-time type than the *variable* in that case, but that's legal, just like it's legal to assign a `String` value to a variable of type `Object`. So in your first commented line:

> ```java
> Object x = code.apply("xxx");
> ```

The compiler doesn't know that the value stored in `code` is expecting a `String`. It might accept a different type like `Double`. The type of `code` only promises that `code` is a function that takes... something!

In the second commented line:

> ```java
> Object x = code.apply((Object) "xxx");
> ```

The same objection applies. The value stored in `code` may not be accepting of any old `Object`, so you can't cast to `Object` and make `code` happy.

When typed as `Function<?, ?>`, the variable `code` could hold any function expecting any non-primitive type, and that means that as far as the compiler is concerned, it's unsafe to apply it to any value other than `null`, the only value that can be used when any (non-primitive) type at all is expected.