Home > Software design >  What does this lambda expression "List.of(() -> "read")" mean?
What does this lambda expression "List.of(() -> "read")" mean?

Time:05-21

It's in a method:

   @Override 
   public Collection<? extends GrantedAuthority> getAuthorities() { 
      return List.of(() -> "read"); 
   }

From my poor understanding of the lambda expression, the "expression" part must return a value and it has to be the String "read" in this case

So '() -> "read"' simply means 'return "read"'?

In that case, why use the lambda expression?

Why not just List.of("read")?

CodePudding user response:

A GrantedAuthority is a functional object interface, not a String.

It has a single method getAuthority() that returns a String.

You need something in your List that will return a String when it is later called, not a String now.

Your code is equivalent to

 return List.of(new GrantedAuthority() {
            String getAuthority() {
                return "read";
            }
        });

CodePudding user response:

This is the difference:

() -> "read"

() -> "read" is equivalent to a printed page with the following instructions on it:

  1. Get yourself some flour.
  2. Toss in a pinch of salt and a spoon of oil.
  3. Mix it up with water and knead.
  4. Toss it in an oven.

"read"

This is equivalent to an actual bread you can eat.

Some more deliberation

One is a recipe to make a thing, one is the thing. In this case, the recipe is really, really stupid. It's a bit like the difference between a glas of water and a recipe for water (which is just: Open a tap, a one-liner), it's perhaps a bit hard to see the difference, but move away from how simple the recipe here is - just think of the difference between a recipe and actual food.

Crucially, if the mission to give you a cake, there must be cake. This is all sorts of complicated, I need to go to a store, it needs to be kept cool, and there is exactly 1. I can't magically duplicate cakes.

In contrast to a recipe for cakes, where there can well be 0 cakes, it's cheap to transport recipes, they don't need to be refrigerated, they don't expire. We can also make as many cakes as necessary. Including 0, if we never want to make one.

Again, the extreme simplicity of this 'recipe' makes this distinction hard to 'see': It's not expensive to have a string literal in the heap, they aren't hard to maintain either. In many ways it's in fact simpler than the recipe. Nevertheless, the principle is what this is about: This particular implementation of a GrantedAuthority is trivial and the rigamarole of going with a recipe instead seems silly. But perhaps there is a different implementation of a GrantedAuthority that checks some authentication server and perhaps even asks the user for a password.

That kind of deal means very much you want to return a recipe, not the actual authority: The granting needs to be checked when necessary (which is not now), and let's not ask for a password if we never need it in the first place.

As you said, () -> "read" is indeed a GrantedAuthority object whose single method (which is presumably public String commandKey(); or something like that) is implemented as return "read";.

CodePudding user response:

GrantedAuthority is a function interface from the Spring Security Core which is meant to represent a user's permition.

A term function interface means that has one and only abstract method - getAuthority(), which signature doesn't collide with methods defined by the Object class.

Because GrantedAuthority is a function interface it is eligible to be implemented using a lambda expression or a method reference.

And to implement an interface literally means to provide implementation of its abstract behavior.

getAuthority() has the following definition:

java.lang.String getAuthority()

So the objects representing GrantedAuthority should be capable to respond to the method call getAuthority() by providing a String (it should not be a string by itself).

That's what this lambda does:

GrantedAuthority authority = () -> "read";

It creates an object of type GrantedAuthority which able to respond with the string when method getAuthority() is being invoked on it.

The result returned by the getAuthorities() method has to be a collection of GrantedAuthority objects (? extends GrantedAuthority implies a subtype of GrantedAuthority, i.e. any of its implementations) not a collection of strings.

Have a look at this tutorial provided by Oracle for more information on lambda expressions

  • Related