method references: type inference, toString()

Vitaly Davidovich vitalyd at gmail.com
Tue Feb 21 16:16:39 PST 2012


As they say, security by obscurity is not security :).  I can see
performance as an argument, but the security aspect seems invalid.

Sent from my phone
On Feb 21, 2012 6:33 PM, "Rémi Forax" <forax at univ-mlv.fr> wrote:

> On 02/21/2012 11:31 PM, Paul Holser wrote:
> > Hi lambda-dev,
> >
> > Using JDK 8 Developer Preview with lambda support
> > (
> http://download.java.net/lambda/b25/windows-i586/lambda-8-b25-windows-i586-05_feb_2012.zip
> ),
> > Guava 11.0, Hamcrest 1.3.RC2, and JUnit 4.10 (sans Hamcrest classes).
> >
> > org.hamcrest.Matcher is not a SAM type, whereas
> > com.google.common.base.Predicate is.
> >
> > Compiling Main.java:
> >
> > ==== begin Main.java ====
> > import com.google.common.base.Predicate;
> > import org.hamcrest.Description;
> > import org.hamcrest.TypeSafeMatcher;
> > import org.junit.Test;
> >
> > import static org.hamcrest.MatcherAssert.assertThat;
> >
> > interface Foo {
> >      boolean isBar();
> > }
> >
> > abstract class PredicateMatcher<T>  extends TypeSafeMatcher<T>  {
> >      protected final Predicate<? super T>  predicate;
> >
> >      private PredicateMatcher(Predicate<? super T>  predicate) {
> >          this.predicate = predicate;
> >      }
> >
> >      @Override public final boolean matchesSafely(T target) {
> >          return predicate.apply(target);
> >      }
> >
> >      public static<U>  PredicateMatcher<U>  matches(Predicate<? super U>
> > predicate) {
> >          return new PredicateMatcher<U>(predicate) {
> >              @Override public void describeTo(Description description) {
> >                  description.appendText("a value acceptable to predicate
> ");
> >                  description.appendValue(this.predicate);
> >              }
> >          };
> >      }
> > }
> >
> > class BarredUpFoo implements Foo {
> >      @Override public boolean isBar() {
> >          return true;
> >      }
> > }
> >
> > class BarredUpFooTest {
> >      @Test public void bar() {
> >         assertThat(new BarredUpFoo(),
> PredicateMatcher.matches(Foo::isBar));
> >      }
> > }
> >
> > public class Main {
> >      public static void main(String... args) {
> >          Predicate<Foo>  bar = Foo::isBar;
> >          System.out.println(bar);
> >      }
> > }
> > ==== end Main.java ====
> >
> > yields:
> >
> > ==== begin console output ====
> > Main.java:41: error: no suitable method found for matches(member
> reference)
> >         assertThat(new BarredUpFoo(),
> PredicateMatcher.matches(Foo::isBar));
> >                                                       ^
> >      method PredicateMatcher.<U>matches(Predicate<? super U>) is not
> applicable
> >        (cyclic inference - cannot infer target type for given
> lambda/method refer
> > ence expression)
> >      method TypeSafeMatcher.matches(Object) is not applicable
> >        (actual argument member reference cannot be converted to Object
> by method
> > invocation conversion
> >          (the target type of a lambda conversion must be an interface))
> >    where U is a type-variable:
> >      U extends Object declared in method<U>matches(Predicate<? super U>)
> > 1 error
> > ==== end console output ====
> >
> > Couple of questions:
> >
> > 1) Should the usage of Foo::isBar as the predicate fed to
> > PredicateMatcher.matches() compile successfully? I'm hoping not to
> > have to perform the SAM conversion by hand:
> >
> >      Predicate<Foo>  bar = Foo::isBar;
> >      assertThat(new BarredUpFoo(), PredicateMatcher.matches(bar);
> >
> > In Main.main(), I perform that SAM conversion by hand, as you can see
> > -- otherwise, it won't know to choose PrintStream.println(Object), it
> > says "(actual argument member reference cannot be converted to Object
> > by method invocation conversion)".
>
> I only answer easy question, I let this one to Maurizio :)
>
> >
> > 2) Wondering if it wouldn't be too much trouble to have method
> > references respond to toString() with something like "Foo::isBar" or
> > "method isBar on class Foo", instead of, e.g. "Main$1 at a30a4e". It'd
> > make the output of PredicateMatcher.matches() really slick.
>
> There are two major problems.
> First security, if toString() exposes declaring class and method name
> you may show to much information for an attacker. Don't forget that
> the class may be non public and the method private.
> Second, performance, we want a VM to be able to implement the SAM
> conversion as a kind of proxy around a function pointer, i.e something
> that may not carry around the fat Object data structure.
>
> One possible solution.
> Because we also want lambda/method reference to be Serializable
> we are discussing an opt-in mechanism that will allow lambdas to
> be Serializable by having a stable name (thus a meaningful toString).
> But this kind of lambda may be less thin (and perhaps less efficient).
>
> >
> > Thanks for the help, and the great work thus far!
> >
> > Cheers,
> > Paul Holser
> >
>
> cheers,
> Rémi
>
>
>
>
>


More information about the lambda-dev mailing list