SamConversion.java revision 1414:01c9d4161882
1/* 2 * Copyright (c) 2012, 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 bar = new A()::method6; 138 try { 139 bar.m(1); 140 assertTrue(false); 141 } catch (MyException e) { 142 } catch (Exception e) { 143 assertTrue(false); 144 } 145 } 146 147 /** 148 * Test SAM conversion of method reference in method/constructor argument context 149 */ 150 private static void testMethodArgument() { 151 assertTrue(test1(A::method1) == 2); 152 assertTrue(test1(new A()::method2) == 3); 153 assertTrue(test1(A::method3) == 4); 154 assertTrue(test1(new A()::method4) == 5); 155 assertTrue(test1(new A()::method5) == 6); 156 test2(A::method1, 2); 157 test2(new A()::method2, 3); 158 test2(A::method3, 4); 159 test2(new A()::method4, 5); 160 test2(new A()::method5, 6); 161 A a = new A(A::method1); //A(Foo f) called 162 assertTrue(a.method2(1) == 11); 163 assertTrue(a.method4(1) == 11); 164 assertTrue(a.method5(1) == 11); 165 A a2 = new A(new A()::method2); //A(Bar b) called 166 assertTrue(a2.method2(1) == 12); 167 assertTrue(a2.method4(1) == 12); 168 assertTrue(a2.method5(1) == 12); 169 } 170 171 /** 172 * Test SAM conversion of method reference in return statement context 173 */ 174 private static void testReturnStatement() { 175 Bar bar = test3(0); 176 try { 177 assertTrue(bar.m(1) == 2); 178 } catch (Exception e) { 179 assertTrue(false); 180 } 181 bar = test3(1); 182 try { 183 assertTrue(bar.m(1) == 3); 184 } catch (Exception e) { 185 assertTrue(false); 186 } 187 bar = test3(2); 188 try { 189 assertTrue(bar.m(1) == 4); 190 } catch (Exception e) { 191 assertTrue(false); 192 } 193 bar = test3(3); 194 try { 195 assertTrue(bar.m(1) == 5); 196 } catch (Exception e) { 197 assertTrue(false); 198 } 199 bar = test3(4); 200 try { 201 assertTrue(bar.m(1) == 6); 202 } catch (Exception e) { 203 assertTrue(false); 204 } 205 bar = test3(5); 206 try { 207 bar.m(1); 208 assertTrue(false); 209 } catch (MyException e) { 210 } catch (Exception e) { 211 assertTrue(false); 212 } 213 } 214 215 /** 216 * Test SAM conversion of method reference in cast context 217 */ 218 private static void testCast() { 219 assertTrue(((Foo)A::method1).m(1) == 2); 220 try { 221 assertTrue(((Bar)new A()::method2).m(1) == 3); 222 } catch (Exception e) { 223 assertTrue(false); 224 } 225 } 226 227 /** 228 * Test SAM conversion of method reference in array initializer context 229 */ 230 private static void testArrayInitializer() { 231 Object[] oarray = {"a", 1, (Foo)A::method3}; //last element need a cast 232 Object[] oarray2 = {"a", 1, (Bar)new A()::method4}; //last element need a cast 233 Foo[] farray = {A::method1, new A()::method2, A::method3, new A()::method4, new A()::method5}; 234 Bar[] barray = {A::method1, new A()::method2, A::method3, new A()::method4, new A()::method5, A::method6}; 235 } 236 237 /** 238 * Test SAM conversion of method reference in conditional expression context 239 */ 240 private static void testConditionalExpression(boolean b) { 241 Foo f = b ? A::method3 : new A()::method5; 242 if(b) 243 assertTrue(f.m(1) == 4); 244 else 245 assertTrue(f.m(1) == 6); 246 247 Bar bar = b ? A::method1 : A::method6; 248 if(b) { 249 try { 250 assertTrue(bar.m(1) == 2); 251 } catch (Exception e) { 252 assertTrue(false); 253 } 254 } 255 else { 256 try { 257 bar.m(1); 258 assertTrue(false); 259 } catch (MyException e) { 260 } catch (Exception e) { 261 assertTrue(false); 262 } 263 } 264 } 265 266 /** 267 * Test SAM conversion of method reference in lambda expression body 268 */ 269 private static void testLambdaExpressionBody() { 270 Foo f = n -> ((Foo)A::method3).m(n); 271 assertTrue(f.m(1) == 4); 272 273 Bar b = n -> { return ((Foo)new A()::method5).m(n); }; 274 try { 275 assertTrue(b.m(1) == 6); 276 } catch (Exception e) { 277 assertTrue(false); 278 } 279 } 280 281 public static void main(String[] args) { 282 testAssignment(); 283 testMethodArgument(); 284 testReturnStatement(); 285 testCast(); 286 testArrayInitializer(); 287 testConditionalExpression(true); 288 testConditionalExpression(false); 289 testLambdaExpressionBody(); 290 291 assertTrue(assertionCount == 38); 292 } 293 294 static class MyException extends Exception {} 295 296 static class A { 297 298 int value = 0; 299 300 A() { 301 } 302 303 A(Foo f) { 304 value = f.m(9); 305 } 306 307 A(Bar b) { 308 try { 309 value = b.m(9); 310 } catch (MyException e){} 311 } 312 313 static Integer method1(int n) { 314 return n + 1; 315 } 316 317 int method2(Integer n) { 318 return value == 0 ? n + 2 : n + value; 319 } 320 321 static int method3(int n) { 322 return n + 3; 323 } 324 325 Integer method4(Integer n) { 326 return value == 0 ? n + 4 : n + value; 327 } 328 329 Integer method5(Integer n) { 330 return value == 0 ? new Integer(n + 5) : new Integer(n + value); 331 } 332 333 static int method6(Integer n) throws MyException{ 334 throw new MyException(); 335 } 336 } 337} 338