Logging API

Adam Hawthorne adam.hawthorne at gmail.com
Tue May 22 13:01:20 PDT 2012


I don't know if it's premature to discuss non-Collections APIs, but in
trying out Lambda, I encountered problems using java.util.logging.Logger.
 Here's some sample code:


import static java.util.logging.Level.INFO;
import static LambdaTest.Stringifier._;

import java.util.concurrent.Callable;
import java.util.logging.Logger;

public class LambdaTest {
    public static void main(String... argv) {
        // Fails to compile, no suitable method
//        Logger.getAnonymousLogger().log(INFO, "Hello {0}", () -> "World");

        // Fails to compile, java.lang.Object method restrictions
//        ToString arg1 = () -> "World";
//        Logger.getAnonymousLogger().log(INFO, "Hello {0}", arg1);

        // Does not produce "hoped for" output, Callable<String>.get()
isn't the same as toString()
        Callable<String> arg2 = () -> "World";
        Logger.getAnonymousLogger().log(INFO, "Hello {0}", arg2);

        // Does not produce "hoped for" output,  Object.toString() is
defined.
        Stringer arg3 = () -> "World";
        Logger.getAnonymousLogger().log(INFO, "Hello {0}", arg3);

        // Works, but hokey/extra allocation
        Logger.getAnonymousLogger().log(INFO, "Hello {0}", _(() ->
"World"));
    }

    public interface ToString {
        String toString();
    }

    public interface Stringer {
        String string();

        String toString() default {
            return string();
        }
    }

    public static class Stringifier {
        private final Callable<String> val;

        public Stringifier(Callable<String> val) {
            this.val = val;
        }

        @Override
        public String toString() {
            try {
                return val.call();
            } catch (Exception e) {
                throw new RuntimeException(e);
            }
        }

        public static Stringifier _(Callable<String> val) {
            return new Stringifier(val);
        }
    }
}

One of the nice things about the logging API is that it doesn't actually
invoke toString() on the arguments unless the log level is actually
enabled.  Lambdas are obvious choices for this kind of delayed execution,
but I tried to do battle against Logging and I lost.

It seems to me that option 4 should work, although I understand from
Defenders section 3, Object.toString() takes precedence over the defender
toString() in Stringer.  It would be helpful if using the Logging API was
more friendly towards Lambdas.

Adam


More information about the lambda-dev mailing list