method references: type inference, toString()
Rémi Forax
forax at univ-mlv.fr
Tue Feb 21 16:35:05 PST 2012
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
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),
> > 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