Car::new is not 'a new car'.
new Cake() is like: "make a cake; once you've made it, make that the value of the expression new Cake().
Cake::new is nothing like a cake. It's not a cake whatsoever, and its value implements none of the interfaces cake do. After all, Cake::new is a cake recipe. It is a thing capable of making cakes, and that has nothing to do with cakes. You can eat a cake. You can't eat a recipe, or an oven. Or a baker (well, I guess you can, but let's not get weird with this. Certainly eating a baker is going to taste nothing like a cake).
In java, 'recipes' like Cake::new are 'untyped' - instead, the compiler looks at the context; the stuff around this expression. That's why this:
Object o = Cake::new;
is not going to compile: From context, there's no hints whatsoever as to what you're trying to do here.
The context needs to tell the compiler exactly what sort of recipe is required, and then the compiler will check if the recipe you've written will fit these needs. If yeah, great, then that's what you get. If not, you get a compiler error.
So, back to your code:
a Rideable describes a recipe: Any recipe that takes as input a name, and turns that into a Car, can be deemed a 'Rideable'. Given that this is an interface that defines precisely one method, it is a so-called FunctionalInterface, and those are special: You can use lambda syntax or method reference syntax to create a new rideable on the fly. The compiler will 'fit' the lambda/reference expression to act as a new instance of Rideable.
Turns out, Car::new fits the bill! There is a constructor that takes a string, and constructors effectively 'return' a Car, which matches that one defined method that Rideable has. Thus, the compiler has determined from the context what you want, that it fits, and goes ahead and does it. Therefore, this:
Rideable r = Car::new;
is just syntax sugar for this:
Rideable r = name -> new Car(name);
which is basically syntax sugar* for this:
Rideable r = new Rideable() {
public Car getCar(String name) {
return new Car(name);
}
}
which is syntax sugar for this:
public class YourCustomRideable implements Rideable {
@Override public Car getCar(String name) {
return new Car(name);
}
}
Rideable r = new YourCustomRideable();
*) There are slight, basically irrelevant differences between the two; the compiler produces slightly different byte code. There are ways to observe this difference, such as asking for the identity hashcode of the rider, but, don't. You're not supposed to treat these things as having a relevant identity, the whole point of your 'instance' of Rideable is that you intend to invoke getCar on it and nothing else. As long as you do that, these 4 lines of code are all entirely equivalent.