1 /* 2 * Copyright (c) 2024, 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 8324873 27 * @summary Test valid placements of super()/this() in constructors 28 * @enablePreview 29 * @ignore fails at execution time because of Optional 30 */ 31 32 public value class ValueClassSuperInitGood { 33 34 ValueClassSuperInitGood(Object obj) { 35 } 36 37 ValueClassSuperInitGood(int x) { 38 } 39 40 // Default constructor provided by compiler 41 static value class Test0 { 42 } 43 44 // No explicit calls to this()/super() 45 static abstract value class Test1 { 46 Test1() { 47 } 48 Test1(int a) { 49 super(); 50 this.hashCode(); 51 } 52 } 53 54 // Explicit calls to this()/super() 55 static abstract value class Test2<T> { 56 static int i; 57 Test2() { 58 this(0); 59 } 60 Test2(int i) { 61 Test2.i = i; 62 super(); 63 } 64 Test2(T obj) { 65 this(java.util.Objects.hashCode(obj)); 66 } 67 public T get() { 68 return null; 69 } 70 } 71 72 // Explicit this()/super() with stuff in front 73 static value class Test3 { 74 int x; 75 final int y; 76 final int z; 77 78 Test3() { 79 new Object().hashCode(); 80 new Object().hashCode(); 81 super(); 82 this.x = new Object().hashCode(); 83 this.y = new Object().hashCode() % 17; 84 this.z = this.x + this.y; 85 } 86 } 87 88 static abstract value class Test5Abstract { 89 Test5Abstract(Object obj) {} 90 } 91 92 // Reference within constructor to outer class that's also my superclass 93 abstract value class Test5 extends Test5Abstract { 94 Test5(Object obj) { 95 if (obj == null) 96 throw new IllegalArgumentException(); 97 super(ValueClassSuperInitGood.this); // NOT a 'this' reference 98 } 99 } 100 101 // Initialization blocks 102 value class Test6 { 103 final long startTime; 104 final int x; 105 { 106 this.x = 12; 107 } 108 Test6() { 109 long now = System.nanoTime(); 110 long then = now + 1000000L; 111 while (System.nanoTime() < then) { 112 try { 113 Thread.sleep(1); 114 } catch (InterruptedException e) { 115 Thread.currentThread().interrupt(); 116 break; 117 } 118 } 119 super(); 120 this.startTime = now; 121 } 122 } 123 124 // Mix up inner classes, proxies, and super() calls 125 // Copied mostly from UnverifiableInitForNestedLocalClassTest.java 126 public static void test7(final String arg) { 127 final String inlined = " inlined "; 128 abstract value class LocalClass { 129 String m() { 130 return "LocalClass " + arg + inlined; 131 } 132 133 abstract value class SubClass extends LocalClass { 134 @Override 135 String m() { 136 return "SubClass " + arg + inlined; 137 } 138 } 139 140 value class SubSubClass extends SubClass { 141 @Override 142 String m() { 143 return "SubSubClass " + arg + inlined; 144 } 145 } 146 147 value class AnotherLocal { 148 value class AnotherSub extends LocalClass { 149 AnotherSub() { 150 } 151 AnotherSub(int x) { 152 this((char)x); 153 } 154 AnotherSub(char y) { 155 super(); 156 } 157 @Override 158 String m() { 159 return "AnotherSub " + arg + inlined; 160 } 161 } 162 } 163 } 164 } 165 166 // Anonymous inner class 167 public static void test8() { 168 new Test2<Byte>(null) { 169 @Override 170 public Byte get() { 171 return (byte)-1; 172 } 173 }; 174 } 175 176 // Qualified super() invocation 177 public static value class Test9 extends Test5 { 178 179 public Test9(ValueClassSuperInitGood implicit, Object obj) { 180 obj.hashCode(); 181 implicit.super(obj); 182 } 183 } 184 185 // Copied from WhichImplicitThis6 186 public static abstract value class Test10 { 187 private int i; 188 public Test10(int i) { this.i = i; } 189 public value class Sub extends Test10 { 190 public Sub() { 191 super(i); // i is not inherited, so it is the enclosing i 192 } 193 } 194 } 195 196 // Two constructors where only one invokes super() 197 public static value class Test11 { 198 public Test11() { 199 } 200 public Test11(int x) { 201 super(); 202 } 203 } 204 205 // Nested version of the previous test 206 public static value class Test12 { 207 Test12() { 208 class Sub { 209 public Sub() { 210 } 211 public Sub(int j) { 212 super(); 213 } 214 } 215 } 216 } 217 218 // Nested super()'s requiring initialization code appended 219 public static value class Test13 extends Test5Abstract { 220 final int x = new Object().hashCode(); 221 Test13() { 222 super(new Object() { 223 public void foo() { 224 class Bar { 225 final int y = new Object().hashCode(); 226 Bar() { 227 super(); 228 } 229 Bar(int ignored) { 230 } 231 } 232 } 233 }); 234 } 235 } 236 237 // Initializer in initializer block 238 public static value class Test14 { 239 final int x; // initialized in constructor 240 final int y; // initialized in initialization block 241 final int z = 13; // initialized with intializer value 242 public Test14() { 243 this(0); 244 } 245 public Test14(boolean z) { 246 this.x = z ? 1 : 0; 247 } 248 public Test14(int x) { 249 super(); 250 this.x = x; 251 } 252 { 253 this.y = -1; 254 } 255 } 256 257 // Qualified super() invocation with superclass instance 258 public static abstract value class Test15 { 259 260 final String name; 261 262 public Test15(String name) { 263 this.name = name; 264 } 265 266 public abstract value class Test15b extends Test15 { 267 268 public Test15b(String name) { 269 super(name); 270 } 271 272 public String getName() { 273 return Test15.this.name; 274 } 275 } 276 } 277 278 public static value class Test15c extends Test15.Test15b { 279 public Test15c(Test15 a, String name) { 280 a.super(name); 281 } 282 } 283 284 // Mixing up outer instances, proxies, and initializers 285 public static value class Test16 { 286 287 final String x = String.valueOf(new Object().hashCode()); 288 289 public void run() { 290 291 final String y = String.valueOf(new Object().hashCode()); 292 293 class Sub { 294 295 final String z; 296 297 Sub(String z, int ignored) { 298 this(z, (float)ignored); 299 } 300 301 Sub(String z, float ignored) { 302 this.z = z; 303 } 304 305 Sub(String z, byte ignored) { 306 super(); 307 this.z = z; 308 } 309 310 Sub(String z, char ignored) { 311 this(z, (int)ignored); 312 } 313 314 String x() { 315 return x; 316 } 317 318 String y() { 319 return y; 320 } 321 322 String z() { 323 return z; 324 } 325 } 326 327 final String z = String.valueOf(new Object().hashCode()); 328 329 final Sub[] subs = new Sub[] { 330 new Sub(z, 1), 331 new Sub(z, -1), 332 new Sub(z, (float)0), 333 new Sub(z, (byte)0), 334 new Sub(z, (char)0) 335 }; 336 337 for (int i = 0; i < subs.length; i++) { 338 //System.err.println("i = " + i); 339 final Sub sub = subs[i]; 340 final String subx = sub.x(); 341 final String suby = sub.y(); 342 final String subz = sub.z(); 343 if (!x.equals(subx)) 344 throw new RuntimeException("x=" + x + " but sub[" + i + "].x()=" + subx); 345 if (!y.equals(suby)) 346 throw new RuntimeException("y=" + y + " but sub[" + i + "].y()=" + suby); 347 if (!z.equals(subz)) 348 throw new RuntimeException("z=" + z + " but sub[" + i + "].z()=" + subz); 349 } 350 } 351 } 352 353 // Records 354 public value class Test17 { 355 356 record Rectangle(float length, float width) { } 357 358 record StringHolder(String string) { 359 StringHolder { 360 java.util.Objects.requireNonNull(string); 361 } 362 } 363 364 record ValueHolder(int value) { 365 ValueHolder(float x) { 366 if (Float.isNaN(x)) 367 throw new IllegalArgumentException(); 368 this((int)x); 369 } 370 } 371 } 372 373 static abstract value class AR<V> implements java.io.Serializable { 374 public AR(V initialValue) { 375 } 376 377 public AR() { 378 } 379 380 public final V get() { 381 return null; 382 } 383 } 384 385 // Exceptions thrown by initializer block 386 public static value class Test18 extends AR<Object> { 387 388 { 389 if ((this.get().hashCode() % 3) == 0) 390 throw new MyException(); 391 } 392 393 public Test18(Object obj) throws MyException { 394 super(obj); 395 } 396 397 public Test18(boolean fail) throws MyException { 398 Object obj; 399 for (obj = new Object(); true; obj = new Object()) { 400 if (((obj.hashCode() % 3) == 0) != fail) 401 continue; 402 break; 403 } 404 this(obj); 405 } 406 407 public static class MyException extends Exception { 408 } 409 } 410 411 // super()/this() within outer try block but inside inner class 412 public static value class Test19 { 413 public Test19(int x) { 414 try { 415 new Test1(x) { 416 @Override 417 public int hashCode() { 418 return x ^ super.hashCode(); 419 } 420 }; 421 } catch (StackOverflowError e) { 422 // ignore 423 } 424 } 425 } 426 427 // local class declared before super(), but not used until after super() 428 public static value class Test20 { 429 public Test20() { 430 class Foo { 431 Foo() { 432 Test20.this.hashCode(); 433 } 434 } 435 super(); 436 new Foo(); 437 } 438 } 439 440 // local class inside super() parameter list 441 public static value class Test21 extends AR<Object> { 442 private int x = 1; 443 public Test21() { 444 super(switch ("foo".hashCode()) { 445 default -> { 446 class Nested {{ System.out.println(x); }} // class is NOT instantiated - OK 447 yield "bar"; 448 } 449 }); 450 } 451 } 452 453 public static void main(String[] args) { 454 new Test0(); 455 new Test1() {}; 456 new Test1(7) {}; 457 new Test2<Byte>() {}; 458 new Test2<>(args) {}; 459 new Test3(); 460 new ValueClassSuperInitGood(3).new Test5(3) {}; 461 new ValueClassSuperInitGood(3).new Test6(); 462 ValueClassSuperInitGood.test7("foo"); 463 ValueClassSuperInitGood.test8(); 464 new Test9(new ValueClassSuperInitGood(5), "abc"); 465 new Test10(7) {}; 466 new Test11(9); 467 new Test12(); 468 new Test13(); 469 Test14 t14 = new Test14(); 470 assert t14.x == 0 && t14.y == -1 && t14.z == 13; 471 t14 = new Test14(7); 472 assert t14.x == 7 && t14.y == -1 && t14.z == 13; 473 new Test15c(new Test15("foo"){}, "bar"); 474 new Test16().run(); 475 new Test17.StringHolder("foo"); 476 try { 477 new Test17.StringHolder(null); 478 throw new Error(); 479 } catch (NullPointerException e) { 480 // expected 481 } 482 try { 483 new Test18(true); 484 assert false : "expected exception"; 485 } catch (Test18.MyException e) { 486 // expected 487 } 488 try { 489 new Test18(false); 490 } catch (Test18.MyException e) { 491 assert false : "unexpected exception: " + e; 492 } 493 new Test19(123); 494 new Test20(); 495 new Test21(); 496 } 497 }