1/* 2 * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. 8 * 9 * This code is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 */ 23 24/** 25 * @test 26 * @bug 8003280 27 * @summary Add lambda tests 28 * Test SAM conversion of method references in contexts of assignment, method/constructor argument, 29 * return statement, array initializer, lambda expression body, conditional expression and cast. 30 * @compile SamConversion.java 31 * @run main SamConversion 32 */ 33 34public class SamConversion { 35 36 static int assertionCount = 0; 37 38 static interface Foo { 39 Integer m(int i); 40 } 41 42 static interface Bar { 43 int m(Integer i) throws MyException; 44 } 45 46 private static void assertTrue(boolean b) { 47 assertionCount++; 48 if(!b) 49 throw new AssertionError(); 50 } 51 52 private static int test1(Foo foo) { 53 return foo.m(1); 54 } 55 56 private static void test2(Bar bar, int result) { 57 try { 58 assertTrue(bar.m(1) == result); 59 } catch (Exception e){ 60 assertTrue(false); 61 } 62 } 63 64 private static Bar test3(int i) { 65 switch (i) { 66 case 0: 67 return A::method1; 68 case 1: 69 return new A()::method2; 70 case 2: 71 return A::method3; 72 case 3: 73 return new A()::method4; 74 case 4: 75 return new A()::method5; 76 case 5: 77 return A::method6; 78 default: 79 return null; 80 } 81 } 82 83 /** 84 * Test SAM conversion of method reference in assignment context 85 */ 86 private static void testAssignment() { 87 Foo foo = A::method1; //static reference, parameter type matching and return type matching 88 assertTrue(foo.m(1) == 2); 89 90 foo = new A()::method2; //instance reference, parameter type unboxing and return type boxing 91 assertTrue(foo.m(1) == 3); 92 93 foo = A::method3; //static reference, parameter type matching and return type boxing 94 assertTrue(foo.m(1) == 4); 95 96 foo = new A()::method4; //instance reference, parameter type unboxing and return type matching 97 assertTrue(foo.m(1) == 5); 98 99 foo = new A()::method5; //instance reference, parameter type unboxing and return type matching 100 assertTrue(foo.m(1) == 6); 101 102 Bar bar = A::method1; 103 try { 104 assertTrue(bar.m(1) == 2); 105 } catch (Exception e) { 106 assertTrue(false); 107 } 108 109 bar = new A()::method2; 110 try { 111 assertTrue(bar.m(1) == 3); 112 } catch (Exception e) { 113 assertTrue(false); 114 } 115 116 bar = A::method3; 117 try { 118 assertTrue(bar.m(1) == 4); 119 } catch (Exception e) { 120 assertTrue(false); 121 } 122 123 bar = new A()::method4; 124 try { 125 assertTrue(bar.m(1) == 5); 126 } catch (Exception e) { 127 assertTrue(false); 128 } 129 130 bar = new A()::method5; 131 try { 132 assertTrue(bar.m(1) == 6); 133 } catch (Exception e) { 134 assertTrue(false); 135 } 136 } 137 138 /** 139 * Test SAM conversion of method reference in method/constructor argument context 140 */ 141 private static void testMethodArgument() { 142 assertTrue(test1(A::method1) == 2); 143 assertTrue(test1(new A()::method2) == 3); 144 assertTrue(test1(A::method3) == 4); 145 assertTrue(test1(new A()::method4) == 5); 146 assertTrue(test1(new A()::method5) == 6); 147 test2(A::method1, 2); 148 test2(new A()::method2, 3); 149 test2(A::method3, 4); 150 test2(new A()::method4, 5); 151 test2(new A()::method5, 6); 152 } 153 154 /** 155 * Test SAM conversion of method reference in return statement context 156 */ 157 private static void testReturnStatement() { 158 Bar bar = test3(0); 159 try { 160 assertTrue(bar.m(1) == 2); 161 } catch (Exception e) { 162 assertTrue(false); 163 } 164 bar = test3(1); 165 try { 166 assertTrue(bar.m(1) == 3); 167 } catch (Exception e) { 168 assertTrue(false); 169 } 170 bar = test3(2); 171 try { 172 assertTrue(bar.m(1) == 4); 173 } catch (Exception e) { 174 assertTrue(false); 175 } 176 bar = test3(3); 177 try { 178 assertTrue(bar.m(1) == 5); 179 } catch (Exception e) { 180 assertTrue(false); 181 } 182 bar = test3(4); 183 try { 184 assertTrue(bar.m(1) == 6); 185 } catch (Exception e) { 186 assertTrue(false); 187 } 188 bar = test3(5); 189 try { 190 bar.m(1); 191 assertTrue(false); 192 } catch (MyException e) { 193 } catch (Exception e) { 194 assertTrue(false); 195 } 196 } 197 198 /** 199 * Test SAM conversion of method reference in cast context 200 */ 201 private static void testCast() { 202 assertTrue(((Foo)A::method1).m(1) == 2); 203 try { 204 assertTrue(((Bar)new A()::method2).m(1) == 3); 205 } catch (Exception e) { 206 assertTrue(false); 207 } 208 } 209 210 /** 211 * Test SAM conversion of method reference in array initializer context 212 */ 213 private static void testArrayInitializer() { 214 Object[] oarray = {"a", 1, (Foo)A::method3}; //last element need a cast 215 Object[] oarray2 = {"a", 1, (Bar)new A()::method4}; //last element need a cast 216 Foo[] farray = {A::method1, new A()::method2, A::method3, new A()::method4, new A()::method5}; 217 Bar[] barray = {A::method1, new A()::method2, A::method3, new A()::method4, new A()::method5, A::method6}; 218 } 219 220 /** 221 * Test SAM conversion of method reference in conditional expression context 222 */ 223 private static void testConditionalExpression(boolean b) { 224 Foo f = b ? A::method3 : new A()::method5; 225 if(b) 226 assertTrue(f.m(1) == 4); 227 else 228 assertTrue(f.m(1) == 6); 229 230 Bar bar = b ? A::method1 : A::method6; 231 if(b) { 232 try { 233 assertTrue(bar.m(1) == 2); 234 } catch (Exception e) { 235 assertTrue(false); 236 } 237 } 238 else { 239 try { 240 bar.m(1); 241 assertTrue(false); 242 } catch (MyException e) { 243 } catch (Exception e) { 244 assertTrue(false); 245 } 246 } 247 } 248 249 /** 250 * Test SAM conversion of method reference in lambda expression body 251 */ 252 private static void testLambdaExpressionBody() { 253 Foo f = n -> ((Foo)A::method3).m(n); 254 assertTrue(f.m(1) == 4); 255 256 Bar b = n -> { return ((Foo)new A()::method5).m(n); }; 257 try { 258 assertTrue(b.m(1) == 6); 259 } catch (Exception e) { 260 assertTrue(false); 261 } 262 } 263 264 public static void main(String[] args) { 265 testAssignment(); 266 testMethodArgument(); 267 testReturnStatement(); 268 testCast(); 269 testArrayInitializer(); 270 testConditionalExpression(true); 271 testConditionalExpression(false); 272 testLambdaExpressionBody(); 273 274 assertTrue(assertionCount == 32); 275 } 276 277 static class MyException extends Exception {} 278 279 static class A { 280 281 int value = 0; 282 283 A() { 284 } 285 286 A(Foo f) { 287 value = f.m(9); 288 } 289 290 A(Bar b) { 291 try { 292 value = b.m(9); 293 } catch (MyException e){} 294 } 295 296 static Integer method1(int n) { 297 return n + 1; 298 } 299 300 int method2(Integer n) { 301 return value == 0 ? n + 2 : n + value; 302 } 303 304 static int method3(int n) { 305 return n + 3; 306 } 307 308 Integer method4(Integer n) { 309 return value == 0 ? n + 4 : n + value; 310 } 311 312 Integer method5(Integer n) { 313 return value == 0 ? new Integer(n + 5) : new Integer(n + value); 314 } 315 316 static int method6(Integer n) throws MyException{ 317 throw new MyException(); 318 } 319 } 320} 321