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