How to bind methods or constructors to functional interfaces in Java
Tags: java, tutorial, reflection
Published: 2020-12-08 07:51:56

To bind methods or constructors to functional interfaces we are going to use the **FunctionalInterfaceFactory**. FunctionalInterfaceFactory component uses to cache all generated functional interfaces for faster access. First of all we must add the following dependency to our _pom.xml_:

{% gist https://gist.github.com/Roberto-Gentili/536ee2d3f775030d46d82a008da10dbe.js %}

## Constructors binding
To bind constructors to functional interfaces we will use the following constructors:
```java
private Service(String id, String name, String... items) {                                                                          
    this.id = id;                                                                                                                   
    this.name = name;                                                                                                               
    this.items = items;                                                                                                             
    logInfo("\nMultiparameter constructor:\n\tid: {}\n\tname: {} \n\titems: {}", this.id, this.name, String.join(", ", this.items));
}                                                                                                                                   
                                                                                                                                    
private Service(String name, String... items) {                                                                                     
    this.id = UUID.randomUUID().toString();                                                                                         
    this.name = name;                                                                                                               
    this.items = items;                                                                                                             
    logInfo("\nMultiparameter constructor:\n\tid: {}\n\tname: {} \n\titems: {}", this.id, this.name, String.join(", ", this.items));
}                                                                                                                                   
                                                                                                                                    
private Service(String... name) {                                                                                                   
    this.id = UUID.randomUUID().toString();                                                                                         
    this.name = name[0];                                                                                                            
    this.items = null;                                                                                                              
    logInfo("\nSingle parameter varargs constructor:\n\tname: {}", this.name);                                                      
}                                                                                                                                   
                                                                                                                                    
private Service(String name) {                                                                                                      
    this.id = UUID.randomUUID().toString();                                                                                         
    this.name = name;                                                                                                               
    this.items = null;                                                                                                              
    logInfo("\nSingle parameter constructor:\n\tname: {}", this.name);                                                              
}                                                                                                                                   
                                                                                                                                    
private Service() {                                                                                                                 
    this.id = UUID.randomUUID().toString();                                                                                         
    this.name = "no name";                                                                                                          
    this.items = null;                                                                                                              
    logInfo("\nNo parameter constructor:\n\tname: {}", this.name);                                                                  
}
```
... And now let's see the code needed to bind and call the generated functional interfaces:
```java
ComponentContainer componentContainer = ComponentContainer.getInstance();                                                            
FunctionalInterfaceFactory fIF = componentContainer.getFunctionalInterfaceFactory();                                                 
                                                                                                                                     
MultiParamsFunction<Service> serviceInstantiatorZero = fIF.getOrCreate(Service.class, String.class, String.class, String[].class);   
Service serviceZero = serviceInstantiatorZero.apply(UUID.randomUUID().toString(), "Service Zero", new String[] {"item 1", "item 2"});
                                                                                                                                     
BiFunction<String, String[], Service> serviceInstantiatorOne = fIF.getOrCreate(Service.class, String.class, String[].class);         
Service serviceOne = serviceInstantiatorOne.apply("Service One", new String[] {"item 1", "item 2"});                                 
                                                                                                                                     
Function<String[], Service> serviceInstantiatorTwo = fIF.getOrCreate(Service.class, String[].class);                                 
Service serviceTwo = serviceInstantiatorTwo.apply(new String[] {"Service Two"});                                                     
                                                                                                                                     
Function<String, Service> serviceInstantiatorThree = fIF.getOrCreate(Service.class, String.class);                                   
Service serviceThree = serviceInstantiatorThree.apply("Service Three");                                                              
                                                                                                                                     
Supplier<Service> serviceInstantiatorFour = fIF.getOrCreate(Service.class);                                                          
Service serviceFour = serviceInstantiatorFour.get();                      
```
## Methods binding
To bind methods to functional interfaces we will use the following methods:

```java
private Long reset(String id, String name, String... items) {                                                                  
    this.id = id;                                                                                                              
    this.name = name;                                                                                                          
    this.items = items;                                                                                                        
    logInfo("\nMultiparameter method:\n\tid: {}\n\tname: {} \n\titems: {}", this.id, this.name, String.join(", ", this.items));
    return System.currentTimeMillis();                                                                                         
}                                                                                                                              
                                                                                                                               
private Long reset(String name, String... items) {                                                                             
    this.id = UUID.randomUUID().toString();                                                                                    
    this.name = name;                                                                                                          
    this.items = items;                                                                                                        
    logInfo("\nMultiparameter method:\n\tid: {}\n\tname: {} \n\titems: {}", this.id, this.name, String.join(", ", this.items));
    return System.currentTimeMillis();                                                                                         
}                                                                                                                              
                                                                                                                               
private Long reset(String... name) {                                                                                           
    this.id = UUID.randomUUID().toString();                                                                                    
    this.name = name[0];                                                                                                       
    this.items = null;                                                                                                         
    logInfo("\nSingle parameter varargs method:\n\tname: {}", this.name);                                                      
    return System.currentTimeMillis();                                                                                         
}                                                                                                                              
                                                                                                                               
private Long reset(String name) {                                                                                              
    this.id = UUID.randomUUID().toString();                                                                                    
    this.name = name;                                                                                                          
    this.items = null;                                                                                                         
    logInfo("\nSingle parameter method:\n\tname: {}", this.name);                                                              
    return System.currentTimeMillis();                                                                                         
}                                                                                                                              
                                                                                                                               
private Long reset() {                                                                                                         
    this.id = UUID.randomUUID().toString();                                                                                    
    this.name = "no name";                                                                                                     
    this.items = null;                                                                                                         
    logInfo("\nNo parameter method:\n\tname: {}", this.name);                                                                  
    return System.currentTimeMillis();                                                                                         
}
```

... And now let's see the code needed to bind and call the generated functional interfaces:

```java
ComponentContainer componentContainer = ComponentContainer.getInstance();                                                                           
FunctionalInterfaceFactory fIF = componentContainer.getFunctionalInterfaceFactory();                                                                
                                                                                                                                                    
MultiParamsFunction<Long> methodInvokerZero = fIF.getOrCreate(Service.class, "reset", String.class, String.class, String[].class);                  
Long currentTimeMillis = methodInvokerZero.apply(service, UUID.randomUUID().toString(), "Service Zero New Name", new String[] {"item 3", "item 4"});
                                                                                                                                                    
MultiParamsFunction<Long> methodInvokerOne = fIF.getOrCreate(Service.class, "reset", String.class, String[].class);                                 
currentTimeMillis = methodInvokerOne.apply(service, "Service One", new String[] {"item 1", "item 2"});                                              
                                                                                                                                                    
BiFunction<Service, String[], Long> methodInvokerTwo = fIF.getOrCreate(Service.class, "reset", String[].class);                                     
currentTimeMillis = methodInvokerTwo.apply(service, new String[] {"Service Two"});                                                                  
                                                                                                                                                    
BiFunction<Service, String, Long> methodInvokerThree = fIF.getOrCreate(Service.class, "reset", String.class);                                       
currentTimeMillis = methodInvokerThree.apply(service, "Service Three");                                                                             
                                                                                                                                                    
Function<Service, Long> methodInvokerFour = fIF.getOrCreate(Service.class, "reset");                                                                
currentTimeMillis = methodInvokerFour.apply(service); 
```

## Void methods binding
To bind void methods to functional interfaces we will use the following methods:
```java
private void voidReset(String id, String name, String... items) {                                                                   
    this.id = id;                                                                                                                   
    this.name = name;                                                                                                               
    this.items = items;                                                                                                             
    logInfo("\nMultiparameter void method:\n\tid: {}\n\tname: {} \n\titems: {}", this.id, this.name, String.join(", ", this.items));
}                                                                                                                                   
                                                                                                                                    
private void voidReset(String name, String... items) {                                                                              
    this.id = UUID.randomUUID().toString();                                                                                         
    this.name = name;                                                                                                               
    this.items = items;                                                                                                             
    logInfo("\nMultiparameter void method:\n\tname: {} \n\titems: {}", this.name, String.join(", ", this.items));                   
}                                                                                                                                   
                                                                                                                                    
private void voidReset(String... name) {                                                                                            
    this.id = UUID.randomUUID().toString();                                                                                         
    this.name = name[0];                                                                                                            
    this.items = null;                                                                                                              
    logInfo("\nSingle parameter void varargs method:\n\tname: {}", this.name);                                                      
}                                                                                                                                   
                                                                                                                                    
private void voidReset(String name) {                                                                                               
    this.id = UUID.randomUUID().toString();                                                                                         
    this.name = "no name";                                                                                                          
    this.items = null;                                                                                                              
    logInfo("\nSingle parameter void method:\n\tname: {}", this.name);                                                              
}                                                                                                                                   
                                                                                                                                    
private void voidReset() {                                                                                                          
    this.id = UUID.randomUUID().toString();                                                                                         
    this.name = "no name";                                                                                                          
    this.items = null;                                                                                                              
    logInfo("\nNo parameter void method:\n\tname: {}", this.name);                                                                  
}
```
... And now let's see the code needed to bind and call the generated functional interfaces:

```java
ComponentContainer componentContainer = ComponentContainer.getInstance();                                                       
FunctionalInterfaceFactory fIF = componentContainer.getFunctionalInterfaceFactory();                                            
                                                                                                                                
MultiParamsConsumer methodInvokerZero = fIF.getOrCreate(Service.class, "voidReset", String.class, String.class, String[].class);
methodInvokerZero.accept(service, UUID.randomUUID().toString(), "Service Zero New Name", new String[] {"item 3", "item 4"});    
                                                                                                                                
MultiParamsConsumer methodInvokerOne = fIF.getOrCreate(Service.class, "voidReset", String.class, String[].class);               
methodInvokerOne.accept(service, "Service One", new String[] {"item 1", "item 2"});                                             
                                                                                                                                
BiConsumer<Service, String[]> methodInvokerTwo = fIF.getOrCreate(Service.class, "voidReset", String[].class);                   
methodInvokerTwo.accept(service, new String[] {"Service Two"});                                                                 
                                                                                                                                
BiConsumer<Service, String> methodInvokerThree = fIF.getOrCreate(Service.class, "voidReset", String.class);                     
methodInvokerThree.accept(service, "Service Three");                                                                            
                                                                                                                                
Consumer<Service> methodInvokerFour = fIF.getOrCreate(Service.class, "voidReset");                                              
methodInvokerFour.accept(service);                    
```

## Binding to methods with boolean return
To bind methods with boolean return to functional interfaces we will use the following methods:

```java
private boolean resetWithBooleanReturn(String id, String name, String... items) {                                                                  
    this.id = id;                                                                                                                                  
    this.name = name;                                                                                                                              
    this.items = items;                                                                                                                            
    logInfo("\nMultiparameter method with boolean return:\n\tid: {}\n\tname: {} \n\titems: {}", this.id, this.name, String.join(", ", this.items));
    return true;                                                                                                                                   
}                                                                                                                                                  
                                                                                                                                                   
private boolean resetWithBooleanReturn(String name, String... items) {                                                                             
    this.id = UUID.randomUUID().toString();                                                                                                        
    this.name = name;                                                                                                                              
    this.items = items;                                                                                                                            
    logInfo("\nMultiparameter method with boolean return:\n\tid: {}\n\tname: {} \n\titems: {}", this.id, this.name, String.join(", ", this.items));
    return true;                                                                                                                                   
}                                                                                                                                                  
                                                                                                                                                   
private boolean resetWithBooleanReturn(String... name) {                                                                                           
    this.id = UUID.randomUUID().toString();                                                                                                        
    this.name = name[0];                                                                                                                           
    this.items = null;                                                                                                                             
    logInfo("\nSingle parameter varargs method with boolean return:\n\tname: {}", this.name);                                                      
    return true;                                                                                                                                   
}                                                                                                                                                  
                                                                                                                                                   
private boolean resetWithBooleanReturn(String name) {                                                                                              
    this.id = UUID.randomUUID().toString();                                                                                                        
    this.name = name;                                                                                                                              
    this.items = null;                                                                                                                             
    logInfo("\nSingle parameter method with boolean return:\n\tname: {}", this.name);                                                              
    return true;                                                                                                                                   
}                                                                                                                                                  
                                                                                                                                                   
private boolean resetWithBooleanReturn() {                                                                                                         
    this.id = UUID.randomUUID().toString();                                                                                                        
    this.name = "no name";                                                                                                                         
    this.items = null;                                                                                                                             
    logInfo("\nNo parameter method with boolean return:\n\tname: {}", this.name);                                                                  
    return true;                                                                                                                                   
}
```

... And now let's see the code needed to bind and call the generated functional interfaces:

```java
ComponentContainer componentContainer = ComponentContainer.getInstance();                                                                     
FunctionalInterfaceFactory fIF = componentContainer.getFunctionalInterfaceFactory();                                                          
                                                                                                                                              
MultiParamsPredicate methodInvokerZero = fIF.getOrCreate(Service.class, "resetWithBooleanReturn", String.class, String.class, String[].class);
boolean executed = methodInvokerZero.test(service, UUID.randomUUID().toString(), "Service Zero New Name", new String[] {"item 3", "item 4"}); 
                                                                                                                                              
MultiParamsPredicate methodInvokerOne = fIF.getOrCreate(Service.class, "resetWithBooleanReturn", String.class, String[].class);               
executed = methodInvokerOne.test(service, "Service One", new String[] {"item 1", "item 2"});                                                  
                                                                                                                                              
BiPredicate<Service, String[]> methodInvokerTwo = fIF.getOrCreate(Service.class, "resetWithBooleanReturn", String[].class);                   
executed = methodInvokerTwo.test(service, new String[] {"Service Two"});                                                                      
                                                                                                                                              
BiPredicate<Service, String> methodInvokerThree = fIF.getOrCreate(Service.class, "resetWithBooleanReturn", String.class);                     
executed = methodInvokerThree.test(service, "Service Three");                                                                                 
                                                                                                                                              
Predicate<Service> methodInvokerFour = fIF.getOrCreate(Service.class, "resetWithBooleanReturn");                                              
executed = methodInvokerFour.test(service);    
```

In this article we learned how to bind methods or constructors to functional interfaces and the complete source is available [**here**](https://github.com/burningwave/core/tree/master/src/test/java/org/burningwave/core/examples/functionalinterfacefactory).