4

Here is the issue, you can find it in w3schools lamda expressions chapter last example:

interface StringFunction {
  String run(String str);
}

And:

public class Main {
  public static void main(String[] args) {
    StringFunction exclaim = (s) -> s + "!";
    StringFunction ask = (s) -> s + "?";
    printFormatted("Hello", exclaim);
    printFormatted("Hello", ask);
  }
  public static void printFormatted(String str, StringFunction format) {
    String result = format.run(str);
    System.out.println(result);
  }
}

So from my understanding,the code here doesnt explicitly define the function '.run()' in the interface 'StringFunction', only the parameters is stated in it.

And I believe one needs to implement this class by making another class to further define the behaviour of this function. Therefore the major confusion here is that '.run()' can for some reason work without any defintition, so if it is not a built-in function of java please someone explain to me as to why and how is this possible. The fact that 'StringFunction' can be used as a class for 'exclaim' and 'ask' is also very confusing without any definition.

I just started out with java so I hope for your understanding.

3
  • 1
    Questions on Stack Overflow should be about the questions only and not meta-talk. If you have questions about Stack Overflow itself, your account or your specific posts, you can ask on Meta Stack Overflow. if you have a direct links to a post, people there can probably tell you what happened, even if you cannot access it any more. Commented Mar 1 at 16:06
  • 6
    "doesnt explicitly define the function" - but that is being done for example by StringFunction exclaim = (s) -> s + "!"; - that is basically similar to StringFunction exclaim = new StringFunction { public String run(String s) { return > s + "!"; } }; -- see JLS 9.8. Functional Interfaces Commented Mar 1 at 16:06
  • 1
    ... and JLS 15.27. Lambda Expressions Commented Mar 1 at 16:12

2 Answers 2

11

Functional interface

StringFunction is a functional interface. In other words it is an interface with a single abstract method.
An abstract method is a method without definition (without body).

Such interfaces can be implemented using a lambda expression. As it is done in your example.

So StringFunction exclaim = (s) -> s + "!" is an implementation of StringFunction and an instance of that implementation.

You can think of StringFunction exclaim = (s) -> s + "!" as a short version of following:

class ExclamationAppender implements StringFunction {
    @Override
    public String run(String s) {
        return s + "!";
    }
}

StringFunction exclaim = new ExclamationAppender();
Sign up to request clarification or add additional context in comments.

3 Comments

and they can have abstract methods of Object (since every instance will inherit these methods), private methods, and static methods - and must not be sealed
@user85421, it's true. But Object's methods are not abstract. And static methods cannot be abstract. You’re right about sealed, but IMO it is not required detail for current question. Thank you for comment and edit!
Now this made it very clear for me, thanks!
5

The other Answers are correct about your StringFunction being a functional interface because it defines only a single abstract method. You later implement that functional interface by way of a lambda. (See tutorial by Oracle.) I’ll add one more thought.

java.lang.FunctionalInterface

If you were intending for StringFunction to be a functional interface, you can communicate that intent by annotating with FunctionalInterface.

@FunctionalInterface          // ⬅️ (a) Communicates your intent. (b) Protects against later adding more methods. 
interface StringFunction {
  String run(String str);
}

Besides communicating intent, this annotation protects you in the future. If a programmer later adds another method to your interface, the compiler reports an error. The error explains how the additional method violates the contract promised by that annotation.

However, note that use of the FunctionalInterface annotation is optional. Your code so demonstrates. To quote the Javadoc:

… the compiler will treat any interface meeting the definition of a functional interface as a functional interface regardless of whether or not a FunctionalInterface annotation is present on the interface declaration.

While technically optional, I do recommend using this annotation.

For a complete definition of a functional interface, see this page of the Java Language Specification.

1 Comment

Excellent addition to the accepted answer! For learners: Although adding @FunctionalInterface is optional, it is considered a best practice. It is similar to adding @Override to a method when it overrides a method from its parent type. Adding this annotation will ensure that the compiler will warn if the method is actually overriding or just looking like overriding.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.