Wed, 14 May 2014 15:41:28 -0600
8034223: Most-specific should not have any special treatment for boxed vs. unboxed types
Summary: Rewrite most-specific logic to conform to JLS 8 15.12.2.5
Reviewed-by: vromero
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 */
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 */
34 public class SamConversion {
36 static int assertionCount = 0;
38 static interface Foo {
39 Integer m(int i);
40 }
42 static interface Bar {
43 int m(Integer i) throws MyException;
44 }
46 private static void assertTrue(boolean b) {
47 assertionCount++;
48 if(!b)
49 throw new AssertionError();
50 }
52 private static int test1(Foo foo) {
53 return foo.m(1);
54 }
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 }
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 }
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);
90 foo = new A()::method2; //instance reference, parameter type unboxing and return type boxing
91 assertTrue(foo.m(1) == 3);
93 foo = A::method3; //static reference, parameter type matching and return type boxing
94 assertTrue(foo.m(1) == 4);
96 foo = new A()::method4; //instance reference, parameter type unboxing and return type matching
97 assertTrue(foo.m(1) == 5);
99 foo = new A()::method5; //instance reference, parameter type unboxing and return type matching
100 assertTrue(foo.m(1) == 6);
102 Bar bar = A::method1;
103 try {
104 assertTrue(bar.m(1) == 2);
105 } catch (Exception e) {
106 assertTrue(false);
107 }
109 bar = new A()::method2;
110 try {
111 assertTrue(bar.m(1) == 3);
112 } catch (Exception e) {
113 assertTrue(false);
114 }
116 bar = A::method3;
117 try {
118 assertTrue(bar.m(1) == 4);
119 } catch (Exception e) {
120 assertTrue(false);
121 }
123 bar = new A()::method4;
124 try {
125 assertTrue(bar.m(1) == 5);
126 } catch (Exception e) {
127 assertTrue(false);
128 }
130 bar = new A()::method5;
131 try {
132 assertTrue(bar.m(1) == 6);
133 } catch (Exception e) {
134 assertTrue(false);
135 }
136 }
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 }
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 }
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 }
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 }
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);
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 }
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);
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 }
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();
274 assertTrue(assertionCount == 32);
275 }
277 static class MyException extends Exception {}
279 static class A {
281 int value = 0;
283 A() {
284 }
286 A(Foo f) {
287 value = f.m(9);
288 }
290 A(Bar b) {
291 try {
292 value = b.m(9);
293 } catch (MyException e){}
294 }
296 static Integer method1(int n) {
297 return n + 1;
298 }
300 int method2(Integer n) {
301 return value == 0 ? n + 2 : n + value;
302 }
304 static int method3(int n) {
305 return n + 3;
306 }
308 Integer method4(Integer n) {
309 return value == 0 ? n + 4 : n + value;
310 }
312 Integer method5(Integer n) {
313 return value == 0 ? new Integer(n + 5) : new Integer(n + value);
314 }
316 static int method6(Integer n) throws MyException{
317 throw new MyException();
318 }
319 }
320 }