user1887464
user1887464

Reputation: 557

Interface method reference to a functional interface

I am working with Java Spring framework and JWT - Java Web Tokens. I have below class

import java.util.function.Function;

import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;

import app.com.javainuse.config.JwtTokenUtil;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;


public class Test {
    public static void main(String[] args) {
        User u=new User("javainuse", "$2a$10$slYQmyNdGzTn7ZLBXBChFOC9f6kFjAqPhccnP6DxlWXx2lPk1C3G6",new ArrayList<>());
        UserDetails ud=u;
        
        JwtTokenUtil jwtTokenUtil=new JwtTokenUtil();
        
        String token = jwtTokenUtil.generateToken(ud);
        Test t=new Test();
        System.out.println(t.getClaimFromToken(token, Claims::getSubject));

        
    }
    
    public <T> T getClaimFromToken(String token, Function<Claims, T> claimsResolver) {
        final Claims claims = getAllClaimsFromToken(token);
        System.out.println(claims.toString());      
        return claimsResolver.apply(claims);
    }

    private Claims getAllClaimsFromToken(String token) {
        return Jwts.parser().setSigningKey("javainuse").parseClaimsJws(token).getBody();
    }
}

I am not able to understand statement containing this Claims::getSubject in main method. It gets passed to a functional interface Named Function<Claims,T> claimresolver. How does a method reference getSubject without implementation able to return subject from claims object in getClaimFromToken method ? When we pass method reference to a Functional Interface we the method must have body wight ? but Claims is an interface and getSubject does not have a body then how does "claimsResolver.apply(claims);" is able to get subject value ?

Upvotes: 0

Views: 290

Answers (3)

user1887464
user1887464

Reputation: 557

I found what it is called in java. It is called unbound non-static method references. Here is a link which explains every type method references and the scenario which I was asking to explain. Unbound Non static method references

Upvotes: 0

rzwitserloot
rzwitserloot

Reputation: 103018

someInstance.getSubject() bakes a cake and returns it to you.

Claims::getSubject is a recipe for baking cakes.

One does the thing. The other doesn't do anything, it merely is a description of how to do the thing - whatever you hand it to can do the thing, or not, or do it 10 times - or pass the recipe on to somebody else who is then faced with the same choice. They can do whatever they like:

  • Toss the recipe in the garbage (and no cakes ever exist).
  • Bake a cake.
  • Bake 10,000 cakes.
  • Start 100 threads and bake 100 cakes simultaneously.
  • Save the recipe for later and bake some cakes tomorrow.

When I write down a recipe for making cake, one of the ingredients I'm going to mention is that you will need fresh water.

That means, to bake a cake, I need fresh water. Or perhaps a tap (something that can make fresh water for me). However, to make a cake recipe I do not need fresh water at all. I just need to tell you (the one who will be following my recipe to bake that cake): "You will need to obtain some fresh water. Not my problem how you do that!".

In other words, a cake recipe is a recipe that turns fresh water (and some other things) into a cake. It does not explain how to obtain fresh water, nor does a recipe for making cake come wrapped around a bottle of fresh water.

In the same vein, Claims::getSubject is a recipe that explains how to turn any instance of a class that implements Claims (i.e. a Claims instance) into a String. It does not come with an instance of Claims nor does it explain how to make an instance of Claims. It merely says: IF you have an instance of Claims, this recipe lets you turn that Claims into a String!

Claims::getSubject specifically says: Take your claims, call it c. Run c.getSubject(). Voila, there's your string.

Here, you pass that notion (a recipe for turning claims into strings) to the getClaimFromToken method, which apparently knows how to produce an instance of Claims.

That's analogous to me handing you a cake recipe today and you showing up with a cake tomorrow. That implies you managed to obtain some fresh water. I do not know how and I don't really need to care - I get to enjoy some cake!

NB: Obviously getClaimsFromToken knows how to make an instance that implements Claims from a token, and will then apply your recipe (i.e., call .getSubject() on it). But that's just 'guessing' - the point of APIs is that they promise they do X. You don't need to bother with knowing how it does it, you just need to bother with knowing what it does, and perhaps ascertaining that the library is fit for purpose and it does what its docs say it does.

Upvotes: 1

Jesse
Jesse

Reputation: 93

You're right that the Claims::getSubject syntax here is passing a method reference to the Function interface, rather than implementing the full lambda expression.

The key to how this works is that Claims is an interface that extends the Claims interface from the io.jsonwebtoken library.

That io.jsonwebtoken.Claims interface defines various getter methods like getSubject(), getIssuer() etc. without providing implementations.

So when we call:

Claims::getSubject

We are providing a reference to the getSubject() method on the io.jsonwebtoken.Claims interface.

Even though the interface doesn't provide an implementation, at runtime the claims object will actually be an instance of some class that implements the io.jsonwebtoken.Claims interface and provides a concrete implementation of getSubject().

When claimsResolver.apply(claims) is called, it will invoke that underlying getSubject() method on the claims instance, which returns the subject value.

So in summary:

  • Claims::getSubject provides a reference to the interface method
  • The claims object provides an implementation of that interface
  • So claimsResolver.apply(claims) is able to call the implemented getSubject() method to return the value

Upvotes: 0

Related Questions