method references: type inference, toString()

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


Sure but that returns a method handle whereas the conversation is just
about pretty printing in the debugger/toString.  Moreover, caller already
has a lambda for the underlying method and so can invoke it - I just don't
see what type of security concern we're talking about.

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

> On 02/22/2012 01:16 AM, Vitaly Davidovich wrote:
>
>>
>> As they say, security by obscurity is not security :).  I can see
>> performance as an argument, but the security aspect seems invalid.
>>
>>
> I agree, here security == part of the Java security model
> like when you call Class.getDeclaredMethods
> http://docs.oracle.com/javase/**7/docs/api/java/lang/Class.**
> html#getDeclaredMethods%28%29<http://docs.oracle.com/javase/7/docs/api/java/lang/Class.html#getDeclaredMethods%28%29>
>
> cheers,
> Rémi
>
>  Sent from my phone
>>
>> On Feb 21, 2012 6:33 PM, "Rémi Forax" <forax at univ-mlv.fr <mailto:
>> 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<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