Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-8311288

Super-class alterations to fields in sub-class are overwritten by the subclass

XMLWordPrintable

    • generic
    • generic

      ADDITIONAL SYSTEM INFORMATION :
      Windows 11 Enterprise
      OS build: 22000.2057

      openjdk version "17.0.7" 2023-04-18
      OpenJDK Runtime Environment Temurin-17.0.7+7 (build 17.0.7+7)
      OpenJDK 64-Bit Server VM Temurin-17.0.7+7 (build 17.0.7+7, mixed mode, sharing)

      A DESCRIPTION OF THE PROBLEM :
      When the super class modifies fields of the sub class before they are technically assigned then these changes will have no effect and will be over written by the sub class after wards.

      Closest related bug I could find is: https://bugs.java.com/bugdatabase/view_bug?bug_id=6275018

      REGRESSION : Last worked in version 17.0.7

      STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
      create a class that has a method that gets called in the constructor of this super class. This must modify fields in its sub-class

      EXPECTED VERSUS ACTUAL BEHAVIOR :
      EXPECTED -
      The following lines should be printed in the terminal
      Check
      123
      true
      "Hello World"

      constructor
      123
      true
      "Hello World"

      when done constructing
      123
      true
      "Hello World"
      ACTUAL -
      The following lines are actually be printed in the terminal:
      Check
      123
      true
      "Hello World"

      constructor
      null
      null
      null

      when done constructing
      null
      null
      null

      ---------- BEGIN SOURCE ----------
      /*
       * I created the following github repo that should contain all the java code to reproduce:
       * https://github.com/St-H123/Java-Compliler-bug
       *
       * I also wrote more information but in case you would also like the raw source code I have it here:
       */

      /**
       * Just a class to help explain the problem as short as possible
       */
      public class Entry {
      public String value = "";
      public String field = "";
      }

      /**
       * The fixed version of the problemetic class
       */
      public class FixedStringAssigned extends SuperClass {

      public Integer valueOne;
      public Boolean valueTwo;
      public String valueThree;

      public FixedStringAssigned(String input) throws IllegalArgumentException {
      super(input);

              System.out.println("constructor");
      System.out.println(valueOne);
      System.out.println(valueTwo);
      System.out.println(valueThree);
              System.out.println();
      }

          @Override
      protected void assign(Entry entry) throws IllegalArgumentException{
      switch (entry.field) {
      case "valueOne":
      valueOne = Integer.parseInt(entry.value);
      break;
      case "valueTwo":
      valueTwo = Boolean.parseBoolean(entry.value);
      break;
      case "valueThree":
      valueThree = entry.value;
      break;
      default:
      super.assign(entry);
      }
      }

          @Override
          protected void check() {

              System.out.println("Check");
              
              System.out.println(valueOne);
              if (valueOne == null) {
                  throw new IllegalStateException();
              }

      System.out.println(valueTwo);
              if (valueTwo == null) {
                  throw new IllegalStateException();
              }

              System.out.println(valueThree);
              if (valueThree == null) {
                  throw new IllegalStateException();
              }

              System.out.println();
          }
      }

      public class Main {
          public static void main(String[] args) {

              StringAssigned instance = new StringAssigned("valueOne:123,valueThree:\"Hello World\",valueTwo:true");

              System.out.println("when done constructring");
              System.out.println(instance.valueOne);
              System.out.println(instance.valueTwo);
              System.out.println(instance.valueThree);
              System.out.println();
          }
      }

      /**
       * Helper class.
       */
      public class Splitter {
      public static Entry[] split(String input) {
      String[] array = (input.split(","));
      Entry[] entries = new Entry[array.length];
      for (int index = 0; index < array.length; index++) {
      String[] split = array[index].split(":");
      String field = split[0];
      String value = split[1];
      entries[index] = new Entry();
      entries[index].value = value;
      entries[index].field = field;
      }
      return entries;
      }
      }

      /**
       * The problemetic class
       */
      public class StringAssigned extends SuperClass {

      public Integer valueOne = null;
      public Boolean valueTwo = null;
      public String valueThree = null;

      public StringAssigned(String input) throws IllegalArgumentException {
      super(input);

              System.out.println("constructor");
      System.out.println(valueOne);
      System.out.println(valueTwo);
      System.out.println(valueThree);
              System.out.println();
      }

          @Override
      protected void assign(Entry entry) throws IllegalArgumentException{
      switch (entry.field) {
      case "valueOne":
      valueOne = Integer.parseInt(entry.value);
      break;
      case "valueTwo":
      valueTwo = Boolean.parseBoolean(entry.value);
      break;
      case "valueThree":
      valueThree = entry.value;
      break;
      default:
      super.assign(entry);
      }
      }

          @Override
          protected void check() {

              System.out.println("Check");
              
              System.out.println(valueOne);
              if (valueOne == null) {
                  throw new IllegalStateException();
              }

      System.out.println(valueTwo);
              if (valueTwo == null) {
                  throw new IllegalStateException();
              }

              System.out.println(valueThree);
              if (valueThree == null) {
                  throw new IllegalStateException();
              }

              System.out.println();
          }
      }

      /**
       * The super class of StringAssigned.
       */
      public abstract class SuperClass {

      public SuperClass(String input) throws IllegalArgumentException{

      Entry[] entries = Splitter.split(input);

      for (Entry entry : entries) {
      this.assign(entry);
      }

              this.check();
      }

          /**
           * goes through the fields and assigns them
           * throws an exception if the field is not reconised
           */
      protected void assign(Entry entry) throws IllegalArgumentException{
      throw new IllegalArgumentException();
      }

          /**
           * Checks all the fields and throws exceptions while in the
           * constructor if they are not correct.
           */
          protected abstract void check();
      }

      ---------- END SOURCE ----------

      CUSTOMER SUBMITTED WORKAROUND :
      not a true work around but instead of using `... = null;` just leave the assignment. This would only work if you want your default to be `null`

      FREQUENCY : always


            adev Anupam Dev
            webbuggrp Webbug Group
            Votes:
            0 Vote for this issue
            Watchers:
            2 Start watching this issue

              Created:
              Updated:
              Resolved: