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