-1

I'm building a JavaFX app and I've discovered the joy of

FXMLloader.setControllerFactory(setControllerFactory​(Callback<Class<?>,Object> controllerFactory)

I went off a searched example to get my code working:

            loader.setControllerFactory(c -> {
               return new MyController(dialog, seed);
            });

It's beautifully simple and clean and now I can define intended controllers in my FXML files but I can construct the controllers with much more complexity/seeding that doesn't happen during injection. Sorry, I'm not really understanding what took place there. I'm sure that's a lambda or an anonymous class. Could somebody please demystify this for me? I'm not sharp with lambdas. They always look attractive and the scoping access for local variables is always handy but they confuse the heck out of me.

In particular... The setControllerFactory needs to be passed an instance X of Callback<P,R> with generics P->Class<?> and R->Object so that something can do X.call(Class<?>) which returns an Object?

What/where did I define a Class<?> thing here? How would I code this without any lambdas/anonymous classes?

  • If you really want to understand what lamdas are I recommend the [Tutorial playlist by JavaBrains](https://youtu.be/gpIUfj3KaOc). – Mushroomator Apr 14 '22 at 16:47
  • 1
    You don't define a `Class>` "thing" (whatever you mean by that). If you look at the docs for `Callback`, the first type parameter is the type of the value that is passed to the `call()` method (in `Callback

    ` there is a method `public R call(P param);`). I.e. in your code the parameter `c` is of type `Class>`. You don't instantiate `Class>` (which I guess is what you mean by "define"???) because it's created by whoever calls the method you define by the lambda; in this case that is the `FXMLLoader`.

    – James_D Apr 14 '22 at 16:53

1 Answers1

1

It (sort of) decomposes as follows

c ->       // c is the Class<?> parameter, which is not used
{    // Scope of Callback<Class<?>, Object>> lambda method body
     return new MyController(dialog, seed);    // The <Object> being returned
});

At some point the lambda gets called with a Class<?>, it ignores it and returns a new controller.

Equivalent anonymous class could be made by implementing Callback<Class<?>, Object> as

Callback<Class<?>, Object> f = new Callback<>() {
    public Object call(Class<?> ignored) {
        return new MyController(dialog, seed);
    }
};
Kayaman
  • 72,141
  • 5
  • 83
  • 121
  • 2
    *"Equivalent anonymous class could be made by implementing `Function, Object>`"*: kind of, but that anonymous class couldn't actually be used in this context. You would have to implement `Callback, Object>`, as that's the type expected by `FXMLLoader.setControllerFactory()`. – James_D Apr 14 '22 at 20:13