JDK-4211070 : Java should support const parameters (like C++) for code maintainence
  • Type: Enhancement
  • Component: specification
  • Sub-Component: language
  • Affected Version: 1.2.0,1.3.1,1.4.2,5.0
  • Priority: P5
  • Status: Closed
  • Resolution: Won't Fix
  • OS:
    linux,solaris_8,windows_95,windows_xp linux,solaris_8,windows_95,windows_xp
  • CPU: x86,sparc
  • Submitted: 1999-02-12
  • Updated: 2005-10-14
  • Resolved: 2005-03-19
Related Reports
Duplicate :  
Duplicate :  
Relates :  
Relates :  
Relates :  
Description
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)
======================================================================

Comments
EVALUATION It's possible, but I would rather hold the line on creaping featurism. One can design around this (using interfaces, wrappers etc.). gilad.bracha@eng 1999-12-22 There are no current plans to add this feature to Java. In addition to creeping featurism, we see the following problems with this feature: * Adding const is too late now. Had this been added from 1.0, the situation could have been different. * Const pollution: the C++ approach requires all const methods to be marked with a const keyword. This means that most methods will have to be marked const explicitly. This tend to clutter all methods in C++. * Compatibility is a very important feature of the JDK. Arguably, the collection classes should be modified to indicate that the elements are const. That would require all existing implementations to be updated in the same way, effectively breaking all existing non-JDK implementations of the collection interfaces. Similarly, hashCode would have to be const, breaking the current implementation of String. ###@###.### 2005-03-01 22:19:57 GMT
01-03-2005

WORK AROUND Name: igT44549 Date: 02/11/99 No clean solution that I know of - just hope that no methods change objects in unexpected ways. Hope your system test finds any bugs instead of your customers. ======================================================================
02-10-2004