Contemplation: How to take advantage of functional interfaces in your own functions (java)

at first

Even if you can use lambda expressions in streams, you may not be able to take advantage of functional interfaces in your own functions. For such people, I would like to introduce how to apply a functional interface to a self-made function using a simple example.

example

It's common to copy the properties of one object to another. At that time, it is often the case that the condition of copying is set only when the value of the property is not null. And, as in this example, copies of various type properties are often lined up. There may be cases where you can copy and paste in this way, but I would like to devise a little. Let's create a common function for the following code to simplify the call. Note that getName () returns a String, and setName () sets a String. getFlag () returns a Boolean and setFlag () sets a Boolean.

if(objA.getName()!=null) {
    objB.setName(objA.getName());
}
if(objA.getFlag()!=null) {
    objB.setFlag(objA.getFlag());
}

Pseudo code

I hope you can write it as follows. Let's see how it is achieved in java.

setIfNotNull(value,func) {
    if(value!= null) {
        func(value);
    }
}
setIfNotNull(objA.getName(),objB.setName);
setIfNotNull(objA.getFlag(),objB.setFlag);

Answer using the interface (example that does not work)

In the above pseudo code, func shows a method, but how should it be expressed in java? An interface is what indicates a method. Again, it may be possible with an interface.

public interface SetNameInterface {
    void setName(String value);
}

public Class ObjB implements  SetNameInterface{
    void setName(String name);
}

public void setIfNotNull(String value,SetNameInterface obj) {
    if(value!= null) {
        obj.setName(value);
    }
}

setIfNotNull(objA.getName(),objB);

It was possible to support setName (), but it is clear that it is not compatible with setFlag (). This method is intuitive, but it doesn't work.

Interface-based answer (works but redundant)

Because we want to call setName () and setFlag () from setIfNotNull () with the common function name func. How about having an object with func as an interface for setName () and setFlag ()?


public Class ObjB {
	public void setName(String name) {
		System.out.println("OnjB.setName:"+name);
	}
	public void setFlag(Boolean flag) {
		System.out.println("OnjB.setFlag:"+flag);
	}
}

public interface FuncInterface<T> {
    void func(T value);
}

public class ObjBSetName implements FuncInterface<String> {
	ObjB obj;
	public ObjBSetName(ObjB obj) {
		this.obj = obj;
	}
	@Override
	public void func(String value) {
		obj.setName(value);
	}
}

public class ObjBSetFlag implements FuncInterface<Boolean> {
	ObjB obj;
	public ObjBSetFlag(ObjB obj) {
		this.obj = obj;
	}
	@Override
	public void func(Boolean value) {
		obj.setFlag(value);
	}
}

public <T>void setIfNotNull(T value,FuncInterface<T> obj) {
    if(value!= null) {
        obj.func(value);
    }
}

setIfNotNull(objA.getName(),new ObjBSetName(objB));
setIfNotNull(objA.getFlag(),new ObjBSetFlag(objB));

ObjBSetName and ObjBSetFlag both have func functions defined in the FuncInterface interface. When the func function is called, the original processing objB.setName () and objB.setFlag () are called. The FuncInterface interface declares the type of the parameter passed to the method as a generic type (T in this case). Correspondingly, setIfNotNull () also changes value and obj to use generic types.

Answers using anonymous classes

I've achieved what I want to do with this, but it is redundant to prepare ObjBSetName and ObjBSetFlag. Let's use an anonymous class.

How to write an anonymous class

new parent class or interface name () { Anonymous class content (field and method definitions) };

Because it is

    var objBSetName = new FuncInterface<String>() {
        @Override
        public void func(String value) {
            objB.setName(value);
        }
    };
    var objBSetFlag = new FuncInterface<Boolean>() {
        @Override
        public void func(Boolean value) {
            objB.setFlag(value);
        }
    };

Write, The call is

    setIfNotNull(objA.getName(),objBSetName);
    setIfNotNull(objA.getFlag(),objBSetFlag);

It will be. Within the anonymous class, you can directly reference the object objB.

Answer using lambda expression

For interfaces with only one function defined, anonymous classes can be replaced with lambda expressions, so

    FuncInterface<String> objBSetName = (v) -> objB.setName(v);
    FuncInterface<Boolean> objBSetFlag = (v) -> objB.setFlag(v);

Can be rewritten as. The lambda expression does not have the notation func, but it implements the func defined in FuncInterface. It's hard to see that func disappears in lambda expressions, but you can understand it by comparing it with anonymous classes.

Omit more variables

    setIfNotNull(objA.getName(),(v) -> objB.setName(v));
    setIfNotNull(objA.getFlag(),(v) -> objB.setFlag(v));

Can be summarized as.

Answer using a functional interface

By the way, the declaration of the interface called FuncInterface is actually as a functional interface. Consumer already exists, so let's replace it with this one. (Before creating your own interface, it's a good idea to check if you can use the provided functional interface.)

public <T>void setIfNotNull(T value,Consumer<T> obj) {
    if(value!= null) {
        obj.accept(value);
    }
}

In addition, since it has one argument, the call uses a method reference,

    setIfNotNull(objA.getName(),objB::setName);
    setIfNotNull(objA.getFlag(),objB::setFlag);

It will be. It was pretty neat.

Summary

This time, I explained with a small example, but you can see that "processing" can be passed to a function. I think. The declaration for that is the "functional interface". You may have already imagined that you could use it to achieve the "Strategy pattern". Please apply it to your program and reuse the program.

Recommended Posts

Contemplation: How to take advantage of functional interfaces in your own functions (java)
How to read your own YAML file (*****. Yml) in Java
How to create your own annotation in Java and get the value
How to call functions in bulk with Java reflection
Summary of how to implement default arguments in Java
[Forge] How to register your own Entity and Entity Render in 1.13.2
How to derive the last day of the month in Java
How to learn JAVA in 7 days
Handle your own annotations in Java
How to use classes in Java?
How to name variables in Java
How to concatenate strings in java
Understand how functional programming was introduced to Java in one shot
How to get the length of an audio file in java
How to increment the value of Map in one line in Java
How to implement date calculation in Java
How to implement Kalman filter in Java
Multilingual Locale in Java How to use Locale
[java] Summary of how to handle char
How to do base conversion in Java
How to implement coding conventions in Java
How to embed Janus Graph in Java
[Java] [Maven3] Summary of how to use Maven3
How to get the date in java
How to get the absolute path of a directory running in Java
Create your own shortcuts in Xcode to eliminate the hassle of pod install
The first year of working people summarized how to take the Java Bronze exam
Summary of how to select elements in Selenium
[java] Summary of how to handle character strings
How to display a web page in Java
[Java] Summary of how to abbreviate lambda expressions
How to get Class from Element in Java
How to hide null fields in response in Java
How to use JQuery in js.erb of Rails6
[Java] How to substitute Model Mapper in Jackson
How to solve an Expression Problem in Java
How to write Java String # getBytes in Kotlin?
How to get the class name of the argument of LoggerFactory.getLogger when using SLF4J in Java
[Java] How to display the day of the week acquired by LocalDate, DateTimeformatter in Japanese
Summary of how to use the proxy set in IE when connecting with Java
[Java] How to get the URL of the transition source
[Java] How to use compareTo method of Date class
How to create a Java environment in just 3 seconds
[Java] How to omit the private constructor in Lombok
How to write Scala from the perspective of Java
[Java] Types of comments and how to write them
How to input / output IBM mainframe files in Java?
[Java] How to get the maximum value of HashMap
As of April 2018 How to get Java 8 on Mac
How to use CommandLineRunner in Spring Batch of Spring Boot
How to generate / verify ID token in Java Memo
Summary of Java communication API (3) How to use SocketChannel
How to convert A to a and a to A using AND and OR in Java
How to Git manage Java EE projects in Eclipse
Summary of Java communication API (2) How to use HttpUrlConnection
How to put old Java (8 series) in macOS 10.15 Catalina
How to execute WebCamCapture sample of NyARToolkit for Java
Notes on how to use regular expressions in Java
Considering the adoption of Java language in the Reiwa era ~ How to choose a safe SDK
Azure functions in java
How to get the class name / method name running in Java