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

Java should support const parameters (like C++) for code maintainence

XMLWordPrintable

    • Icon: Enhancement Enhancement
    • Resolution: Won't Fix
    • Icon: P5 P5
    • None
    • 1.2.0, 1.3.1, 1.4.2, 5.0
    • specification
    • x86, sparc
    • linux, solaris_8, windows_95, windows_xp

      Name: igT44549 Date: 02/11/99


      I think Java would be a much safer language if it would
      support const parameters like C++. For instance:
      class Example
      {
        void func1(MyObject const myObject)
        {
           myObject.const_methods_only();
        }
      }

      If a non-const method were called, the compiler would flag
      it as an error.

      Right now it is impossible to know if a method you call
      might modify the class you pass it. This would be something
      that the compiler can find easily, but is extremely difficult
      for a programmer to know until after the code has been found
      defective by a customer.

      I think adding const to the language would greatly improve
      the Java language in terms of how bug free Java programs
      would be. You already did a great job of elimating memory
      bugs, why not take it one step farther and help eliminate
      other bugs by supporting const parameters (and methods).
      (Review ID: 52919)
      ======================================================================

      Name: jl125535 Date: 01/04/2002


      FULL PRODUCT VERSION :
      java version "1.3.1"
      Java(TM) 2 Runtime Environment, Standard Edition (build
      1.3.1-b24)
      Java HotSpot(TM) Client VM (build 1.3.1-b24, mixed mode)


      FULL OPERATING SYSTEM VERSION :
      Windows 2000
      5.00.2195
      Service Pack 2

      ADDITIONAL OPERATING SYSTEMS :
      (All others)


      A DESCRIPTION OF THE PROBLEM :
      Related bugs: 4211070, 4093718, 4069541.

      A COMPREHENSIVE THEORY OF ADDING 'CONST' TO JAVA

      [This document is also available at
      <http://david.tribble.com/text/javaconst.html>.]

      CONCEPTS

      A reference variable or constant declared as 'final'
      has a value that is immutable and cannot be modified to
      refer to any other object than the one it was
      initialized to refer to. Thus the 'final' specifier
      applies to the value of the variable itself, and not to
      the object referenced by the variable.

      A reference variable or constant declared as 'const'
      refers to an immutable object that cannot be modified.
      The reference variable itself can be modified (if it is
      not declared 'final'). Thus the 'const' specifier
      applies to the value of the object referenced by the
      variable.

      An object is modified whenever any of its accessible
      member variables are the subject of an assigment (or
      compound assignment) or increment/decrement operator.
      An object is also considered modified whenever a call
      is made to any of its member methods that are not
      declared 'const' (see below).

      CLASS VARIABLES

      Only reference (non-primitive) types can have the
      'const' specifier applied to them. Primitive types
      that need to be declared 'const' should be declared
      'final' instead.

      A member variable declared 'const' and declared with a
      reference type (i.e., any class type extending 'Object'
      or any interface type), or declared as an array of any
      type, refers to an immutable object whose value cannot
      be modified. The reference variable itself can be
      modified, provided that it is not declared 'final'.

      The following code fragment illustrates these rules:

          class Foo
          {
              int max = 100;
              final int LENGTH = 80;
              const int GREAT = 15; // Error
              final const int LEAST = 2; // Error

              Bar b = new Bar(17);
              final Bar bf = new Bar(23);
              const Bar bc = new Bar(55);
              final const Bar bfc = new Bar(79);
          }

      The member variable 'max' is modifiable.

      The member constant 'LENGTH' is not modifiable (because
      it is 'final').

      The member variable 'b' is modifiable, and refers to an
      object that is modifiable.

      The member constant 'bf' is not modifiable (because it
      is 'final'), but the object to which it refers is
      modifiable.

      The member constant 'bc' is modifiable, but the object
      to which it refers is not modifiable (because it is
      'const').

      The member constant 'bf' is not modifiable (because it
      is 'final'), and the object to which it refers is not
      modifiable (because it is 'const').

      ASSIGMENT EXPRESSIONS

      Expressions of reference type, either const or
      non-const, can be freely assigned to const variables of
      compatible reference types, and can be freely passed to
      methods as const arguments of compatible reference
      types.

      Expressions of const reference type can only be
      assigned to const variables, or passed as const
      arguments to methods, of compatible reference types.

      An expression of const reference type cannot be cast to
      a compatible non-const (see the Cast Expressions
      section below).

      Consider the following code fragment:

          class Foosball
              extends Bar
          {
              const Bar bc;
              Foosball fb;
              const Foosball fc;

              void enconst1(Foosball f)
              {
                  bc = f; // Okay, implicit cast
                  fb = f; // Okay
                  fc = f; // Okay, implicit cast
              }

              void enconst2(const Foosball f)
              {
                  bc = f; // Okay, implicit cast
                  fb = f; // Error, f is const
                  fc = f; // Okay
              }
          }

      INTERFACE CONSTANTS

      Since all member variables of interfaces must be
      declared 'final', all such member variables are
      actually constants. In all other respects, the rules
      for const member constants are the same as for const
      class member variables.

      Consider the following code fragment:

          interface Baz
          {
              static final Bar bf = new Bar(1);
              static const Bar bc = new Bar(2);
              static final const Bar bfc = new Bar(3);
          }

      Member methods of classes that implement interface
      'Baz' cannot modify any of the three constants 'bf',
      'bc', or 'bfc' (because they are final). Such methods
      are allowed to modify the Bar object referenced by
      'bf', but cannot modify the objects referenced by 'bc'
      or 'bfc' (because they are const).

      CLASS METHODS

      Static member methods declared 'const' cannot modify
      any static class variables of their parent class. They
      also cannot modify any objects referenced by any static
      class reference variables of their parent class.

      Non-static member methods declared 'const' may not
      modify any member variables (static or not) of their
      parent class object ('this'). They also cannot modify
      any objects referenced by any class reference variables
      (static or not) of their parent class.

      A method declared 'const' declares that it cannot
      modify any member variables of its class, nor any
      objects referenced by those variables. Conversely, a
      method that is not declared 'const' declares that it
      may modify member variables of its class or objects
      referenced by them (and should be assumed to do so,
      whether it actually does or not).

      The following code fragment illustrates these rules
      (it is assumed that 'Bar.peek()' is a const method and
      'Bar.poke()' is not):

          class Foomy
          {
              static Bar bs = new Bar(15);
              Bar b = new Bar(34);
              const Bar b2 = new Bar(53);

              void frob() // Not const
              {
                  bs = new Bar(48); // Okay
                  b = new Bar(81); // Okay
                  frotz(); // Okay
                  b.poke(13); // Okay
                  b.peek(); // Okay
                  b2.poke(13); // Error
                  b2.peek(); // Okay
              }

              void fraz() const // Is const
              {
                  bs = new Bar(48); // Error
                  b = new Bar(81); // Error
                  frotz(); // Error
                  b.poke(13); // Error
                  b.peek(); // Okay
                  b2.poke(13); // Error
                  b2.peek(); // Okay
              }

              void frotz() // Not const
              { ... }
          }

      Member method 'frob()' is not declared 'const', so it
      can modify any non-const member variables of class
      'Foomy'. It cannot modify any const member variables,
      though, such as 'b2'.

      Member method 'fraz()' is declared 'const', so it
      cannot modify any member variables of class 'Foomy'.
      It also cannot indirectly modify any member of the
      class by calling non-const member methods, such as
      'frotz()'. It also cannot indirectly modify any member
      by calling non-const methods on those members, such as
      'b.poke()' (which is not declared 'const' in this
      example).

      Member method 'frotz()' is not declared 'const', so it
      must be assumed to modify member variables of class
      'Foomy'.

      A non-static member method of a class that extends
      another class or implements an interface which
      overrides a method of the base class or implements a
      method of the interface must be declared with a
      "const-ness" that is at least as restrictive as the
      method it overrides. In other words, if a method in a
      base class is declared 'const', then all subclass
      methods that override that method must also be declared
      'const'; on the other hand, an overriding method may be
      declared 'const' even if the method it overrides is not
      declared 'const'. (In this respect, 'const' specifiers
      are similar to 'throws' clauses.)

      The following code fragment illustrates these rules:

          class Foomier
              extends Foomy
          {
              void frob() const // Added const
              { ... }

              void fraz() const // Must be const
              { ... }
          }

          class Foomiest
              extends Foomy
          {
              void fraz() // Error, Must be const
              { ... }
          }

      LOCAL VARIABLES

      Variables local to a method body may be declared
      'const', in which case the objects they refer to cannot
      be modified. The reference variables themselves can be
      modified provided they are not declared 'final'.

      Consider the following code fragment:

          void f()
          {
              Object o = new Object();
              final Object fo = new Object();
              const Object co = new Object();
              final const Object fco = new Object();
              ...
          }

      The object referenced by 'o' can be modified, and
      variable 'o' can be modified to refer to a different
      object.

      The object referenced by 'fo' can be modified, but
      variable 'fo' cannot be modified to refer to any other
      object (because it is 'final').

      The object referenced by 'co' cannot be modified
      (because it is const), but variable 'co' can be
      modified to refer to another object.

      The object referenced by 'fco' cannot be modified
      (because it is const), and variable 'fco' cannot be
      modified to refer to another object (because it is
      'final').

      METHOD PARAMETERS

      The same rules apply to method parameters as to local
      variables. That is, a reference parameter declared
      'final' cannot be modified, but the object which it
      references can be modified. A reference parameter
      declared 'const' can be modified, but the object which
      it references cannot be modified.

      CAST EXPRESSIONS

      A reference variable declared 'const' cannot be cast to
      its equivalent non-const type. Such casting would
      remove the "const-ness" of the object referred to, and
      thereby violate const type safety.

      Conversely, a reference variable may be implictly cast
      to its equivalent const type (by assignment or by
      passing it as an argument to a method), which adds
      "const-ness" to the resulting reference expression.
      There is no syntax for an explicit such cast, since
      assigning a const or non-const reference expression to
      a const variable does not require an explicit cast.

      Consider the following code fragment:

          class Fooberry
          {
              const Bar bc;

              const Bar enconst(Bar b)
              {
                  bc = b; // Okay
                  return b; // Okay
              }

              const Bar addconst(Bar b)
              {
                  bc = (const Bar) b; // Error
                  return (const Bar) b; // Error
              }
          }

      METHOD RETURN VALUES

      Methods may return non-primitive const object types,
      which means that the values returned by such methods
      cannot be modified (but that references to such objects
      can be assigned and passed to other methods).

      This implies that the return value of a method declared
      as returning a const type can be assigned to only a
      const reference variable or passed as an argument to a
      method taking a const reference parameter.

      Consider the following code fragment:

          class Foodor
          {
              Bar getBar()
              { ... }

              const Bar cBar()
              {
                  return new Bar(); // Okay
              }

              void f()
              {
                  Bar b;
                  const Bar bc;

                  b = getBar(); // Okay
                  bc = getBar(); // Okay
                  b = cBar(); // Error
                  bc = cBar(); // Okay
              }
          }

      CONCLUSION

      Adding the 'const' specifier keyword to Java would
      bring new forms of type safety to the language, and
      simplify the semantics of "read-only" objects.

      This bug can be reproduced always.

      CUSTOMER WORKAROUND :
      Splitting classes into "read-only" and "writable"
      interfaces, which is a real pain, especially in a language
      without multiple inheritance.
      (Review ID: 137795)
      ======================================================================

            ahe Peter Ahe
            iris Iris Clark
            Votes:
            0 Vote for this issue
            Watchers:
            0 Start watching this issue

              Created:
              Updated:
              Resolved:
              Imported:
              Indexed: