Patrick C.
Patrick C.

Reputation: 1429

Java8: About Functional Interface

I would like to ask about the following piece of code related to Functional Interfaces. I am confused by:

Rideable rider = Car :: new

Is it creating a Rideable (interface) or Car (class) instance? If it is creating a Car object, the constructor new Car() (i.e. with no arguments) should be not existing, then how come this can be valid?

I Have been reading through this tutorial ,but still could not figure it out.

@FunctionalInterface 
interface Rideable {
  Car getCar (String name);
}

class Car {
  private String name;

  public Car (String name) {
    this.name = name;
  }
}

public class Test {
  public static void main(String[] args) {
    Rideable rider = Car :: new; 
    Car vehicle = rider.getCar("MyCar");
  }
}

Upvotes: 6

Views: 1156

Answers (3)

Chota Bheem
Chota Bheem

Reputation: 1126

You are creating new object of "Car" which is "Rideable". So yes, you are creating new "Car" object.

Now Rideable is defined as "expecting nameOfTheCar and gives you Car instance via getCar() method" and that is precisely what "Car::new" is doing.

Car::new 

in this example is same as(as its assigned to Rideable)

carName -> new Car(carName)

Now the above behaviour is wrapped using lambda which would be Java7 look something like below:

Rideable rideable = new Rideable() {
    @Override
    public Car getCar(String carName ) {
        return new Car(carName);
    }
};

Now let's say you have another interface

@FunctionalInterface
interface SelfRideable {
    Car getSelfDriven();
}

And now if you do

SelfRideable selfDriven = Car::new;

Then it would not compile since now it does not have any parameter it its method(getSelfDriven()). For this to work, you would need to have default constructor.

Upvotes: 1

Alex Mamo
Alex Mamo

Reputation: 139029

You are using the Lambda syntax to implement the getCar() method of the Rideable interface, where the following anonymous class program is omitted using Lambda's concise syntax:

Rideable rideable = new Rideable() {
    @Override
    public Car getCar(String name) {
        return new Car(name);
    }
};

This is Java 7 code. You can achieve the same thing using using Lambda expression:

Rideable rider = name -> new Car(name);

Or as in your example, using method reference:

Rideable rider = Car::new;

As a result, the getCar(String) method of the Rideable object can be used as a new Car(String).

And as an answer to your question, you are creating an instance of Car class that implements the Rideable interface. This is another way you can implement an interface without using implement keyword.

If you are thinking of:

Car auto = Car("MyCar")::new;

or

Car auto = Car::new;
Car vehicle = auto::getCar("MyCar");

or

Car vehicle = Rideable::new::getCar("MyCar");

All these examples are wrong approaches. I gave you this examples because these are common mistakes that can be made when we are speaking about Lambda expressions or method reference.

Upvotes: 1

Eran
Eran

Reputation: 394126

Is it creating a Rideable (interface) or Car (class) instance?

It is creating an instance of (a class that implements) the Rideable interface.

The Rideable functional interface has a single method - getCar - that accepts a String argument and returns a Car instance.

The public Car (String name) constructor accepts a String argument and produces a Car instance.

Therefore the method reference Car::new (which in this case does not refer to a parameter-less constructor) can be used as implementation of the Rideable interface.

And if it helps to clarify the confusion, here's a lambda expression equivalent to the Car::new method reference:

Rideable rider = (String s) -> new Car(s);

or

Rideable rider = s -> new Car(s);

Upvotes: 5

Related Questions