aoqi@0: /* aoqi@0: * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved. aoqi@0: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. aoqi@0: * aoqi@0: * This code is free software; you can redistribute it and/or modify it aoqi@0: * under the terms of the GNU General Public License version 2 only, as aoqi@0: * published by the Free Software Foundation. aoqi@0: * aoqi@0: * This code is distributed in the hope that it will be useful, but WITHOUT aoqi@0: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or aoqi@0: * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License aoqi@0: * version 2 for more details (a copy is included in the LICENSE file that aoqi@0: * accompanied this code). aoqi@0: * aoqi@0: * You should have received a copy of the GNU General Public License version aoqi@0: * 2 along with this work; if not, write to the Free Software Foundation, aoqi@0: * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. aoqi@0: * aoqi@0: * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA aoqi@0: * or visit www.oracle.com if you need additional information or have any aoqi@0: * questions. aoqi@0: */ aoqi@0: aoqi@0: /** aoqi@0: * @test aoqi@0: * @bug 8003280 aoqi@0: * @summary Add lambda tests aoqi@0: * Test SAM conversion of method references in contexts of assignment, method/constructor argument, aoqi@0: * return statement, array initializer, lambda expression body, conditional expression and cast. aoqi@0: * @compile SamConversion.java aoqi@0: * @run main SamConversion aoqi@0: */ aoqi@0: aoqi@0: public class SamConversion { aoqi@0: aoqi@0: static int assertionCount = 0; aoqi@0: aoqi@0: static interface Foo { aoqi@0: Integer m(int i); aoqi@0: } aoqi@0: aoqi@0: static interface Bar { aoqi@0: int m(Integer i) throws MyException; aoqi@0: } aoqi@0: aoqi@0: private static void assertTrue(boolean b) { aoqi@0: assertionCount++; aoqi@0: if(!b) aoqi@0: throw new AssertionError(); aoqi@0: } aoqi@0: aoqi@0: private static int test1(Foo foo) { aoqi@0: return foo.m(1); aoqi@0: } aoqi@0: aoqi@0: private static void test2(Bar bar, int result) { aoqi@0: try { aoqi@0: assertTrue(bar.m(1) == result); aoqi@0: } catch (Exception e){ aoqi@0: assertTrue(false); aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: private static Bar test3(int i) { aoqi@0: switch (i) { aoqi@0: case 0: aoqi@0: return A::method1; aoqi@0: case 1: aoqi@0: return new A()::method2; aoqi@0: case 2: aoqi@0: return A::method3; aoqi@0: case 3: aoqi@0: return new A()::method4; aoqi@0: case 4: aoqi@0: return new A()::method5; aoqi@0: case 5: aoqi@0: return A::method6; aoqi@0: default: aoqi@0: return null; aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: /** aoqi@0: * Test SAM conversion of method reference in assignment context aoqi@0: */ aoqi@0: private static void testAssignment() { aoqi@0: Foo foo = A::method1; //static reference, parameter type matching and return type matching aoqi@0: assertTrue(foo.m(1) == 2); aoqi@0: aoqi@0: foo = new A()::method2; //instance reference, parameter type unboxing and return type boxing aoqi@0: assertTrue(foo.m(1) == 3); aoqi@0: aoqi@0: foo = A::method3; //static reference, parameter type matching and return type boxing aoqi@0: assertTrue(foo.m(1) == 4); aoqi@0: aoqi@0: foo = new A()::method4; //instance reference, parameter type unboxing and return type matching aoqi@0: assertTrue(foo.m(1) == 5); aoqi@0: aoqi@0: foo = new A()::method5; //instance reference, parameter type unboxing and return type matching aoqi@0: assertTrue(foo.m(1) == 6); aoqi@0: aoqi@0: Bar bar = A::method1; aoqi@0: try { aoqi@0: assertTrue(bar.m(1) == 2); aoqi@0: } catch (Exception e) { aoqi@0: assertTrue(false); aoqi@0: } aoqi@0: aoqi@0: bar = new A()::method2; aoqi@0: try { aoqi@0: assertTrue(bar.m(1) == 3); aoqi@0: } catch (Exception e) { aoqi@0: assertTrue(false); aoqi@0: } aoqi@0: aoqi@0: bar = A::method3; aoqi@0: try { aoqi@0: assertTrue(bar.m(1) == 4); aoqi@0: } catch (Exception e) { aoqi@0: assertTrue(false); aoqi@0: } aoqi@0: aoqi@0: bar = new A()::method4; aoqi@0: try { aoqi@0: assertTrue(bar.m(1) == 5); aoqi@0: } catch (Exception e) { aoqi@0: assertTrue(false); aoqi@0: } aoqi@0: aoqi@0: bar = new A()::method5; aoqi@0: try { aoqi@0: assertTrue(bar.m(1) == 6); aoqi@0: } catch (Exception e) { aoqi@0: assertTrue(false); aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: /** aoqi@0: * Test SAM conversion of method reference in method/constructor argument context aoqi@0: */ aoqi@0: private static void testMethodArgument() { aoqi@0: assertTrue(test1(A::method1) == 2); aoqi@0: assertTrue(test1(new A()::method2) == 3); aoqi@0: assertTrue(test1(A::method3) == 4); aoqi@0: assertTrue(test1(new A()::method4) == 5); aoqi@0: assertTrue(test1(new A()::method5) == 6); aoqi@0: test2(A::method1, 2); aoqi@0: test2(new A()::method2, 3); aoqi@0: test2(A::method3, 4); aoqi@0: test2(new A()::method4, 5); aoqi@0: test2(new A()::method5, 6); aoqi@0: } aoqi@0: aoqi@0: /** aoqi@0: * Test SAM conversion of method reference in return statement context aoqi@0: */ aoqi@0: private static void testReturnStatement() { aoqi@0: Bar bar = test3(0); aoqi@0: try { aoqi@0: assertTrue(bar.m(1) == 2); aoqi@0: } catch (Exception e) { aoqi@0: assertTrue(false); aoqi@0: } aoqi@0: bar = test3(1); aoqi@0: try { aoqi@0: assertTrue(bar.m(1) == 3); aoqi@0: } catch (Exception e) { aoqi@0: assertTrue(false); aoqi@0: } aoqi@0: bar = test3(2); aoqi@0: try { aoqi@0: assertTrue(bar.m(1) == 4); aoqi@0: } catch (Exception e) { aoqi@0: assertTrue(false); aoqi@0: } aoqi@0: bar = test3(3); aoqi@0: try { aoqi@0: assertTrue(bar.m(1) == 5); aoqi@0: } catch (Exception e) { aoqi@0: assertTrue(false); aoqi@0: } aoqi@0: bar = test3(4); aoqi@0: try { aoqi@0: assertTrue(bar.m(1) == 6); aoqi@0: } catch (Exception e) { aoqi@0: assertTrue(false); aoqi@0: } aoqi@0: bar = test3(5); aoqi@0: try { aoqi@0: bar.m(1); aoqi@0: assertTrue(false); aoqi@0: } catch (MyException e) { aoqi@0: } catch (Exception e) { aoqi@0: assertTrue(false); aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: /** aoqi@0: * Test SAM conversion of method reference in cast context aoqi@0: */ aoqi@0: private static void testCast() { aoqi@0: assertTrue(((Foo)A::method1).m(1) == 2); aoqi@0: try { aoqi@0: assertTrue(((Bar)new A()::method2).m(1) == 3); aoqi@0: } catch (Exception e) { aoqi@0: assertTrue(false); aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: /** aoqi@0: * Test SAM conversion of method reference in array initializer context aoqi@0: */ aoqi@0: private static void testArrayInitializer() { aoqi@0: Object[] oarray = {"a", 1, (Foo)A::method3}; //last element need a cast aoqi@0: Object[] oarray2 = {"a", 1, (Bar)new A()::method4}; //last element need a cast aoqi@0: Foo[] farray = {A::method1, new A()::method2, A::method3, new A()::method4, new A()::method5}; aoqi@0: Bar[] barray = {A::method1, new A()::method2, A::method3, new A()::method4, new A()::method5, A::method6}; aoqi@0: } aoqi@0: aoqi@0: /** aoqi@0: * Test SAM conversion of method reference in conditional expression context aoqi@0: */ aoqi@0: private static void testConditionalExpression(boolean b) { aoqi@0: Foo f = b ? A::method3 : new A()::method5; aoqi@0: if(b) aoqi@0: assertTrue(f.m(1) == 4); aoqi@0: else aoqi@0: assertTrue(f.m(1) == 6); aoqi@0: aoqi@0: Bar bar = b ? A::method1 : A::method6; aoqi@0: if(b) { aoqi@0: try { aoqi@0: assertTrue(bar.m(1) == 2); aoqi@0: } catch (Exception e) { aoqi@0: assertTrue(false); aoqi@0: } aoqi@0: } aoqi@0: else { aoqi@0: try { aoqi@0: bar.m(1); aoqi@0: assertTrue(false); aoqi@0: } catch (MyException e) { aoqi@0: } catch (Exception e) { aoqi@0: assertTrue(false); aoqi@0: } aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: /** aoqi@0: * Test SAM conversion of method reference in lambda expression body aoqi@0: */ aoqi@0: private static void testLambdaExpressionBody() { aoqi@0: Foo f = n -> ((Foo)A::method3).m(n); aoqi@0: assertTrue(f.m(1) == 4); aoqi@0: aoqi@0: Bar b = n -> { return ((Foo)new A()::method5).m(n); }; aoqi@0: try { aoqi@0: assertTrue(b.m(1) == 6); aoqi@0: } catch (Exception e) { aoqi@0: assertTrue(false); aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: public static void main(String[] args) { aoqi@0: testAssignment(); aoqi@0: testMethodArgument(); aoqi@0: testReturnStatement(); aoqi@0: testCast(); aoqi@0: testArrayInitializer(); aoqi@0: testConditionalExpression(true); aoqi@0: testConditionalExpression(false); aoqi@0: testLambdaExpressionBody(); aoqi@0: aoqi@0: assertTrue(assertionCount == 32); aoqi@0: } aoqi@0: aoqi@0: static class MyException extends Exception {} aoqi@0: aoqi@0: static class A { aoqi@0: aoqi@0: int value = 0; aoqi@0: aoqi@0: A() { aoqi@0: } aoqi@0: aoqi@0: A(Foo f) { aoqi@0: value = f.m(9); aoqi@0: } aoqi@0: aoqi@0: A(Bar b) { aoqi@0: try { aoqi@0: value = b.m(9); aoqi@0: } catch (MyException e){} aoqi@0: } aoqi@0: aoqi@0: static Integer method1(int n) { aoqi@0: return n + 1; aoqi@0: } aoqi@0: aoqi@0: int method2(Integer n) { aoqi@0: return value == 0 ? n + 2 : n + value; aoqi@0: } aoqi@0: aoqi@0: static int method3(int n) { aoqi@0: return n + 3; aoqi@0: } aoqi@0: aoqi@0: Integer method4(Integer n) { aoqi@0: return value == 0 ? n + 4 : n + value; aoqi@0: } aoqi@0: aoqi@0: Integer method5(Integer n) { aoqi@0: return value == 0 ? new Integer(n + 5) : new Integer(n + value); aoqi@0: } aoqi@0: aoqi@0: static int method6(Integer n) throws MyException{ aoqi@0: throw new MyException(); aoqi@0: } aoqi@0: } aoqi@0: }