Java Solaris Communities Sun Store Join SDN My Profile Why Join?
 
Bug Database
Bug Detail
Quick Lists
Top 25 Bugs
Top 25 RFE's
Recently Closed Bugs
Printable Page Printable Page


Bug Database
Bug ID: 4211070
Votes 787
Synopsis Java should support const parameters (like C++) for code maintainence
Category java:specification
Reported Against 1.2 , 1.3.1 , 1.4.2
Release Fixed
State 11-Closed, Will Not Fix, request for enhancement
Priority: 5-Very Low
Related Bugs 6336887 , 4910043 , 6432147 , 5076739 , 4617197
Submit Date 12-FEB-1999
Description


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)
======================================================================




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  customer  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  customer  referenced by the variable.

A reference variable or constant declared as 'const'
refers to an immutable  customer  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  customer  referenced by the
variable.

An  customer  is modified whenever any of its accessible
member variables are the subject of an assigment (or
compound assignment) or increment/decrement operator.
An  customer  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  customer  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
 customer  that is modifiable.

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

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

The member constant 'bf' is not modifiable (because it
is 'final'), and the  customer  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  customer  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  customer  ('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  customer  referenced by 'o' can be modified, and
variable 'o' can be modified to refer to a different
 customer .

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

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

The  customer  referenced by 'fco' cannot be modified
(because it is const), and variable 'fco' cannot be
modified to refer to another  customer  (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  customer  which it
references can be modified.  A reference parameter
declared 'const' can be modified, but the  customer  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  customer  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  customer  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)
======================================================================
Posted Date : 2005-10-14 06:11:03.0
Work Around




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.
======================================================================
Evaluation
It's possible, but I would rather hold the line on creaping featurism. One can
design around this (using interfaces, wrappers etc.).

  xxxxx@xxxxx   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.

  xxxxx@xxxxx   2005-03-01 22:19:57 GMT
Comments
  
  Include a link with my name & email   

Submitted On 31-AUG-1999
andythomascramer
Yes, yes, yes, for efficient large-scale development we need const parameters,
const methods, const return instances, and const members -- for instances of
user-defined types as well as primitive types.
Java currently only supports a small subset of const-correctness checking:
const primitive types and constant references to non-const user-defined types. 
Const-correctness checking is similar in importance and concept to
type-checking. Just as the lack of strong type-checking in some other languages
increases costs, so does the lack of const-checking in Java.
  We are &lt;em&gt;not&lt;/em&gt; seeking a run-time check of constness, just a
compile-time check of a const qualifier to type. 
  The workarounds suggested by Sun and others (copying, immutable classes,
subclassing from an immutable interface, and wrapping with an immutable class)
all increase development, maintenance and/or performance costs, and aren't
always feasible. 
  Yes, const is implemented in C++ syntax, but the concept of const is generic
to language. 
  The longer const is withheld from the language, the larger the body of
const-incorrect legacy code that's being generated. Please fix it as soon as
possible.


Submitted On 09-OCT-1999
Zoso
Design By Contract features allow for much safer programming, which has been a
Java goal.  Any support that the language can provide makes DBC much more
practical, since support by convention requires a higher degree of developer
knowledge and skill as well as more development effort.  The ability to specify
C++-like const features would move closer to supporting DBC in Java by allowing
a more complete contract definition for method declarations.  I would also
suggest looking into other DBC features like pre- &amp; post-conditions and
invariants.  See the Eiffel language implentation for other ideas.


Submitted On 21-OCT-1999
sonstone
I have a need for this type of functionality when it comes to object
inspection.  It
would be nice to look at a java bean's getter methods and automatically call
the 
get methods to know what these values return, but there is no way that I can
tell 
if the get method will modify the state of the object.  I think this feature
would help 
out significally when using dynamic method calls and the such.


Submitted On 18-NOV-1999
billrobertson
It has been pointed out that immutable super interfaces are a good work around.
It has also been pointed out that that can not be used all of the time.  In
addtion, that amounts to more work for the developers.
The key here is that Java does not properly support const correctness, and that
amounts to a lot of extra work for the users of the language.  More work spent
either adding and passing around immutable interfaces, or more work spent
debugging because someone unknowingly diddled with an object that (s)he
shouldn't have.
Java needs proper support for const correctness.  Const object references and
const methods do a good job at that IMHO.
Vote for this RFE.  :)



Submitted On 15-DEC-1999
aleclee
I'm a fan of const correctness too, but then you need a mechanism like the
&quot;mutable&quot; keyword in C++ to notify the compiler of member data that
may be modified without violating the spirit of const.


Submitted On 17-DEC-1999
sdempsey
One vote from me.  Use const to mark an object as immutable &amp; to mark
methods
as non-mutating.  (I know there are design patterns for using immutable
interfaces 
but these are clunky).  Note that Java itself &quot;cheats&quot; and stipulates
String
as being const.  
Having confusing C++ syntax isn't a problem because 
there's already a &quot;final&quot; keyword with a different meaning.


Submitted On 17-JAN-2000
schapel
Note that if this feature were implemented in Java like it is in C++, that it
would tell the
compiler that it may not modify an object *through a const reference*. It would
*not*
tell the compiler that an object itself is const. For example, if there were
one const and
one non-const reference to the same object, we could not modify the object by
using the
const reference, but we *could* modify the object through the non-const
reference.
In C and C++ I used pointers to const objects often, and if this feature were
added to
Java, I think it would help me produce code that documents itself better and
that would
tend to have fewer bugs.


Submitted On 20-JAN-2000
derbyshire16
I agree. Const correctness should be supported. Add the const keyword -- use
final on reference types as is, to indicate they can't be re-pointed at new
referents, and make final and const synonymous on primitives. Const on objects
would restrict to invoking const methods only and not modifying ivars except if
these were flagged mutable. Const on instance methods would indicate they don't
modify the underlying object. Const on a class would assert that the pbjects
were immutable -- same as const on its non-constructor methods and non-private
ivars. There'd be a mutable keyword for cached or transient data to be flagged
as such -- stuff that is computed or transient and doesn't affect the object's
identity or API, just its performance, e.g. caching a matrix inverse with the
matrix but lazily computing it only when it is desired.


Submitted On 25-JAN-2000
andythomascramer
The desired enhancement is not a particular
keyword or syntax, but increased const semantics.

Used for const methods, interfaces:
- Are an incomplete workaround using
  type-checking in place of const-checking.
- Double the complexity of the class model.
- Don't support static consistency checking by
  the compiler of const method
  implementation.
- May decrease performance by preventing
  optimization of &quot;final&quot; methods on const
  references.
- Don't support const arrays. (Ask me about
  caching an array of 40,000 doubles ...).
- Increase the code base.
- Increase development and maintenance effort.
- Aren't used in practice, even by Sun.


Submitted On 26-JAN-2000
brettporter
Yes, I would like const parameters and methods. I don't know how many times I
mess up classes or arrays by forgetting to make copies.


Submitted On 26-FEB-2000
jonathanfinn
schapel is right - the semantics of const needs very 
careful thought before adding it to the language. e.g. 
consider a function

static void add(Matrix a, const Matrix b) {...}
    // adds b to a, leaving b unchanged

We then invoke it somewhere like this:
  add(x,y);  // y unchanged
But in one case y has in fact changed, because x and y 
refer to the same object. The C++ const semantics are easy 
to implement but not very useful - it's fairly useless to 
know that add() can't change y directly if it can change it 
indirectly! So C++-style const can only protect you against 
some types of const bug.


Submitted On 28-FEB-2000
andythomascramer
static void add(Matrix a, const Matrix b) {...}
    // adds b to a, leaving b unchanged

On the contrary, it's very useful to know, from the 
standpoint of someone calling this method, that an object 
can't be modified ***through the pointer passed to the 
formal b argument***. In the usual case of a call to add
(x,y), where x and y point to different, independent 
objects, the caller knows that the physical object pointed 
to by y can't be modified by the method through y. In the 
case of a call to add(x,x), the caller knows that the 
object may be modified, because it's passed through the non-
const pointer.


Submitted On 01-MAR-2000
dkf
The above example illustrates just why const is *not*
enough, since what you (or at least I) would like instead is
to state that the second argument is not modified and must
never be the same as the first argument, and this
restriction is not enforced by the use of const.  Instead,
it would be better to have Eiffel-like pre/post conditions
and invariants., and since these would form part of the
contract entered into by the class or method, this would be
far easier to maintain.

Plus, it is all to easy to get swamped under &quot;const creep&quot;
in C++ so not having any of that stuff is refreshing in
Java!

(Also, what about immutable objects?  etc.)


Submitted On 02-MAR-2000
andythomascramer
Pre/post conditions and invariants would _also_ be nice. 
However, const type qualifiers are easily checked at 
compile time and suffer little, if any, runtime costs. And 
they can be used in more general situations than method 
calls (e.g., an instance can store a const pointer). Both 
const type qualifiers and method invariants have their 
advantages, and neither precludes the other.

And no, what I would like is not necessary a guarantee of 
invariance during a method call, but rather a restriction 
against variance _ever_ through a const pointer provided to 
any object or method. If I provide _any_ non-const pointers 
to the same object, I know that the object can be modified.


Submitted On 18-MAR-2000
Ixchel
Another issue related to 'const' that I haven't seen 
anybody mention yet:

The &quot;Simple Assertion Facility&quot; proposal (#JSR-000041, 
currently underway in the Sun Community Process) proposes 
the addition of an 'assert' keyword which can be used to 
check various conditions that a software engineer thought 
would be true, like so:

    assert &lt;boolean-expression&gt;;

However, these checks are not supposed to have side effects 
on the state of the program, since asserts can 
be 'disabled' which would cause their expressions to not be 
evaluated. Unfortunately, however, there is currently no 
way to enforce a lack of side effects in Java. Why? Because 
someone could write code that looks like this:

     assert anObject.someFunction(anotherObject) &gt; 5;

and the someFunction method could modify either anObject or 
anotherObject, which would cause the assert statement to 
have different behavior depending on whether or not asserts 
were enabled.

Now, if const-correctness were instituted in the language, 
we could define 'assert' like so:

     assert &lt;const-boolean-expression&gt;;

where const-boolean-expression was an expression which had 
the following limitations:
1) No side effect operators (+=, ++, --, =, etc.) were 
allowed.
2) Only 'const' methods taking only 'const' or pass-by-
value parameters could be invoked.

This would eliminate the possibility of someone 
creating 'assert' statements that had side-effects (or at 
least would force them to cast-away-const to do it), and 
would substantially reduce the probability of bugs 
introduced due to 'assert'.


Submitted On 21-MAR-2000
Derek Foster
As another issue to consider: When arrays are being 
returned from methods, it is common practice to make copies 
of them (via clone()) to return, like this:

private final int [] myPrivateArray = ???;
int [] aMethodReturningAnArray()
{
    return (int [])myPrivateArray.clone();
}

This extra copy is done just to make sure that the caller 
of the method doesn't screw up the object that the method's 
data is called on (by modifying the returned array, and 
hence modifying the object's private data).

With const arrays, this extra copy could be eliminated 
(since the caller couldn't modify the array), resulting in 
more efficient code. The result would look like this:

private const int const [] myPrivateArray = ???;
int const [] aMethodReturningAnArray()
{
    return myPrivateArray;
}

Incidentally, I am not particularly enamored of the 'const' 
keyword, because it seems to imply to me that something 
will be truly constant (unchanging over time), rather than 
just constant with respect to a particular reference to it 
which is declared 'const'. I'd rather it were called 
something else that carried implications of &quot;You can't 
modify it through me&quot;.

Also incidentally, what syntax should be used? I don't like 
C++'s syntax (too vague: Most people don't know the 
difference between &quot;const int *&quot; and &quot;int const *&quot; and &quot;int 
* const&quot;) I suggest that it consistently be prefixed to the 
particular item it is to apply to, so declarations can be 
read left-to-right:

const Thing [] x;   // array of constant Things
Thing const [] x;   // constant array of non-constant Things
final Thing [] x;   // fixed reference to non-constant 
array of non-constant Things
final const Thing const [] x;   // fixed reference to 
constant array of constant Things

It might be helpful (less typing) to use some kind of piece 
of punctuation (e.g. @, #, or such) instead of a 'const' 
keyword for this. Otherwise, declarations can get rather 
long and unwieldy.


Submitted On 29-MAR-2000
abies
  const Thing [] x;   // array of constant Things
  Thing const [] x;   // constant array of non-constant
Things

I know that it is done in such way in C++, but I would hate
to see it in java.
It is way too puzzling for beginners and even for more
experienced programmer it requires a moment of thinking
instead of just 'look-and-know' which is true for most java
constructs.

Note that this only affects arrays - in all other cases
there is no reason
for having two positions for const, given 'final' keyword.
It also does not
cope fully with java multidimensional arrays - const
int[][][] const const x; ??

I would suggest forgetting about having constant arrays and
stick just to
arrays pointing to const objects. Why ? You can easily do
constant array
by wrapping it into constant Vector/ArrayList, but you are
unable to to do
the ArrayList returning constant Objects.

And this gives second problem - I suppose that there would
have to be 
number of collection classes, like ConstCollection,
ConstIterator etc + 
corresponding methods in all classes (constantIterator()
etc). Unfrotunately it would require doubling a some other
methods like addAll(Collection). It would be best if addAll
could work both on Collection and ConstCollection, but I'm
afraid it is impossible to do with current semantics (maybe
with 
covariant (const versus non-const in this case) return types
it would be possible ?).


Submitted On 31-MAR-2000
dkf
The only way you can properly handle asserts is to specify
that any methods called have no detectable side-effects. 
Which is very tough to detect, since you may have an object
whose exterior appearance is that of immutability, but whose
actual implementation does all sorts of things that are not
constant (talking to a database, for example.)  No amount of
playing around with a &quot;const&quot; keyword will add this check
either; only DBC (or anything stronger than that, of course)
can offer these sorts of guarantees.  You could prohibit
method calls (const would only ever tell you about what
you're doing to parameters and results, and nothing about
what is really going on) in asserts, but that is just too
restrictive - I'd like to assert things about strings...

Given that &quot;const&quot; doesn't solve many problems (it only
helps when you're passing around arrays that shouldn't be
assigned to) and it introduces plentiful problems of its own
(creeping constism plagues C++, making it harder to write
code than it ought to be) we're better off without it.  If
you put side-effects in your asserts or muck around
inappropriately with arrays, your code will break.  But it
is impossible to stop people from writing bad code; all you
can do is make it easier to write good code...


Submitted On 05-MAY-2000
mcharsley
I agree, much needed in a language where any object is 
passed by reference - just as long as we have a mutable 
keyword for those lazily-evaluated member variables. I 
can't understand why the Java authors appeared to view it 
as being as bad as goto.

The only problem is that there's so much existing Java code 
out there that doesn't support const, that we'd probably 
need some abomination like const_cast, just as C++ needed 
it to be able to use all the existing C code.


Submitted On 08-MAY-2000
dkf
What good would &quot;const&quot; do anyway?  There are three cases to
consider:
1) const primitive types - These can be done quite happily
through other mechanisms already present in Java; the values
themselves are immutable (42 is always 42!) and variables
containing these values can always be declared to be final. 
This applies equally to a reference to an object or array.
2) const objects - What exactly *is* a const object?  Is it
one that doesn't change any of its fields?  Is it one who's
public interface has no set methods and no writable public
fields?  Is it one that always gives the same answers for
any of its method calls (given the same inputs, of course.) 
The first of these operations is unduly restrictive; the
object would not even be able to keep a record of the number
of times it has been accessed.  The second is just plain
laughable as the object could just call those methods
something else.  The third requires much more sophisticated
analysis to enforce, and is clearly not robust in the
presence of accesses outside the current Java environment. 
The only solution to this sort of thing is something like
Design By Contract, but integrating that with Java means
integrating it with the whole of the Java libraries too,
which is a lot of work.
3) const arrays - this is the only case where it would have
any value, but there are still problems, since what happens
if the array is changed by some other route (another thread,
or just a separate non-const reference in this thread)? 
Life is not a bed of roses and things will still go wrong. 
Unless you forbid mixing between const arrays and non-const
arrays (a ridiculous suggestion, I'm sure you would agree!) 
I just don't see a nice way of handling constant arrays,
though there are certainly possibilities (c.f.
http://www.javasoft.com/aboutJava/communityprocess/review/jsr041/)
if you are willing to go the DBC-like way of using
assertions.

Looking at the above, I'd say that the chances that const is
going to add anything particularly valuable to the Java
language are small.  One thing it could do is already
covered by existing constructs, another requires a
completely different strategy, and the third doesn't offer
nearly enough.  And it would open up a morass of mess as the
const typing propagates through libraries, causing problems
for loads of existing code.

Please, no const.  The costs are too high for the meagre
benefits offered.


Submitted On 17-MAY-2000
epovazan
I'll add my vote for the const modifier, to be used as C++ 
uses it. Besides, it's already reserved in Java, so use it!
const is a DESIGN tool. It is also a SPECIFICATION as to 
what an object does, just like exceptions are specified in 
the interface.
Anyone who is a C++ coder has found problems when passing a 
const object to a method requiring a non const object. In 
99% of the cases, it show a design flaw in the libraries. 
There is always a workaround in the 1%, including 
const_cast when used with caution.
At the moment I have to resort to implementing a constant 
interface (only getters) for most of my objects.
And I bet the garbage collector would get a break ... how 
many libraries simply new() an object when they return it, 
to prevent the accidental modification of members.


Submitted On 23-MAY-2000
danfuzz
I'll add my vote for the functionality, but I have to say I
absolutely hate the term &quot;const&quot; as used in C++ because
it's so misleading (misleading enough that in my past I've
had to work around bugs in C++ compilers that mistook it
to mean &quot;immutable&quot;). I'll put forward two suggestions:
&quot;readonly&quot; and &quot;sensory.&quot; As for the latter, there is some
history of the use of that term in capability systems for
the
proposed meaning. (See, for example,
&lt;http://www.cis.upenn.edu/%7EKeyKOS/OSRpaper.html&gt;.)
But I think the former is reasonably contrastive to
&quot;immutable&quot;
(which I'll also suggest should be a concept supported by
the language and VM) and has that all-lowercase-look made
so popular by the &quot;instanceof&quot; keyword and &quot;arraycopy&quot;
method.


Submitted On 25-MAY-2000
svenmeier
Please no const - keep the Java syntax simple.
(I totally agree with &quot;dkf&quot;.)
There should be a way to vote *against* a so called &quot;rfe&quot; 
in the bug database...


Submitted On 30-MAY-2000
andythomascramer
  Dkf's protests against const objects are not relevant to 
this RFE. This RFE requests a compile-time-checked 
qualifier for references that restricts the operations that 
may be performed through them -- not a run-time-checked 
guarantee of object immutability.
  Support for such references can be added without 
modifying existing libraries to be const-correct. Whether 
and how to modify existing libraries is a separate issue.


Submitted On 09-AUG-2000
jdesmet
As the JVM is an interpreter the const should definitly not 
be only a Compile Time thing. It should be consistant with 
the Reflection API, as the const is part of your method 
signature. Not everything is yet resolved at compile time.


Submitted On 18-AUG-2000
frankbranch
A better approach would be to declare particular instances 
as immutable.  Why you may ask?  Supose we create a class 
that represent color.  A programmer may want to create a 
color instance that would change as various states in the 
application change.  However, the class designer would like 
to be able to produce singletons that represent specific 
colors that could never be changed (ie. red, blue, etc...)

Current you have to create two classes one class that 
represent color and another that exends color with all of 
the accessor methods disabled.

Alternately, you could create one class and add a readonly 
internal boolean, and create constructors that set this 
flag.

A language based solution would be better and more 
consistant.

For example:

public class color
{
   public static final Color red = new immutable Color
(255,0,0);
}

Any attempt to change internal member varibles or red would 
result in an ObjectImmutabilityException.  If another 
programmer needed a color that they could change.  They 
would just use the old delclaration.

Color statusLight = new Color(255, 0, 0);
if (status.equals(&quot;Warning&quot;)
{
    statusLight.setRGB(128,128,0);
}


Submitted On 22-AUG-2000
andythomascramer
On the other hand, the misuse of instances marked immutable 
frequently could not be detected at compile-time, and 
checking them at run-time would add an additional run-time 
cost to every method call, even on instances of classes not 
using the feature.

Personally, I'd rather have my compiler complain than my 
clients, and I don't want Java to run any slower.

For immutable instances of classes with mutators, cheaper 
options are available. 
* You cite one that provides run-time checking. 
* Switching the inheritance relationship so that the 
immutable interface is the superclass allows compile-time 
checking. 
* The typical Java approach is simply not to not provide 
mutators -- at the cost to performance of creating a new 
object whenever modifications are desired.
* With const-restricted references, a programmer could 
provide an effectively immutable instance by providing only 
const-restricted references to it -- unless casting-away-
const were supported.


Submitted On 22-AUG-2000
guill
Please don't add const in the Java syntax.

Of course their is case where the const would be usefull, the same also stand for all the feature of the C++, 
or any other language.  I think sun make a good job in choosing the language feature that are really usefull 
to most programmer and putting away the one that are usefull only in specific situation or very confusing.  
It`s a lot simpler to understand someone else code in Java language that in C++, thanks to the confusing 
features that don't exist in Java.

There is other language extension that will prevent a lot more mistake and create a lot less confusion : 
generic type, covariant return type, pre and post condition...


Submitted On 30-AUG-2000
bmckeever
The type of programming that the lack of const engenders can be seen in the Collection API.  One of the 
things about it that drives me crazy is the idea of (e.g.) static List Collection.unmodifiableList(List list).  The 
iterator() for this collection throws an UnsupportedOperationException if you call its remove() method.  It is 
quite likely that this won't be detected until runtime, and quite unlikely that there will be a handler for this 
exception (since it's unchecked).  On the other hand, using C++-like const, you could have a const 
Collection return a const iterator, and have remove() be a non-const method.  Then the above error is 
caught at *compile-time*.  I would much rather have a compiler tell me that something is not quite right 
than have a user tell me.


Submitted On 30-AUG-2000
amorrowcrcg
Has anyone discovered any third party tools for doing 
compile time const checking?

Many of the RFE's in the top ten have associated third 
party precompilers - GJ for genericity, iContract for DBC, 
aspectJ for AOP (although that is not an RFE). I would be 
very interested in finding an analogous tool for const 
correctness.

I'm also curious as to whether any work has been done on 
designing a generic framework for compiler/language 
extensions. It would be very usefull to have a tool that 
combined the above technologies and allowed new plugins, 
perhaps using JavaML and XSL... any info or comments?


Submitted On 10-SEP-2000
javabandit
YES.  Please add const (or an enhanced 'final') to the Java 
language.

In large applications (especially MDI apps), it is 
important to be able to control the mutability of objects 
across different contexts.

The current implementation of using the 'final' modifier 
with a parameter is really useless.  It only keeps the 
reference from being reassigned.  Very silly... which is 
why it is hardly ever used in this context.

Writing an interface or a wrapper to handle this kind of 
functionality is very expensive and promotes code bloat.  

The concept of objects/primitives being flagged as read-
only is nothing new to OOP.  There is no reason why Java 
should NOT have this fundamental capability, IMHO.

Although, people seem to only want compile-time checking, I 
will stand up (as I have in other forums) and say that in 
this age of distributed computing and EJBs, it becomes 
increasingly important to have runtime checking as well.  
Only requiring compile-time checking is fine, but it really 
is thinking 'inside of the box'.

The ability to control the mutability of an object/EJB 
across distributed platforms would be ideal.

This gets my vote.



Submitted On 12-SEP-2000
javabandit
Andy,

You are correct that the RFE does not explicity state that 
a read-only marker be placed on objects, but if you read 
the all of the RFEs (and I know you have -- because I've 
seen your posts), you'll see that the evaluations/solutions 
are rarely exactly what the RFE asked for in the first 
place.

Using your own example, I think it would be highly useful 
to be able to declare an object as 'final' (or const) 
within the scope of that method call:

double distance = MyClass.distance(final p1, final p2);

And you are correct.  That is not to say that the object 
itself is globally immutable; rather, that it is only 
immutable within the scope (or context) of the distance() 
method.  

Being able to declare the arguments as const within the 
signature of the distance() method itself would be greatly 
helpful.  Java does support this syntax, but it is severely 
limited.  Unfortunately.  I REALLY like the idea of being 
able to pass an immutable marker along with the reference 
to an object.

Hopefully they lay the groundwork to get this in by 1.5.  I 
don't see them supporting runtime checking at all (with 
respect to const/strict/parameterized-type checking).  Its 
probably too much of a major overhaul.

But one can always hope...

--Rick


Submitted On 18-SEP-2000
andythomascramer
Rick and I discussed this at length over email.

I misunderstood Rick's post. He was requesting the ability 
to mark references as restricted to read-only operations -- 
the basis of this RFE – not the the ability to mark objects 
as read-only.

We also have different assumptions. I assume that the 
compiler would not allow copying a const-restricted 
reference to a non-const-restricted reference (e.g., an 
argument copied to a parameter in a method call). This 
enables compile-time checking, for example, that a const-
restricted formal parameter is not modified in either its 
method _or_ the call graph descending from its method.

Rick does not make this assumption, and specifically wants 
to be able to pass const-restricted references to 
references not marked const-restricted -- so that such 
references could be passed to non-const-correct recipients 
without modifying the recipients. (Rick emphasizes its 
utility in distributed programming, where making the 
recipient const-correct might not be feasible.) His desire 
for runtime checking is a logical consequence.


Submitted On 04-OCT-2000
hwc
I, too, get confused by the different possible meanings 
of 'const'.  C++ introduces the idea of const methods, then 
immediately adds 'mutable' and 'const_cast&lt;&gt;' to get round 
it: not a good idea.  const function parameters may seem a 
good idea but are of limited value without const methods.

As a way of solving this problem, and others, I would much 
rather be able to pass objects into a function by value as 
well as by reference (see also RFE 4213096).


Submitted On 07-OCT-2000
derbyshire16
Just Say No to passing objects by value. This is the #1 cause of poorly-performing C++ programs -- large 
structures and objects being passed by value. It also raises issues of copying semantics for various classes. 
Const-correctness need not involve the &quot;const methods&quot; confusion in C++. We don't need a keyword at all, 
because Java stores metadata in its classes. A &quot;const-correct&quot; future version of javac can, in compiling a 
non-static method, note whether it changes non-&lt;code&gt;transient&lt;/code&gt; fields of the object, and if so, 
flag it as modifying, and otherwise as non-modifying. It could check method calls on constant references for 
being to methods flagged as modifying, and report an error if so. For interoperability with older versions, it 
would ignore methods not flagged either way (those from older implementations), and optionally produce 
warnings. Javadoc could be modified to indicate in generated documentation methods that don't modify the 
object and classes that have no modifying methods. Alternatively, one could  add new keywords, say 
&quot;nomod&quot; to indicate a method that is nonmodifying and &quot;immutable&quot; to indicate a class whose instances are 
supposed to be immutable, as convenient indicators that can show up in javadoc generated documentation 
and to force the programmer to pay attention to what they are doing. This would produce better 
correctness, as the programmer must in declaring certain methods and classes explicitly state their 
intentions for them, but makes interoperability and backward compatibility harder to maintain, particularly 
because of using new keywords. Reusing existing keywords, of course, would also be confusing -- the 
multiple meanings of &quot;const&quot; in C++ have been described as such. Even better alternative for future 
const-correctness: mark not the immutable classes and nonmodifying methods, but the mutable classes and 
modifying methods. This will really force programmers to specify their intentions -- they will have to declare 
all mutators as modifying, and any class of mutable objects as mutable. Agan, though, interoperability and 
backwards compatibility might be an issue.

&lt;p&gt;We do already have a way to indicate instance variables that are not intrinsic to an object's identity 
(&lt;code&gt;transient&lt;/code&gt;). However, we might want to separately specify data not serialized and data that 
isn't part of a constant object's identity. Certainly, we will need a new keyword to indicate references that 
can't be written through -- &quot;constant&quot; presumably -- since &quot;&lt;code&gt;final Foo bar&lt;/code&gt;&quot; indicates andt 
&lt;code&gt;bar&lt;/code&gt; can't be re-aimed and &lt;code&gt;public final Foo bar ()&lt;/code&gt; indicates that 
&lt;code&gt;bar&lt;/code&gt; can't be overridden.

&lt;p&gt;Immutable classes -- These would be enforced at compile time to only contain nonmodifying methods, 
aside from constructors of course. Non-&lt;code&gt;transient&lt;/code&gt; (or whatever) fields would have to be 
declared &lt;code&gt;final constant&lt;/code&gt;.

&lt;p&gt;Non-modifying methods -- Inside of these, the &lt;code&gt;this&lt;/code&gt; reference would be treated as 
&lt;code&gt;constant&lt;/code&gt;. One consequence would be that if the method returned &lt;code&gt;this&lt;/code&gt; it 
would have to be declared as returning a &lt;code&gt;constant&lt;/code&gt; whatever.

&lt;p&gt;Constant references -- A &lt;code&gt;constant&lt;/code&gt; reference could be re-aimed if not 
&lt;code&gt;final&lt;/code&gt;, but could not be modified -- only nonmodifying methods could be called on it and any 
non-&lt;code&gt;transient&lt;/code&gt; (or whatever) fields inside would be treated as &lt;code&gt;constant final&lt;/code&gt;.

&lt;p&gt;Primitive types -- For these, &lt;code&gt;constant&lt;/code&gt; would be synonymous with &lt;code&gt;final&lt;/code&gt;/


Submitted On 09-OCT-2000
andythomascramer
Derbyshire raises some good points, and is right on target 
about the negative aspects of passing objects by value. 
Objects and call stacks can both be big! I’d like to 
discuss just a few points. 

“Constant reference” seems misleading, so I’ll use the term 
“const-restricted reference” instead.

Explicit identification of immutable classes has been 
proposed at least by Gosling (see 
http://java.sun.com/people/jag/FP.html#overloading ). 
Perhaps all methods of immutable classes should be 
implicitly const-restricted? 

Const-restricted methods require explicit identification. 
Automated identification is not sufficient, because a 
method that’s logically non-const may be physically const 
one day and not the next. The const-restriction of a method 
is part of its public interface, and shouldn’t depend on 
its implementation (though the reverse may be true). In 
addition, Java has no means of identifying logically const-
restricted methods – only physically const-restricted.

It’s best to identify const-restricted references and 
methods explicitly, rather than non-const, because it makes 
the language more accessible to beginning users. This 
accessibility to beginners continues to be vital to Java’s 
success as a language. 

A new keyword is not _necessary_ to identify const-
restricted references and methods (though it might be 
desired). The following syntax is offered solely as a 
counter-example.

Examples of existing syntax:
  final int myInt             // Constant primitive.
  final MyClass myRef         // Constant reference to 
object
  final MyClass myMethod()    // Method which may not be 
overridden. 

Examples of syntax without new keyword for identifying 
const-restricted references and methods (combinations of 
these are possible):

  MyClass final myRef         // Variable, const-restricted 
reference.
                              // Only const-restricted 
methods can be 
                              // called through it.
  
  MyClass final myMethod( )   // Method that returns a 
const-restricted reference.
  int myMethod() final        // Const-restricted method; 
compile-time checked.

  double[ final ]  myArrayRef // Array whose member 
primitives may not be 
                              // modified through 
myArrayRef.
  MyClass[ final ] myArrayRef // Array whose member 
_references_ may not be 
                              // modified through 
myArrayRef.
  MyClass[ ] final myArrayRef // Array of const-restricted 
references.

  


Submitted On 20-OCT-2000
Ixchel
With regards to the above comment, I agree that in C++ this 
is a significant problem. In C++, it is often necessary to 
write both a const and a non-const version of the same 
method in order to satisfy the compiler, e.g.

    // Non-const method returns a reference to a non-
constant Thing
    Thing &amp; operator [] (int index) {
        return array[index];
    }
    // Const method returns a reference to a constant Thing
    const Thing &amp; operator [] (int index) const {
        return array[index];
    }

However, it has occurred to me that this problem could be 
solved if there were a keyword which indicated what I will 
call, for lack of a better term, 'covariant const'. In 
other words, the keyword would indicate constness if the 
object in question (the one that the method is being 
defined on) was const, and would indicate nonconstness if 
the object was non-const. This should be resolvable using 
static types at compile time.

For instance, in place of the declarations above, one might 
write:

    covconst Thing &amp; operator [] (int index) covconst {
        return array[index];
    }

The above method would be invokable both on a const object 
and on a non-const object. For purposes of static 
typechecking, if invoked on a const object, it would be 
considered to return a reference to a const Thing, but if 
invoked on a non-const object, it would be considered to 
return a reference to a non-const Thing.

Of course, someone can probably find a better keyword than 
the 'covconst' that I used in the above example. Also, I am 
not particularly fond of the C++ syntax for declaring 
methods to be const -- I think a more readable syntax could 
be found.


Submitted On 23-OCT-2000
hlovatt
Java and 'const'

Below is a proposal that adds a 'const' type construct to Java that is without
the problems associated with the C++ 'const' construct, needs little new
syntax, does not need new keywords, breaks little old code (compiler switch 
for old code), and does not need runtime support.

In summary I propose that 'm.inv()' means 'm' may change, whereas 'inv(m)' 
guarantees that the fields of 'm' don't change. Note 'inv(m)' is not a call to a 
static method but a call to an instance method. The proposal formalizes in the 
language the concept that method calls don't have side effects by making the 
fields of all method arguments constant. To help the compiler and the runtime, 
all method arguments are made implicitly 'final'. More details below.

The debate in this discussion group demonstrates that their is support to add
some sort of constant assurance to Java. The debate also demonstrates that
there is also considerable opposition to adding the C++ type of 'const'
construct because of problems people have encountered with this construct. 
Therefore I think Sun are wise in resisting adding a new construct until 
something better than the C++ 'const' is discovered.

The debate in the forum has centred on two different types of constant 
assurance. Firstly a form of design contract that assures the user of a method 
that objects don't change. Secondly a form of final for class objects. The 
second type of suggestion is typified by:

Type t = new immutable Type();

This proposal deals with the first form, a design contract. This is what
this RFE was originally concerning (I think - original posting not 100% clear on 
this). I am not dismissing the need for immutable class objects but think this 
extension is best handled in another forum.

There are many problems with the C++ 'const' construct as already discussed 
in this forum. So many as to easily justify Sun's decision not to add 'const' to 
Java. I will not review all the problems here, read the other postings if you are 
interested in seeing the problems people have encountered.

This proposal, like the others in this forum, deals almost exclusively with class 
objects, leaving primitive semantics largely unchanged. The only change to 
primitive semantics is that arguments are implicitly 'final'. My ideas stem from 
thinking about why 'const' is a problem in C++, since it seems so good when I 
first encountered it. I, like many others, started to change all my code to use 
'const' everywhere when it was first introduced in C/C++. That is until I 
discovered the problems that are now well documented, I now use 'const' 
sparingly. I think the problem is that it is a feature for the class writer, whereas 
what is required is a feature for the class user. Also the feature is a mixture of 
design by contract and immutable object whereas these different concepts are 
best treated separately.

By way of example I will use a hypothetical 'Matrix' class that has methods to 
invert a matrix ('inv'),  to add matrices, etc. The matrix class could store the 
elements of the matrix in a 'double[rows][colums]' array one array element for 
each value or if the matrix was sparsely populated use a smaller 
'double[rows][varable_length]' array and implicitly assume the missing elements 
are zero. The point is that it doesn't matter what the internal storage structure is 
to the user, therefore this class is a good example of a general problem.

The idea is that a non-static method invoked with the new syntax 
'method_name(object_name, ...)', e.g. 'inv(m)', guarantees that the fields of 'm' 
don't change. Whereas the existing non-static method invocation 
'object_name.method_name(...)', e.g. 'm.inv()', makes no such guarantee on 'm' 
(but formal arguments are guaranteed not to change). Note: 'inv(m)' is not a call 
to a static method, static method syntax is unchanged, i.e. 
'class_name.method_name(...)' or 'unused_obj


Submitted On 23-OCT-2000
andythomascramer
I was greatly mistaken. Method calls can occur on the lhs 
of an assignment statement in Java. (For example, a method 
could return a reference to an array, which could be 
subscripted on the lhs of an assignment statement.) And 
there are other situations in which both const and non-
const versions of a method may be desired. However, in 
practice, at least for me, such doubling occurs rarely.


Submitted On 23-OCT-2000
andythomascramer
  Jcb seems to suggest that each method requires a const 
and non-const version, merely to allow calling the method 
through both const-restricted and unrestricted references. 
This is not true, because const-restricted methods can be 
called on both const-restricted and unrestricted references.
  Jcb's comments about the doubling up of methods apply 
only to methods used on the left-hand-side of an assignment 
statement. This is possible in C++, given operator 
overloading (e.g., of operator[]), but not in Java. His 
concern about the &quot;doubling up of everything&quot; is hence 
unwarranted. Ixchel's solution would not be required for 
Java. (And, IMHO, though nice, it would not be used 
frequently enough in C++ to offset the costs of its 
inclusion in C++. This is off-topic, so let's discuss this 
via private email, if desired.)
  Jcb's comments about defining two versions of iterators 
are true. However, iterators are defined infrequently -- 
I've defined several in the last decade -- whereas const-
restricted references and methods could be used in every 
Java class.


Submitted On 24-OCT-2000
andythomascramer
While hlovatt’s proposal might be interesting for a new 
language, it isn’t feasible for inclusion in Java. Contrary 
to his assertions, a great deal of existing code does 
modify objects to which references are passed as formal 
parameters.

For example, consider one class: java.util.Collections. 
Here we find methods fill(), copy(), reverse(), shuffle() 
and sort(), all of which modify the objects pointed to by 
references passed as formal parameters. Its companion 
java.util.Collection contains toArray(Object[ ]). And is 
there really little existing code using System.arrayCopy()? 

In addition, his proposal doesn’t provide const-restriction 
for references returned from methods. Some of such methods 
require two versions in C++. Hlovatt eliminates the need 
for duplicate versions by eliminating the functionality 
that led to their requirement! Ixchel’s elegant solution 
eliminates the need without eliminating the functionality. 
As well, without const-restricted references in general, 
how does one return, given a const-restricted reference to 
a composite object, a const-restricted reference to a part 
of the composite? How does a compiler verify a method 
doesn’t save a copy of a reference parameter for later 
abuse?

Also, hlovatt’s proposal does not cover const-restriction 
of array contents. Consequently, the proposal does not 
provide a means for a class to expose arrays for reading 
but not writing. This is highly important for efficiency.

Const-restricted references and methods can be implemented 
in Java without breaking _any_ code, and with greater 
functionality.


Submitted On 25-OCT-2000
andythomascramer
Hlovatt's proposal doesn't conflict with this RFE; my 
criticism was for infeasibility and incompleteness. I 
overlooked ambiguity.

In addition to breaking much existing code, hlovatt's 
proposed syntax for calls of const-restricted methods is 
ambiguous. Let alpha be a reference to an instance of class 
Alpha. Let a call &quot;inv(alpha)&quot; exist in a class Beta. Is 
the call to a const-restricted method of alpha, or to a non-
const-restricted method of Beta? It isn't possible to tell 
from the call alone, and any resolution based on available 
methods in the two classes results in fragile code.

Also, note that special syntax for the call is unnecessary. 
Given const-restricted references, a caller could already 
mark a call as const-restricted either by using an existing 
const-restricted reference -- the usual case -- or casting 
to a const-restricted reference. Using the syntax I showed 
above, both calls of aMethod() below indicate that aMethod
() must be const-restricted:

  void someMethod( MyObject final o ) {
    o.aMethod(); // Must be a const-restricted method.
  }

  void anotherMethod( MyObject o ) {
    ((MyObject final) o).aMethod(); // Must be a const-
restricted method
  }

Finally, note that Java is neither a procedural nor 
functional language. There are frequent cases in which it 
is useful for instance-based methods to modify objects 
pointed to by formal parameters.


Submitted On 25-OCT-2000
hwc
hlovatt's suggestion seems to be a variation of the common
convention that functions should not modify their arguements
whereas procedures may.  Sticking with the example of matrix
inversion, if a matrix method is declared void inv() or as
static void inv(matrix m) is likely to invert the matrix
in place whereas a member declared matrix inv() or a static
method matrix inv(matrix m) should return a new object.

Rather than extending Java's syntax to create a new type of
function, I would find it useful to have a tool that warned
me when a class I was using might be breaking these rules.
This would be difficult for the compiler to do accurately
but that wouldn't matter - as a user, all I need to know is
that a function call *might* modify one its parameters.


Submitted On 30-OCT-2000
Ixchel
Oops. In that last comment, I accidentally reversed the 
names 'source' and 'destination'. Clearly, the const 
parameter should be the one being copied FROM. :-)


Submitted On 30-OCT-2000
hlovatt
I would like to thank everyone for their thoughtful comments concerning my 
proposal, which I will address below. However first I would like to digress.

In this forum a number of postings (including mine) have alluded to the fact that a 
C++ style 'const' is possible using a wrapper. However no one has spelt this out, 
in &quot;Java Platform Performance Strategies and Tactics&quot; a good example of a 
wrapper that adds C++ 'const' functionality is given (page 95). I have slightly 
modified their example below to illustrate the use of wrappers.

public class Location {
    protected int x, y;
    public Location() {}
    public Location(int x, int y) {this.x = x; this.y = y;}
    public final int getX() {return x;}
    public final int getY() {return y;}
    public final Location max(Location l) {...}
    ...
}
public class MutableLocation extends Location {
    public MutableLocation() {}
    public MutableLocation(int x, int y) {super(x, y);}
    public final void setX(int x) {this.x = x;}
    public final void setY(int y) {this.y = y;}
    public final MutableLocation add(MutableLocation m) {...}
    ...
}

You use 'Location' where you want a 'const' and 'MutableLocation' where you 
don't want 'const'. You can also cast away 'const', e.g. if 'm1', 'm2', and 'm3' are 
all of type 'MutableLocation' then you can write 
'((MutableLocation)(m1.max(m2))).add(m3)'. Note the use of inheritance allows 
the call 'm1.max(m2)' without needing any casts even though 'm1', and 'm2' are 
of type 'MutableLocation' and the arguments of 'max' are of type 'Location'. This 
wrapper construct is better than the C++ 'const' in three ways: the declaration 
syntax is clearer, the cast is type checked, and you can declare 'MutableLocation' 
private if you want users of your class to only have access to the immutable 
form. This later improvement (private mutable form) over C++ is apparently used 
in Sun libraries, e.g. the 'BigNumber' classes. Internally 'BigNumber' classes uses 
a mutable object for efficiency reasons but to keep the interface clean only the 
immutable form is made public. This wrapper technique and other forms, e.g. see 
'Collection' classes, can be applied to primitive arrays to give any desired degree 
of control over access.

To get back to my original posting, the reason for wanting the change I proposed 
is that adding a C++ 'const' construct gives us little we don't already have using 
wrappers. The change I proposed, as well as helping the user of a class also 
helped the runtime optimize the code. Two people have pointed out that they 
would like to write static methods that changed at least one argument (none static 
methods can change 'this' in my proposal already using the form 'm.inv()'). I 
would therefore suggest a change to my proposal, the first argument of static 
methods is not forced to have unchanging fields. I.E. 'Matrix.inv(m)' in this 
modified proposal is analogous to 'm.inv()' but still quite different to 'inv(m)', in my 
original proposal 'Matrix.inv(m)' was analogous to 'inv(m)'. This does not allow 
arbitrary arguments to change, only 'this' in the form 'm.inv()' and the first 
argument of a static method, e.g. 'Matrix.inv(m)', are allowed to change - all 
others arguments are constant. This maybe not what everyone want but I think it 
is good practice and is what is most comonly done, allowing arbitrary changing 
only encourages bad practice.

As one posting has pointed out the intention can be infered from the return type 
(if it is void it is an in-situ change) otherwise it returns a copy. This is essentially 
the same suggestion, it just depends on which set of syntax people prefer. 
Another posting raised concern re. name hiding, I don't think this is a problem, the 
existing methods of qualifying a name (e.g. 'this.&lt;method_name&gt;', etc.) can be 
used.

In subsequent thought about my proposal I came up with two problems


Submitted On 30-OCT-2000
Ixchel
Hmm. My main concern regarding hlovatt's proposal is that 
it defines methods in which ALL parameters are const, or NO 
parameters are const, but it allows no mixing of the two. 
So, for instance, I have no way to declare a method like 
the following C++ method:

    void copyArray(int * source, const int * destination, 
int howmany);

Note that this method has one const parameter and one non-
const parameter. There would be no way to write such a 
method in Java using hlovatt's proposal.

This one fact alone kills the proposal for me right there. 
It is quite common to want to declare some method 
parameters const while allowing others to remain non-const.


Submitted On 05-NOV-2000
pmurray
I think this is a bad idea, and a non OO way to go. Java 
already has a way to stop other classes modifying your 
class in ways you didn't expect - it's 
called &quot;encapsulation&quot;. If other classes are modifying your 
class in ways you didn't expect, you haven't coded your 
class properly. If calling a getter method makes a class 
change state, then someone is not using the &quot;get/set&quot; 
accessor method paradigm properly.

Flashy features are no substitute for good coding practise. 
I don't want to see java become a heavyweight language like 
C++, ADA and Cobol.


Submitted On 05-NOV-2000
pmurray
The other way to keep other classes from modifying your 
class is by correct use of the security mechanism. If you 
don't want someone else's method calling a method on a 
parameter you pass, then what you are looking at is a 
security issue. Yes, signing your code and putting security 
checks in place is complicated, but its more general, more 
flexible and it's already in the language. 


Submitted On 06-NOV-2000
andythomascramer
Encapsulation protects the representation of a class from 
being modified in ways not expected by the class.

However, that is not the goal of this RFE. This RFE seeks a 
means to restrict certain references to operations which 
don't change the referenced object's logical state.

For example, encapsulation protects the representation of 
subclasses of java.util.Collection. Compare that to a const-
restricted reference to an instance of a Collection; it 
could be used to call Collection.isEmpty() -- if it were 
marked const -- but not Collection.add(Object). 

This RFE seeks a simple, compile-time checked means of 
const-restricting references. Java's security mechanism is 
run-time checked, adds run-time costs, and would require 
greater development and maintenance costs. It's a worse 
hack than splitting a logical class into two physical 
classes.


Submitted On 10-NOV-2000
VWorksS
Yep, this is a good idea. Anything that emphasizes Design 
By Contract as opposed to Design By Convention or Design By 
Gambling is a good thing. 

How to implement it, however, is another issue. I don't 
think the 'const' keyword from c++ is the optimal way to 
go. 


Submitted On 19-NOV-2000
naansoft
I agree to the need of having const in as many aspects as possible. Not only will this give a better protetion 
during programming - it should also enable compilers, JVM's and gc's to do more intelligent work.


Submitted On 29-NOV-2000
hounsome
C++ style const can be added in a backward compatible way
provided only that overloading based on constness is not
allowed.
The compiler could have a flag to treat const violation as
a  warning. 
The jvm would not even know that it existed.
The reason that I would like it added is so that I can
efficiently dole out some of my class's internal data to
clients without them being able to modify it.


Submitted On 30-NOV-2000
vailant
I vote stricty against having const!
As can be learned from C++ with the late
introduction of mutable, the subject is much 
more complicated then it looks like.

Keep it Simple!


Submitted On 18-DEC-2000
pvloon
Please no const for Objects.
If an Object should not be changed, it should be reflected in its methods.
If you want two types of Objects, one that can be changed, and one that can't,
please create two classes to do this.
If you really want somebody not to change the internals of your particalur object,
give them a copy.
In C++ code I have seen, const is a mess, ending up in too much code that starts
casting const away again.
This just adds complications to Java and doesn't solve problems that can be solved right now.


Submitted On 22-DEC-2000
andythomascramer
Pvloon's comments about const objects don't apply to this 
RFE, which seeks const-restricted references, not constant 
objects. His or her comments about copying as a workaround 
ignore the significant performance hit.


Submitted On 24-DEC-2000
pillayd
Keep it simple - Java should NOT support const parameters. I like strong semantics. I have even been burnt by unintentionally modified objects. However, turning Java into Eiffel for DBC is as silly as turning it into Prolog for backward chaining. Delegation is sufficient for individual objects decide constant correctness. Java provides Exceptions for semantic infringements. Why not use them and avoid the ambiguity C++ const creates?


Submitted On 28-DEC-2000
andythomascramer
This RFE requests the addition of a simple language 
feature; this is part of the normal evolution of a 
language. It does not request that Java be turned into DBC.
Delegation increases complexity of programs; it is not the 
simple approach. Exceptions are runtime phenomena; this RFE 
seeks a compile-time verification to reduce risks.


Submitted On 10-JAN-2001
dkf
Having thought about this a bit more, I suppose you could
argue reasonably for const array references (i.e. an array
reference through which it is impossible to assign to
elements of the array) especially since there is only one
mutator for arrays (i.e. assignment - System.arraycopy can
be regarded as a wrapper round this) whose behaviour is
universally understood.

Immutability of classes/objects is much less useful,
particularly since you might have non-transient fields that
potentially need updating on every method call but which are
still not part of the ostensible state of the object (e.g.
that are used to log the number of accesses to the object.) 
The problem of constant objects is that the meaning of
constant is non-trivial, and might only apply to a
particular view of an object - it is a matter for the
class's contract (especially as it might actually depend on
the behaviour of other classes as well) and consequently for
a DBC system.  These simple language hacks are always going
to be less-than-perfect by comparison, and given the
confusion over the different interpretations of const in
this discussion and the C++ community (as well as the fact
that it is not a critical feature as it can be handled by
adequate software engineering procedures) I have to say that
Sun's position is absolutely correct.

I also dislike both hlovatt's and andythomascramer's
syntax.  Once of the most unpleasant problems with C++'s
const are the subtle differences between its meanings,
depending on exactly where in the declaration you put it,
and having a formal &quot;this&quot; parameter seems to be utterly at
odds with the language as it stands (IMHO, of course.)


Submitted On 17-JAN-2001
Ixchel
In regards to the last comment, a couple of observations:

1) C++ 'const' does not attempt to enforce immutability. It 
attempts to enforce immutability through a given reference 
to an object. This is an entirely different matter. It is 
perfectly permissible to have a const reference and a non-
const reference to the same object, and to have the non-
const reference be used to modify the object, thus changing 
the state observed by the const reference. In fact, I would 
prefer a keyword 'readonly' to be used instead of 'const' 
for this reason. It would be less prone to 
misinterpretation over its meaning.

2) Despite the fact that the above is true, constness 
(or 'readonlyness') is still quite powerful at catching 
design-time bugs at compile time. It is certainly not full 
Design By Contract, but it can be a useful component of 
such a system. Despite some of the above comments, its 
semantics can easily be made well defined: A method 
declared as 'const' may not change the observable state of 
the interface it is called on. (Note that internal caching, 
etc. may technically change the state of the object without 
actually changing the observable state of a given 
interface). Likewise, an interface reference declared 
as 'const' may not be used to do anything to modify the 
observable state of the interface it references.

Also note that a lot of the things that the 'const' keyword 
indicates must generally be specified via comments for 
languages that don't have 'const'. Since specifying these 
things in English (or whatever language) generally takes 
much more text than specifying them with a single keyword, 
and cannot be checked automatically at compile time, this 
creates more work, not less, for the software developer.

Incidentally, I would also like a 'notnull' keyword to 
create a similar compile-time check that a given reference 
cannot ever be null. C++ has this (in the form of reference 
arguments), and it is quite nice for eliminating argument 
validity checks which otherwise waste time.

Note that if the 'const' keyword existed in Java, by the 
way, that the whole concept of 'const wrappers' from the 
Java Collections Classes could be eliminated, resulting in 
an increase in runtime efficiency when using immutable 
collections.

In fact, I wonder if a similar use of the 'synchronized' 
keyword could eliminate the need for synchronization 
wrappers from the libraries as well...


Submitted On 24-JAN-2001
dkf
It is deeply unsafe to eliminate synchronized like that.


Submitted On 24-JAN-2001
dkf
The problem comes from the complexity of specifying which
methods are const-preserving, and which are not (as opposed
to which return const object references.)  Sure, you could
do it with different positions of the keyword, but that's
really going to just confuse more people than it helps.

Hmm.  If you have non-mutating methods, do you allow two
adjacent calls to the same non-mutating method to be
coalesced into a single call?


Submitted On 07-MAR-2001
tbreuel
PLEASE keep it simple. In the right language, I'm all for
immutable types.  I love functional programming.  But Java
isn't that kind of language.  Retrofitting the language, the
compilers, and the programmers would be a major
undertaking.  I think there are bigger, more pressing issues
to address than this.


Submitted On 07-MAR-2001
Ixchel
The const keyword as it is used in C++ has nothing to do 
with immutable types, nor with functional programming. It 
allows compiler-enforced read-only references to particular 
objects. This does not affect the types of those objects, 
and does not recast Java as a functional programming 
language (unless you intend to make ALL of your references 
const...)


Submitted On 20-MAR-2001
hugg
No!  Java is what it is, and what it is is not C++. 
Retrofitting the class libraries with const would break
every single program ever created.  For that matter, lets
add asserts, guard statements, theorem proving... 


Submitted On 23-MAR-2001
andythomascramer
Languages grow over time. Java is no exception. The asserts 
hugg mentions, for example, are being added in merlin (see 
bug ID 4290640).

Language features are not automatically bad merely because 
they're found in C++. For example, C++ includes 
typechecking.

As noted in a previous comment, this RFE does _not_ request 
modification of existing libraries; that's a separate issue.


Submitted On 10-APR-2001
enicholas
I'd like to add yet another request for a negative vote capability -- I do *not* want this feature added to 
the language!


Submitted On 03-MAY-2001
lukaszczyk
I do *NOT* want this feature in the language. The numerous 
arguments presented by fellow developers are proof 
that "CONST" will be inconsistently used. We have found 
that using true immutable objects (such as String) can in 
fact be used to enforce the desired behavior both at 
compile-time and at run-time. And yes, we have heard all 
the "but-copying-is-not-optimal" arguments associated with 
this philosophy by those not comfortable with immutability.
If you really care not to change an object's state, then
make the object protect itself. "Immutability by policy" is
not a safe way to design a system. When properly 
architected,a system relying on immutable entity objects 
can be made nearly as efficient as one that does not, and 
as for "maintenance" costs, it is much safer to allow those
unfamiliar with a system to add code that operates with
immutable objects than to expect them to remember to
type "const".


Submitted On 03-MAY-2001
hwc
As far as I can see, nobody is suggesting that the user of a class
needs to put 'const' anywhere.  Rather, it allows the class's author
to specify when a method might have unforseen side effects:

1) a const method does not change the state of its object;
2) a method cannot change the state of const parameters;
3) a const returned value cannot be changed by the method
that it has been returned too.

Immutable classes will often be documented as such; making
'const' part of the language lets the compiler in on the secret
so that it can better support the programmer intention.

Further restrictions may (or may not) allow optimisation.

For example: repeated calls to a const method should return the
same result if they aren't allowed to modify any class variables,
so the result needn't be re-calculated, but only when it can
be sure that the object cannot be modifed by another thread.

or: objects can be created on the stack, rather than the heap,
if they are only passed to other methods by const references,
providing that such objects cannot be assigned to instance or
class variables (they would need to be cloned)

or: const parameters cannot alias other parameters.

The point being that careful consideration of the rules the
compiler enforces can help provide slightly more efficient,
slightly better documented, slightly more reliable code.


Submitted On 05-MAY-2001
tfhudso
Interesting reading... Anyone else notice that the 
discussion about what const is has become terribly 
complicated? 

It has been argued that const could lower maintenance and 
development costs. I don't see how it can lower maintenance 
costs. Since maintenance programmers generally are not your 
crack programmers, I rather expect it would cost more for 
them to find a bug caused by lack-of-const, or to fix bugs 
they introduce because their understanding of const is 
inadequate.

Immutabilty costs copying. We build large digital signal 
processing systems in Java and have found that clone-in 
clone-out on the data costs us about 10% in speed. This is 
nothing compared to the 300% hit we take for going from C++ 
to Java. The position we have taken is that if you really 
need that 10%, upgrade your computer - hardware is cheaper 
than software. And if you really need that 300%, go back to 
C++.

The development cost increase is real. It takes time for a 
programmer to step back and think about what he's doing 
instead of just slapping out the first solution that comes 
to mind. This is money I don't mind spending on 
development. I have never had anyone offer me a way to 
reduce development costs that didn't end up costing 
exponentially more in maintenance.

Another nice thing about immutability is that it forces 
programmers to separate data and operations. It have seen 
some truly horrible objects done by amateurs that would 
represent the fundamental object along with file-io and all 
the operations they could ever think of to perform on that 
object. Using "immutable entity objects" as the core of 
what's being passed around for data, and moving every 
operation on that data (that can be) to utility classes, 
you enforce a partitioning that maintainers can handle and 
that makes the system MUCH less brittle.

In short, immutability is very easy to understand. Some 
people may not like it, but I everyone can use it reliably. 
const will be very hard to understand, even if it settles 
down to a single definition. Some will like it, most won't 
understand it, and you'll be one step further down the road 
of making Java into another C++ or Ada.


Submitted On 08-MAY-2001
andythomascramer
This RFE does not request an "immutable" qualifier for 
objects. There are no object variables in Java. This RFE 
requests a type qualifier for _references_ which restricts 
the operations which may be performed through them 
to “const” operations.

The immutable objects suggested by Lukaszczyk and tfhudso 
are sometimes an appropriate workaround for the lack of 
const-restricted references. But usually the interface-hack 
is better. Consider java.util.Vector. A reasonable 
implementation using the immutable-object approach would 
require a pair of classes, ConstVector and Vector, the 
former immutable and the latter not, a la String and 
StringBuffer. The size of the class hierarchy is doubled 
(as it would be with the interface hack as well). To pass a 
mutable vector to a method that accepted an immutable 
vector would require the _caller_ to copy the Vector to a 
ConstVector - extra code and an O(n) cost avoided with 
either const-restricted references or the interface-hack.

Lukaszczyk is concerned about maintenance 
programmers “remembering to type const.” I’m unclear in 
what exactly what situation a maintenance programmer would 
fail to “type const”, and not have it caught by the 
compiler, when they _would_ remember to work with immutable 
objects.

Tfhudso waves away the costs to performance with the 
suggestion to buy better hardware. It may be reasonable to 
accept constant-factor performance decreases in in-house 
software. It might not be for linear performance decreases 
in software developed for external clients.

Tfhudso is concerned const-restricted references will be 
too difficult for most programmers to understand. I beg to 
differ. Most programmers are acquainted with read-write 
permissions various users have with mutable files. I think 
we can just barely grasp read-write permissions various 
references have with mutable objects.

Finally, as with the interface hack, the immutable object 
approach is not usually used in real code because of the 
extra costs in development, maintenance, performance and 
understandability. The practical result is the anarchy 
approach we see in java.util.Vector.


Submitted On 12-MAY-2001
tfhudso
Have you discussed with Bill Joy the meaning of "interface 
hack"? 


Submitted On 16-MAY-2001
hlovatt
I think that the discussions in this forum have shown how
difficult it would be to introduce a const reference into
Java. Therefore I would like to vote against it. The only
issues that have often arose from the 'pro const camp' are 
performance, arrays, and typing. Consider the example below.

class IntArray extends ReadOnlyIntArray {
    public IntArray(int size) {super(size);}
    public final void set(int index, int value) {array
[index] = value;}
}
public class ReadOnlyIntArray {
    protected int[] array;
    public ReadOnlyIntArray(int size) {array = new int
[size];}
    public final int get(int index) {return array[index];}
    public final int length() {return array.length;}
    // Test performance
    private static int value;
    private static long time;
    private static void inBuilt(int length) {
        long start = System.currentTimeMillis();
        int[] array = new int[length];
        for (int i = 0; i < length; i++) array[i] = i;
        value = 0;
        for (int i = 0; i < length; i++) value += array[i];
        time = System.currentTimeMillis() - start;
    }
    private static void readOnly(int length) {
        long start = System.currentTimeMillis();
        IntArray array = new IntArray(length);
        for (int i = 0; i < length; i++) array.set(i, i);
        value = 0;
        ReadOnlyIntArray rOArray = array;
        for (int i = 0; i < length; i++) value += 
rOArray.get(i);
        time = System.currentTimeMillis() - start;
    }
    public static void main (String args[]) {
        final int length = 1000000;
        inBuilt(length);
        System.out.println("In-built test 1: value = " +
        value + " time = " + time);
        inBuilt(length);
        System.out.println("In-built test 2: value = " +
        value + " time = " + time);
        readOnly(length);
        System.out.println("Read-only test 1: value = " +
        value + " time = " + time);
        readOnly(length);
        System.out.println("Read-only test 2: value = " +
        value + " time = " + time);
    }
}

When run using the IBM JVM 1.3 on my PC I get:

In-built test 1: value = 1783293664 time = 80
In-built test 2: value = 1783293664 time = 61
Read-only test 1: value = 1783293664 time = 70
Read-only test 2: value = 1783293664 time = 60

Therefore performance is not an issue. The example shows
read-only arrays, therefore these are not an issue. As for
typing even such a contrived and small example as this 
required little extra typing. Object versions of arrays
could be added to java.util.Array and other libraries
expanded to use them. Surely this shows that const isn't
worth adding!


Submitted On 17-MAY-2001
Ixchel
Sigh. Hlovatt, I have to say, that if you really think that 
the example that you have given demonstrates that const is 
not worthwhile, you really don't understand it.

The major issues to do with const are architectural issues, 
not performance issues. In many cases, usage of const can 
cut the number of classes and interfaces that need to be 
written for a large library in half, or better. 
Furthermore, it prevents lots and lots of bugs.

I have used the "const interface" hack. I have used 
constness decorators (like the Java collections). I have 
used a variety of other ways to get around the fact that 
Java doesn't have const. And, frankly, in many cases, they 
suck. They don't work well when you try to apply them to a 
large tree of interrelated classes and interfaces. They 
introduce a huge amount of complexity into programs, they 
slow programs down, and they often create huge typing 
messes (of weirdly interconnected interfaces, with every 
one having to have a const and a non-const version) that 
can't be resolved in any reasonable fashion. These 
workarounds work OK for trivial examples, but they simply 
don't scale well for large projects.

I've used const with C++ for many years, and it is by far 
preferable to these kinds of problems. It's not hard to 
understand -- it can be explained to someone in five 
minutes. And it works.

Most of the opposition I'm seeing from the people here 
against const seems to come from people who don't really 
understand how it's used and what it's for, and what the 
large-scale architectural impact of it (or of not having 
it) is.

For example, try passing one of your "read-only arrays" to 
a method that someone else wrote which takes a 
java.lang.Object [] which it doesn't modify. What will you 
do if you need to deal with a library which you don't have 
source for? Etcetera. In the real world, rewriting every 
class you need to have a const interface for just isn't 
practical, and won't work. Only if we agree on how const 
will be implemented can code interoperate. And only by 
having it as part of the language can we const-restrict ALL 
types in the language without having to implement lots and 
lots of scaffolding code just to achieve basic data safety.



Submitted On 20-MAY-2001
hlovatt
Ixchel, thank you for your comments. I would like to take 
your example of passing a 'const' array  to an existing 
function that does not declare its argument 'const'. For 
example 'static int f(int[] array)', using a C++ 
like 'const' notation you would write:

const int[] array = {1, 2, 3};
int result = SomeClass.f( (const_cast)array );

Note that you need to cast away the 'const' because you 
can't, in your example, re-write the function 'f' and it 
doesn't accept a 'const' array. Even though we know 
that 'f' doesn't change the array, the problem is that the 
compiler thinks it does because the array is not 
declared 'const'.

In my case I would write:

ConstIntArray array = new ConstIntArray( {1, 2, 3} );
int result = SomeClass.f( array.constCast() );

Note in the first line above I have taken the liberty of 
using one of the new Java 1.4 initialisers. The 
method 'constCast()' returns the underlying primitive array.

For both your method and my method there is a problem if we 
are wrong about 'f' and it changes the array. This is the 
same as C++ where the results are implementation dependent 
if a 'const' is changed.

If you can re-write the function 'f', then in both cases 
the call becomes:

int result = SomeClass.f(array);

As you can see there is virtually no difference between the 
two methods in either case (able to re-write 'f' or 
not).    

There is a very good discussion on 'const' in: Stroustrup, 
The Design and Evolution of C++, sections 13.3 and 14.3.4. 
If you follow the discussion given by Stroustrup you will 
see that in addition to requiring 'const' and 'const_cast' 
you will probably also want 'mutable'. The introduction of 
all these key words is avoided by using the design pattern 
suggested by myself and others. What is more, this design 
pattern is already in use and the convenience the key words 
add is minimal. Note that the key words do not add any 
functionality.


Submitted On 22-MAY-2001
vor23
It is a shame that this RFE mentioned C++, because what this
RFE
calls for is much simpler than the mess that const is in
C++.  It seems
to me that the request calls for the following only:

1.  If an object A contains a method declared const, then
that method
cannot assign to any field in A, nor can it call any
non-const method
in A, nor can it pass A to any method that does not take A
as a
const parameter.
2.  A method that takes a const parameter B cannot assign to
any
field in B, nor can it call any non-const methods in B, nor
can it
pass B to any method that does not take B as a const
parameter.

That is it.  In this form, I fully support this RFE.


Submitted On 25-MAY-2001
andythomascramer
Vor23 has stated this RFE succinctly. He doesn’t include 
mutable members -- and they’re not required, since any 
logically mutable members can be implemented through 
references to component objects. I myself, however, would 
like to see const-restricted references to Java’s object-
like arrays included as part of the RFE; it would be highly 
valuable, and the rules are as simple as those for const-
restricted references to objects.

Hlovatt’s suggestion for API-based emulation of const-
restricted arrays has several flaws, including but not 
limited to the following:

First, Hlovatt’s array class doesn’t support the common 
array indexing operator [ ], since Java doesn’t support 
operator overloading. Consequently, it’s less friendly to 
those of us who use arrays frequently in complex 
expressions.

Second, it doesn’t support multidimensional arrays. This 
could be solved by adding methods within Hlovatt’s IntArray 
class, or introducing new classes such as IntArray2 and 
IntArray3 for each number of dimensions. The former is more 
friendly but may suffer additional performance costs (the 
cheapest representation in space and time would be a single 
Object reference, and all methods would downcast it as 
appropriate). The latter introduces new class library 
complexity. Both limit the number of dimensions supported 
by an IntArray.

Third, either language supported arrays would continue to 
be used or not. If they were, then conversion costs would 
be encountered between language-supported arrays and API-
based arrays. If they were not, then current array syntax 
could be redirected to refer to the API-based arrays -- 
which would require a syntatic const qualifier on arrays.

Fourth, it requires at least 18 classes to implement -- a 
pair of read/write classes for arrays of each primitive 
type, and a pair of read/write classes for arrays of the 
Object type. Until generics are introduced in 1.5, 
downcasts are necessary from accessors provided by the 
Object array class.

We know the language _allows_ use of const-restricted 
constructs. This RFE requests _support_ for const-
restricted constructs.



Submitted On 30-MAY-2001
hlovatt
It is suggested that API arrays don’t support multi-
dimensional arrays. This isn't true, you can take an 
IntArray 
and put it into an ObjectArray - this is close to what 
happens with built in arrays like int[][]. When we get 
generics (version 1.5?), you will be able to write:

ObjectArray<IntArray> a;
...
result = a.get(i).get(j);

This is very similar to the current multi-dimensional 
arrays. 

However the current multi-dimensional arrays and putting 
arrays into an ObjectArray are not what you ideally want 
from 
a performance point of view because both techniques 
introduce 
an extra indirection, cause unnecessary bound checking, and 
split the array into different areas of the heap. There is 
already a package that as part of the 3D Graphics API 
called 
java.vecmath that has two API based arrays GVector (1 D) 
and 
GMatrix (2 D), these were introduced for performance 
reasons. 
There is also an approved extension proposal for API based 
multi-dimensional arrays JSR-000083, again primarily 
proposed 
for performance reasons. The existing package and the 
proposed package both store multi-dimensional arrays as a 
single dimension array to overcome the performance problems 
with the current built-in arrays.

Moving onto syntax, it is true that without operator 
overloading that [] is substituted for get or set and that 
this is not ideal. It should be born in mind that we 
already 
use set and get like syntax with the Collections API, 
StringBuffer, GVector, and GMatrix, to name a few, and it 
isn't too bad. Also other features are better syntactically 
with an array based API, for example:

Currently: Arrays.sort(a)
API: a.sort()

The whole of the Arrays API could be replaced resulting in 
better syntax, same goes for common matrix type operations 
like a.mult(b) and sub arrays, a.sub(1,2). You can also 
provide iterators for API arrays to syntactically unify 
their 
use with the Collections API, e.g.:

int sum = 0;
for (IntIterator i = a.iterator(); i.hasNext(); )
    sum += i.next();

Thus API syntax is not only better than the in-built syntax 
in many circumstances, it is also more like everyone is 
used 
to with other commonly used classes like StringBuffer and 
Collections.

What I suggest is that instead of asking for const we 
canvas 
for operator overloading and ask the people who are 
currently 
implementing JSR-000083 API arrays to add read-only. I have 
sent an email to jsr-083-comments@sun.com saying great work 
what about read-only arrays, if others do like wise then 
maybe we will have const arrays sooner rather than latter. 
If 
the API arrays become successful then the in-built arrays 
could be depreciated, which would be a nice simplification 
to 
Java (less is more!).


Submitted On 03-JUN-2001
eckely
Const methods are of paramount importance for J2EE EJB 
programming. Designating a method as const will 
allow “smart” persistence. That is, if only const methods 
have been called on a bean during a transaction, the 
container may decide not to store this bean into database 
(as the bean’s state never changed). Because of this major 
optimization, vendors of application servers (specifically 
WebSphere and WebLogic) already provide proprietary means 
for such read-only designation of bean’s remote methods. 
The problem with that (besides the lack of standardization) 
is the lack of compile-time checking, causing error-prone 
hard-to-debug code. This, plus design help provided by the 
const correctness is more than enough to consider this 
feature seriously.

Jacob Eckel <eckel@dealfusion.com>


Submitted On 03-JUN-2001
mlaiosa
I would like to refute that the complexity of const-ness in 
C++ would be carried into Java by this RFE (or anything 
else that adds C++’s notion of const to Java)

This is what I understand to be complex about C++’s const.  
If there is a complexity to that I am missing here, please 
tell me about it.

class A { … };

//ex 1
const A* i; //A pointer to an A that wont let you change 
the A object
A* const i; // A pointer to an A that cannot be made to 
point to something else (like final)
const A* const i; //A pointer to an A that cannot itself 
change, nor can it be used to change the A

//ex 2
const A ** const * i;
//This is confusing.  It is a pointer to a pointer to a 
pointer to an A; which may not be used to modify the A, nor 
may it be used to modify what is produced by the expression 
*i.

1: If the final keyword were used as the qualifier proposed 
by this RFE, then this confusion would likely still exist. 
For this reason, I am in favor of a different keyword.

2: This would not exist in Java, because you cannot have a 
reference to a reference, let alone something as bothersome 
as this triple pointer.  Java avoids this complexity by 
avoiding references to references, adding const-ness will 
not bring it back.


Submitted On 05-JUN-2001
hlovatt
I think there is a tendency to understate the difficulty of 
the problem of adding const to Java and for that matter, to 
assume that C++ did everything wrong. I think that C++ 
probably got as good a concept of const as you are likely 
to get (note I am taking const to be different to 
immutable, as this RFE does) in a language where it is 
added on after basic mutable types are established. This 
understatement of the difficulties of adding const, 
although not deliberate, trivializes the debate to the 
level of ''it's so easy why haven't we done this already''. 
I would like to point out why it is much harder.

Vor23 stated a set of rules but neglected arrays (this has 
already been pointed out), generics, fields, locals, and 
casting away const. The proposal won't fly unless you can 
address these points! I will address all these points below.

For example it has been stated that casting away const 
isn't necessary (andythomascramer), if you can't cast away 
const then you can't use any existing API because they 
don't declare their argument const. This would seem to be a 
major problem! Also functions that accept const arguments 
often return const values and there is then the need to 
cast back to a mutable type. EG to increment the maximum of 
two Objects (e.g. arrays), the max function would accept 
constants (it doesn't change anything) and therefore return 
a constant. Thus you need something like:

int[] a, b;  // Note - not const
...
result = ( (const_cast) max(a, b) ).inc();

Once you can cast away const, then you can get bugs where a 
supposedly const object is changed by mistake.

Another misconception is that Java doesn't have pointers to 
pointers (mlaiosa). However you can have a pointer inside 
an object that is pointed to! For example multi-dimensional 
arrays.  You also need arrays, generics, fields, and 
locals. So we would require declarations something like:

final Object final o;
final int[] final ia;
final int[] final [] final iaa;
final Array<final Object final> goa;    // Generics
final Array< final Array<final Object final> > goaa;

Just as bad as C++! You could make const mean every stage 
of the declaration is final, so that the above declarations 
become:

const Object o;
const int[] ia;
const int[][] iaa;
const Array<Object> goa;
const Array< Array<Object> > goaa;

This would probably be OK since the finer control of 
exactly which reference and which object is final (const) 
is rarely needed. I am suggesting that final is not 
changed, so the first example would remain illegal, and 
that const is introduced in addition to final with the 
meaning implied by the second example. However you can 
almost get as good a syntax using wrappers, as shown in 
previous postings. So it begs the question, ''why bother 
changing the language?''

Eckely has said that there are already products out there 
that in a proprietary way declare a limited form of const. 
I would suggest that what ever technique they use, I am not 
familiar with the products, that it isn't very safe because 
of the need to cast away const (in some form or other). The 
only suggestion I have seen that seems practical, to allow 
performance optimisations, is the immutable proposal of 
James Gosling (http://java.sun.com/people/jag/FP.html). I 
would suggest that if this type of optimisation is what you 
want, then this is not the RFE for you!

I think most people are sympathetic to the idea of 
declaring something constant both from a class design point 
of view and from a performance point of view. The problem 
is, how to do it in Java in a way that adds sufficient 
benefit for all the trouble it will be to add. Particularly 
when wrappers provide much the same functionality already.


Submitted On 07-JUN-2001
hwc
Please no casting away const; it makes the whole thing unsafe.  It may seem useful
to be able to use existing class libraries but if you could always rely on other people's
code doing what they say it should, there would would be much less need to introduce
'const' in the first place.

I would expect add( const Object a, const Object b )  to return a new Object.  By
analogy, I wouldn't be surprised if max( const Object a, const Object b ) returned a
clone of the larger object.

Another question, though: this RFE asks for const references and const methods;
isn't an immutable object just an extension of the same idea?  Constructors could
(implicitly) return const references and all its methods would be const.

It's not something I've tried, but couldn't APIs be retrofitted with 'const' 
parameters, much as is being suggested for collections in the generics
proposal?  String, Float etc. immediately spring to mind.  Later 
compilers can then make a much better job of simple statements such as

String s  = ….
Float x = (new Float( s ).floatValue();


Submitted On 09-JUN-2001
cowwoc
One thing that needs to be pointed out: 'const' in C++ isn't _really_ constant. You can easily cast a const 
object to a non-const equivilent therefore 'const' provides no protection what-so-ever. If you do add 'const' to 
the language, then make sure you plan ahead so that there is no need for const-casting an object to 
remove/add a const modifier to it.


Submitted On 18-JUN-2001
sci-agn
This whole RFE is a ridiculous idea.  If you want constant
primitives and constant Object references, declare them
final.  If you want the objects' fields to be constant, use
the existing modifiers and deny direct access to the fields.
 I don't see what is so hard about this.

This is a design issue more than it is a syntax issue, as
correctly mentioned in the official evaluation.  I
understand that this RFE was lodged with good intentions,
but what it requests is already possible.  If Sun never
implement this, it won't hurt the decent programmers out
there - it isn't their fault that people are generating a
"body of const-incorrect legacy code" (andythomascramer).

Regards,
Aaron Nielsen
roesti@f2s.com


Submitted On 19-JUN-2001
hlovatt
Consider the following code which implements the 'real life'
example given by andythomascramer in three different ways,
firstly as given in this forum, then using an array (API)
wrapper, and finally using vecmath like classes. This is an
ironic example to give in this forum, since the supposed
'good'  implementation in terms of speed and least code
using the built-in arrays is in fact the slowest and second
longest!

public final class TwoD {
    // Common
    static final int testTimes = 5, loopTimes = 1000000;
    static long start, finish;
    static double result;
    static final double ptx = 1, pty = 2, ptz = 3;
    static void print(String s) { System.out.println(s +
      ": " + (finish - start) + " ms - result = " + result); }
    // Built-in Array
    static final double[][] mb = { {1, 2, 3, 4},
                                   {5, 6, 7, 8},
                                   {9, 10, 11, 12},
                                   {13, 14, 15, 16} };
    static double builtIn() {
        double sum = 0;
        for (int loop = 0; loop < loopTimes; loop++) {
            double rvx = (mb[0][0] * ptx) +
           (mb[0][1] * pty) + (mb[0][2] * ptz) + (mb[0][3]);
            double rvy = (mb[1][0] * ptx) +
           (mb[1][1] * pty) + (mb[1][2] * ptz) + (mb[1][3]);
            double rvz = (mb[2][0] * ptx) +
           (mb[2][1] * pty) + (mb[2][2] * ptz) + (mb[2][3]);
            double w   = (mb[3][0] * ptx) +
           (mb[3][1] * pty) + (mb[3][2] * ptz) + (mb[3][3]);
            sum += rvx + rvy + rvz + w;
        }
        return sum;
    }
    // API Array
    static final class API {
        static final double[] m = {1, 2, 3, 4, 5, 6, 7, 8,
                           9, 10, 11, 12, 13, 14, 15, 16};
        double get(final int row, final int col)
                              { return m[row * 4 + col]; }
    }
    static final API ma = new API();
    static double api() {
        double sum = 0;
        for (int loop = 0; loop < loopTimes; loop++) {
            double rvx = (ma.get(0,0) * ptx) +
   (ma.get(0,1)* pty) + (ma.get(0,2) * ptz) + (ma.get(0,3));
            double rvy = (ma.get(1,0) * ptx) +
  (ma.get(1,1) * pty) + (ma.get(1,2) * ptz) + (ma.get(1,3));
            double rvz = (ma.get(2,0) * ptx) +
  (ma.get(2,1) * pty) + (ma.get(2,2) * ptz) + (ma.get(2,3));
            double w   = (ma.get(3,0) * ptx) +
  (ma.get(3,1) * pty) + (ma.get(3,2) * ptz) + (ma.get(3,3));
            sum += rvx + rvy + rvz + w;
        }
        return sum;
    }


Submitted On 19-JUN-2001
hlovatt
Continued ...
    // vecmath
    static final class Vector4d {
        double x, y, z, w;
        Vector4d() { }
        Vector4d(double x, double y, double z, double w) {
            this.x = x;
            this.y = y;
            this.z = z;
            this.w = w;
        }
        double sum() { return x + y + z + w; }
    }
    static final class Matrix4d {
        final double m00 = 1, m01 = 2, m02 = 3, m03 = 4;
        final double m10 = 5, m11 = 6, m12 = 7, m13 = 8;
        final double m20 = 9, m21 = 10, m22 = 11, m23 = 12;
        final double m30 = 13, m31 = 14, m32 = 15, m33 = 16;
        void transform(Vector4d vec, Vector4d vecOut) {
            vecOut.x = (m00 * vec.x) + (m01 * vec.y) +
                       (m02 * vec.z) + (m03);
            vecOut.y = (m10 * vec.x) + (m11 * vec.y) +
                       (m12 * vec.z) + (m13);
            vecOut.z = (m20 * vec.x) + (m21 * vec.y) +
                       (m22 * vec.z) + (m23);
            vecOut.w = (m30 * vec.x) + (m31 * vec.y) +
                       (m32 * vec.z) + (m33);
        }
    }
    static final Vector4d rv = new Vector4d(),
           pt = new Vector4d(ptx, pty, ptz, 0);
    static final Matrix4d mf = new Matrix4d();
    static double vecmath() {
        double sum = 0;
        for (int loop = 0; loop < loopTimes; loop++) {
            mf.transform(pt, rv);
            sum += rv.sum();
        }
        return sum;
    }
    // Test
    public static void main(String args[]) {
        for (int test = 0; test < testTimes; test++) {
            start = System.currentTimeMillis();
            result = builtIn();
            finish = System.currentTimeMillis();
            print("Built-in");
            start = System.currentTimeMillis();
            result = api();
            finish = System.currentTimeMillis();
            print("API     ");
            start = System.currentTimeMillis();
            result = vecmath();
            finish = System.currentTimeMillis();
            print("vecmath ");
        }
    }
}

When run on my PC using the IBM 1.3 JVM it gives:

Built-in: 100 ms - result = 2.4E8
API     : 150 ms - result = 2.4E8
vecmath : 110 ms - result = 2.4E8
Built-in: 161 ms - result = 2.4E8
API     : 80 ms - result = 2.4E8
vecmath : 100 ms - result = 2.4E8
Built-in: 160 ms - result = 2.4E8
API     : 80 ms - result = 2.4E8
vecmath : 100 ms - result = 2.4E8
Built-in: 161 ms - result = 2.4E8
API     : 80 ms - result = 2.4E8
vecmath : 100 ms - result = 2.4E8
Built-in: 170 ms - result = 2.4E8
API     : 80 ms - result = 2.4E8
vecmath : 100 ms - result = 2.4E8

As you can see wrapping the built-in arrays in a 2D API
speeds things up by about a factor of 2. The vecmath
definitions are taken from the Java3D API v1.3, therefore if
vecmath is used you would not need to write the classes
Vector4d or Matrix4d (making this version the shortest and
easiest to understand). The vecmath version is also
considerably quicker than using built in arrays but not
quite as quick as the array API (but the vecmath method is
the most realistic since it calls methods to do the
multiplication and summing). Note vecmath supports byte,
int, float, and double for small vectors and matrices (but
only double for large ones) and provides many common
operations as methods.

In conclusion, it is a fallacy to suggest that the built-in
arrays should be considered the 'best' method of coding many
problems and therefore do not provide 'good' evidence as to
why 'const' should be added to the language.


Submitted On 19-JUN-2001
andythomascramer
Cowwoc's claim that casting-away const eliminates any protection offered by const-restriction is not 
correct. Though the existence of const in C++ does not protect against _mischief_, it still protects against 
_accidents_. 


Submitted On 19-JUN-2001
andythomascramer
If primitive arrays were deprecated, as hlovatt suggests, how would the API-based arrays be implemented? 
Surely not with JNI, if they're intended to be efficient in time. How would arrays of higher-dimensionality 
than supported by the API be implemented efficiently by programmers outside of Sun? 

Let's move on to the strawman of casting-away-const. Hlovatt claims it's necessary for const-restricted 
references, but can lead to bugs, and that therefore const-restricted references are unsafe.. 

I see nowhere that I've claimed casting-away-const is not necessary, but no matter -- I agree that it's not 
necessary. Hlovatt claims it's necessary, but shows only that it would be useful with pre-const libraries. 
"Useful" is not "necessary." Commercial Java libraries would likely be updated over time to include 
const-correct interfaces; in the meantime, const-restricted references would still be useful for 
application-specific code.

Hlovatt claims that casting-away const could lead to bugs, where something is modified unexpectedly. 
That's true -- but casting-away const already exists in the current language, implicitly with references 
intended to be const-restricted. Even the interface hack suggested by some as an emulation (i.e., doubling 
the size of the class hierarchy with the addition of read/write variants of each class) currently allows 
casting-away const explicitly. If hlovatt is concerned about casting-away-const, then this proposal would 
help, either by not allowing such casts, or by introducing an explicit syntatic salt that can highlight the 
danger. 

Thus, hlovatt's strawman fails on both assertions. First, casting-away-const is not necessary for this RFE. 
Second,.even if it were provided, it doesn't introduce any bugs that can't already exist in current Java -- in 
fact, it would reduce the likelihood of such bugs by requiring explicit casts at compile-time.

However, this RFE does not request the ability to cast-away const. Whether it should or should not be 
included is left to the language designers. I am not advocating its inclusion or exclusion.


Submitted On 19-JUN-2001
andythomascramer
Sci-agn's dismissal of this RFE relies on the misunderstanding that this RFE requests a qualifier for immutable 
objects. It does not. This RFE requests a type qualifier for _references_ which restricts the operations 
which may be performed through them to "const" operations. 


Submitted On 19-JUN-2001
andythomascramer
Apparently, for hlovatt, more is less. 

To avoid a const-restricted qualifier to array references, he suggests the introduction of API-based arrays 
consisting of two classes (read and write) per primitive type per number of dimensions. Fortran77 supported 
seven dimensions on arrays, but I could get by myself with four (consider a variable across three spatial 
dimensions and time, for example). Let's provide Java with less functionality than Fortran 77 - only four 
dimensions. Let's also presume only rectangular arrays are provided in the standard API. That's 2 * 8 * 4 = 
64 classes. Oh, yeah, let's increase Java's memory footprint even more!

The JSR 000083 hlovatt cites is for the implementation of rectangular multidimensional arrays. The 
performance benefit hlovatt cited is derived from the rectangular constraint, not the choice of basing it in 
the API rather than the language. The same benefit would be obtained from a language-based approach.

The vecmath classes hlovatt cites are not general arrays, they are mathematical vectors and matrices. In 
addition, they support only values of type double. I see no indication that they were preferred for 
"performance reasons" over language-based arrays, but rather that they're the natural OO classes to 
represent mathematical vectors and 2D rectangular matrices, which might be represented internally partly 
by arrays -- language-based arrays. I happen to use Java3D myself, which depends on the vecmath library. 
Performance is critical in Java3D, and most of Java3D uses primarily language-based arrays to represent 
arrays.

Hlovatt suggests using "get" and "set" are acceptable alternatives to using the natural "[ ]" operator. My 
experience as a former CS instructor has been that students would find the latter easier to understand. And 
it's more readable as well. Here's part of the code I wrote to multiply a 3D point by a 4x4 transformation 
matrix. The language-based version allows a readable, tabular format on 80-character lines. (Each 
statement below appears on a single, separate line in the source.)
  rv.x = (m[0][0] * pt.x) + (m[0][1] * pt.y) + (m[0][2] * pt.z) + (m[0][3]);
  rv.y = (m[1][0] * pt.x) + (m[1][1] * pt.y) + (m[1][2] * pt.z) + (m[1][3]);
  rv.z = (m[2][0] * pt.x) + (m[2][1] * pt.y) + (m[2][2] * pt.z) + (m[2][3]);
  w    = (m[3][0] * pt.x) + (m[3][1] * pt.y) + (m[3][2] * pt.z) + (m[3][3]);

Here's the API-based version, presuming the existence of a 2D array class for the array member type.
  rv.x = (m.get(0,0) * pt.x) + (m.get(0,1) * pt.y) 
    + (m.get(0,2) * pt.z) + (m.get(0,3));

  rv.y = (m.get(1,0) * pt.x) + (m.get(1,1) * pt.y) 
    + (m.get(1,2) * pt.z) + (m.get(1,3));
  
  rv.z = (m.get(2,0) * pt.x) + (m.get(2,1) * pt.y) 
    + (m.get(2,2) * pt.z) + (m.get(2,3));

  w = (m.get(3,0) * pt.x) + (m.get(3,1) * pt.y) 
    + (m.get(3,2) * pt.z) + (m.get(3,3));

(continued ...)


Submitted On 28-JUN-2001
andythomascramer
My example was provided only to show the greater 
readability provided by the common array access operator [] 
over .get() methods. 

It's obvious that rectangular arrays and hand-coded 4D 
matrices will be faster than the current general-purpose 
non-rectangular arrays. However, this has no relevance to 
the readability issue. Further, I see no relevance to this 
RFE. I will reply only to substantive remarks that have 
relevance to this RFE.


Submitted On 03-JUL-2001
tbreuel
On the question of "const" methods and caching, you cannot,
in C++, assume that just because only "const" methods have
been called, the object has not been modified, even in the
absence of casts.  The object's constructor may have leaked
a non-const reference to the object that is merrily being
used to modify the object behind your back.

The safe way of implementing these kinds of features is via
a "modified" flag.  That flag can be implemented more
conveniently using something like AspectJ.



Submitted On 24-JUL-2001
thomas.sievers@gmx.de
Up to now, there's only the possibility to prevent a 
parameter given to a method from being assigned to a new 
reference by doing the following:

public SomeClass doSomething (final AnotherClass c)

But this is simply insufficient for reference types, as 
they can be changed using setter methods.


Submitted On 05-AUG-2001
jdcjdc
Ugh! 'const' artificially creates two types from a given class: a mutable type
and an immutable type. The mutable object can passed as an argument to
any method, but the const (immutable) object cannot be passed as an
argument for mutable args.

Please don't import C++ warts into Java. Use something better like
'design-by-contract' instead of const.


Submitted On 10-AUG-2001
dnoyeB
Help me understand why this is necessary?  If you don't 
wan't your object modified, pass an interface which your 
object implements.  That interface should only contain 
your 'const' methods.

Or
Make your methods package methods.

package xyz;
void doThis(){}

That method can only be called from within the package.  I 
take this to be an excellent solution.  I cant think of a 
reason for more, though there may be one.  Please let me 
know!


Submitted On 14-AUG-2001
nerd2004
Imho, C++-style const would add unnecessary bloat to the 
language.  However, I wouldn't mind a "const class" 
construct which prevents a class from including any methods 
that change its state.  (Constructors are an exception, of 
course.)


Submitted On 28-AUG-2001
finking
One of my few gripes with java is the lack of support for
constancy. Anybody who has got into using constancy in other
languages will know how much time it can save when the
compiler picks bugs up for you instead of you having to find
them yourself. In Java however compiler support for
constancy only works for primitive types:
 
    final int i = 9;
 
i can never be changed it will always be 9 - if you try to
change it the compiler will compain....  but 
 
    final Thang thang = new Thang(parameters);
 
thang can be changed (assuming ObjectThang has modifiers).
The only thing the final keyword buys here is that
identifier thang will never be used to refer to a different
object, it does not stop us from changing thang.
 
The standard solution to this problem is to make "immutable"
classes i.e. classes which have no modifier methods. This in
itself is not enough however. It means that every instance
of the class is either constant or non constant. The
programmer has no way of declaring a constant object if the
class definiing it is not immutable.
 
What is needed is a scheme which allows objects to be
declared final in the same way that instances of primitive
types are. That is:
an object of a mutable class can be declared as final or not
depending on whether it should be constant or not
respectively. 
methods should be able to declare an object parameter as
final or not depending on whether or not the method modifies
that object 
methods that have a final object parameter should be able to
take either a final object or a nonfinal object as input
parameters
I addition, because we're dealing with objects we need the
following to be true:
subclasses must have the same properties as the parents and
be able to inherit form parents in the normal way.
The key point here is that we need the compiler to enforce
these rules. The whole point of using constancy is to get
the compiler to do some of the debugging for you.
 
The Solution
 
The simple solution to this is as follows: for every class
you write/have written, declare an interface called
YourClass_final. In this interface declare all the class's
non modifier methods. Then have YourClass implement
YourClass_final. That's all there is to it. Now if you (or
anybody else) wants to declare a constant instance of
YourClass they do:
 
    YourClass_final  myClass = new YourClass();
 
If they want to declare a constant parameter to a method,
they do:
 
    public void foo(YourClass_final  yc)
 
It really is that simple! It doesn't get any more
complicated when you add in inheritence either. Lets say you
have a subclass of YourClass called ChildClass. All you do
here is create a new interface ChildClass_final as before -
this class contains all the methods of ChildClass except for
the modifiers. The only extra thing you have to do is make
ChildClass_final extend YourClass_final. Now you can do
things like:
 
    ChildClass_final  myChild = new ChildClass();
    ChildClass  myOtherChild = new ChildClass();
 
    myChild.foo(myOtherChild);
 
Simple!


Submitted On 28-AUG-2001
Ixchel
Oops. That example should read:

    void foo(const Thing x) {
         int y = x.getFoo(); // OK
         x.setFoo(y); // Compiler error
    }

Presumably, it uses a definition of Thing something like:

     interface Thing {
           int getFoo() const; // Can be called for both 
const and non-const 'Thing' references
           void setFoo(int x); // Can be called only for 
non-const 'Thing' references.
    }


Submitted On 28-AUG-2001
Ixchel
I agree that immutable classes are great, and solve many 
problems. However, they are not what this RFE is about. 
This RFE is about immutable-restricted REFERENCES to 
classes. If someone wants to start a new RFE relating to 
how to add immutable classes to Java, they are free to do 
so, and could even post a link to it here so that others 
can find it. I know that James Gosling has written some 
papers in support of the idea, and has suggested them as a 
possible solution to the "Java has no enumerated types" RFE 
that is also active. But this RFE is not about that 
subject. The use of the 'const' keyword (in C++) that this 
RFE describes has nothing to do with guaranteeing 
immutability of objects. It is about restricting the 
operations that may be performed via a particular REFERENCE 
to an object. That is an ENTIRELY DIFFERENT MATTER.

Sigh. I am quite concerned that the original intent of this 
RFE will be lost amidst the noise of the various people in 
this discussion who really don't understand it and are 
posting irrelevant comments, raising irrelevant objections, 
and describing irrelevant solutions based on a 
misunderstanding of what is being suggested. I wonder how 
many people posting here have actually worked on a project 
that consistently USED const in C++. A little experience 
often overthrows a lot of theory.

Also, keep in mind that the 'const' keyword in C++ serves 
TWO DISTINCT PURPOSES, only one of which is being discussed 
by this RFE. One use of 'const' is already handled by 
Java's 'final' keyword: Namely, that of ensuring that a 
particular object reference (or primitive variable) may not 
be changed to point to a new object (or value). This RFE is 
about the OTHER use of const, which restricts the 
operations that may be performed via a particular object 
reference. In other words, we are talking about:

<pre>
    void foo(const x) {
         int y = x.getFoo(); // OK
         x.setFoo(y); // Compiler error
    }
</pre>

and we are NOT talking about:

<pre>
    const Thing foo = new Thing();
    foo = new Thing(); // Compiler error: reference 'foo' 
can't be retargeted.
</pre>

since the above is already handled by use of the 'final' 
keyword.



Submitted On 28-AUG-2001
finking
Workaround

This problem has come up at our site. I posted a couple of
short articles about it on our site Java BB. The technique I
outline requires no change to the Java language syntax, but
does require the creation of new interfaces for existing
classes. This can be semi-automated. Ultimately to effect a
full solution using this technique, every class would need a
corresponding interface creating (see following posts),
which would require (backwards compatible) changes to all
classes from java.lang.Object downwards.
   Finally the second part of the post goes on to describe a
stronger kind of constness (immutability), which is the kind
of const you get in Ada. This is implemented using a similar
technique.

Regards

Robert Finking


Submitted On 28-AUG-2001
finking
One of the main benefits of immutable classes is that you
know an object of an immutable class is guaranteed never to
be changed by anybody. A classic bug is as follows:
 
class Bar
{
    final Object object;
    final YourChild_final yourChild;
 
    public Bar(final Object newObject, final YourChild_final
newYourChild)
    {
        this.object = newObject;
        this.yourChild = newYourChild;
    }
 
    ....
    // Methods, which rely on object and yourChild not
changing
}
 
The class relies on the objects passed in to the constructor
being constant. It would appear from the definitions that
the objects can't change. However there is nothing to stop
the Bar class being used as follows:
 
    Object black = new AnimalColour();
    YourChild sheep = new YourChild();
    Bar bar = new Bar(black, sheep);
 
    Bar.method();
    black.setFlashing(true);
    Bar.method();
    sheep.addLeg();
    Bar.method();
 
Clearly this is not what the author of the Bar class
intended. What is needed to prevent this kind of bug (which
happens all too easily and can be very difficult to track
down) is a stronger form of constancy - immutability. 
Immutability allows a method not just to state that it will
never change the parameters passed to it (which is what the
_final classes achieve), but to require that the object
passed to it is totally immutable. The only way to achieve
this at present is by having objects of an immutable class.
There is currently no way to take an object of a mutable
class and declare an immutable object of that class.
 
The Solution
 
The solution to this problem is a simple extension of the
scheme I outlined previously. The essential properties that
are needed are:
A way to declare immutable instances of mutable classes 
Compile time checking that a method that accepts an
immutable object has not been passed a mutable one 
Validity of either a mutable or immutable object to be
passed to a _final parameter
Again, the solution is very simple, create a new class
YourClass_immutable, which implements YourClass_final. The
YourClass_immutable class implements all the methods in the
YourClass_final interface, no more, no less. The
implementation is trivial: YourClass_immutable contains a
single instance of YourClass and does a simple call through
to that for each method, so we have:
 
class YourClass_imm implements YourClass_final
{
    protected YourClass yourObject;
 
    YourClass_imm(..params..)
    {
        this.yourObject = new YourClass(..params..);
    }
 
    int method1()
    {
        return yourObject.method1();
    }
 
    ....
}
 
We are now able to declare immutable instances of YourClass!
 
What about inheritence? The observent ones among you will
have noticed that yourObject was declared as having
protected scope rather than private. This is so that when
you have a chlid class, the immutable child can still
inherit from the immutable parent:
 
 
class YourChild_imm implements YourChild_final
{ 
    YourChild_imm(..params..)
    {
        super(new YourChild(..params..));
    }
 
    int method1()
    {
        return ((YourChild) super).yourObject.method1();
    }
 
    ....
}
 
Note that there is no need to declare a YourChild member
here, since there is already a member in the parent. In an
ideal world there would be _final and _imm classes
throughout the entire java class tree, from java.lang.Object
downwards, so no _imm classes would need a member, they'd
all refer to the one in Object_imm.
 
Note also that you need to downcast the member in the parent
to the class you are making an immutable version of.
Sounding more complicated? This is a bit more involved than
the basic "final for objects" described in the previous
post. However the good news is that the generation of the
_imm class can be automated once the corresponding _final
class is in place.
 
Regards


Submitted On 29-AUG-2001
finking
To clarify my recent posts I am totally behind having
references
to constant values, which is why I've voted for this. The
workaround I presented is just that, a workaround and would
never be as good as the introduction of C++ type constness.
I thought people might be interested in the short articles
I'd written so I posted them. In hind sight it probably
would have been less confusing if I'd not included the
immutability post as that is a separate issue.

However if you read my second post, I think you'll find it
gives you C++ style constness. For the sake of those
unfamiliar with C++ you have

const Class * obj;

to mean obj is a pointer (reference) to a constant instance
of Class and

Class * const obj

to mean obj is a constant pointer (reference) to an instance
of Class

In Java final covers the second option, but not the first,

final Class obj

means obj is a constant reference to an instance of
Class. Now in C++ the meaning of the const keyword is
determined by it's position. In C++ putting it at the front
means "const object" and right before the identifier means
"const reference". In Java it's the other way around putting
final in front means it's a const reference, so to complete
the C++ constness picture all we need is to allow:

Class final Obj

Which would mean Obj is a reference to a constant instance
of Class. That's what I personally want to see and that's
why I voted for this enhancement.

However in the interim you find that the workaround that I
outlined allows you to do:

Class_final Obj

To mean the same thing. The only difference syntactically is
that you use an underscore instead of a space. Either way
though, you get C++ constness

Cheers

Robert Finking

PS To put to rest any fears you may have about my
understanding of C++ constness it's worth saying that I have
roughly the same amount of industrial experience in C++ as I
do with Java. Regards.


Submitted On 30-AUG-2001
dkf
IME, one of the most awkward things about the use of 'const'
in C++ is the way that moving it around causes it to have
different meanings.  Sure you can work it out, but it makes
life quite difficult.  Worse, you'd still have this
complexity in Java with multi-dimensional arrays, even if
the proportion of people bitten by it would be less.

The sole good feature of 'const' that I miss is being able
to say that a particular array reference can't be used as an
Lvalue.  The neatest work-around for this is really using
design-by-contract to specify that the array reference
returned by a method cannot be modified (or perhaps rather
that an array returned this way is only ever modified in a
controlled fashion.)  All the other things discussed here
(Robert Finking's suggestions in particular) won't be in the
slightest bit elegant for this case (wrapper classes *and* a
different method of access?  Yuck!) though they do indicate
why the need is not pressing for the rest of the language.

On reflection, design-by-contract is probably the way to go
anyway, but more particularly as it allows the capturing of
more of the intent of the code (immutability of reference is
only one of the things you might specify with such a system)
and it need not be too closely linked with Sun anyway (as
long as they don't heave roadblocks in the way. :^)


Submitted On 30-AUG-2001
andythomascramer
The interface hack presented at length by finking has been 
discussed in earlier posts. It's discussed in the very 
first post, and a list of negatives are in the ninth.

>const Class * obj;
> to mean obj is a pointer (reference) to 
> a constant instance of Class and

No, in C++, this means that obj is a pointer restricted to 
const operations on an instance of Class. This RFE seeks 
the same semantics for Java -- the ability to mark a 
_reference_ as restricted to const operations.



Submitted On 16-OCT-2001
adamc
const correctness would be a real boon for java. One thing 
to consider is whether more general design-by-contract 
support (a la Eiffel) would be better than just 
adding "const" and "mutable".


Submitted On 24-OCT-2001
Brill
I'm not a fan of the idea myself, at least not with the 
reasons you give. your objects should be designed better in 
the first place. I would think very carfully before adding 
such a major change to the way you *think* about writing 
java code.


Submitted On 24-OCT-2001
ethanleet
Keep const out.  Java came from C++, but it is not C++.
C++ allows for sloppy designs and programming.  Java forces
the programmer or developer to design better.  Java is more Object
Oriented.  Lets keep it that way.


Submitted On 09-NOV-2001
finking
We need const to
1. Mark methods as not changing internal state
2. Mark objects as only being allowed to call the methods outlined in 1 and
3. To mark whole classes (as immutable), to allow the compiler to check that an immutable class really is 
immutable. At the moment you can write a class, think it's immutable but have some mutable aspect to the 
class due to a mistake you've made.
4. To mark arrays as const

Regarding other recent comments, design by contract gives you run time checking. The whole point of 
constness is you get the security of compile time checking - no latent bugs. Interestingly the whole theory 
that DBC is based on (predicate calculus) was originally employed as a formal method, used to prove  (or 
disprove) program correctness. The fact that doing the manual proof offline is arduous has led to this whole 
idea of runtime checking, which is a great way to keep some of the rigour (baby) whilst throwing away the 
impractical proof process (bath water). However, I can't help thinking that parts of a contract might not still  
be checkable at compile time. It just needs somebody to write the analysis tools and people to be prepared 
to wait for them to run.

On the point about constness being a C++ idea and therefore not OO: the concept of constness is abstract 
and nothing to do with C++ per se, any more than having a president is anything to do with Russia. 
Constness actually makes more sense in an OO environment than it does outside of it. Why do you think 
constness is anti-OO?

Andy, I agree with you. When I talk about a "constant instance of a Class", I do mean an instance from 
which you can only call const methods. The class based workaround I outlined is not the same as the 
schemes outlined at the start in that it addresses the need for both constness and immutability. The point 
that seems to have been missed in other schemes is that you want all of the follwing:
1. You want to be able to declare a class as immutable
2. You want to be able to declare an object as either mutable, const or immutable
3. You want to be able to pass either mutable or immutable objects to a const object parameter (since both 
mutable and immutable versions support the const methods)
4. You want to be able to provide a separate implementation for immutable classes since there are often 
perfomance benefits to be had from taking advantage of the immutable nature of the class, however you 
also need a trivial default implementation for immutable classes to avoid having to write the same class 
twice (immutable and mutable versions).

Point 3 above is the one thing that worries me about the const keyword idea. There is currently no effort to 
provide a parent interface that covers both mutable and immutable versions of a class. The big culprit here 
is String/StringBuffer - instead of having a parent interface that covers both classes, you end up having to 
create an intermediate String object whenever you want to pass a StringBuffer object into a method. If we 
go down this route than I fear that we'll have to take a leaf out of String/StringBuffer's book and every 
immutable/mutable pair of classes we'll have to provide explicit conversion routines. Ah well, small price to 
pay eh?


Submitted On 15-NOV-2001
hwc
Finking’s comments may point towards another solution to 
the problem – a const interface.

Ideally we should be able to define individual methods 
const so that the compiler prevents us
from changing an object’s state accidentally but it would 
be equally possible, and giver greater
backwards compatibility, to list the public methods in an 
interface marked const.  A const
reference to an object would use this const interface.  An 
immutable object would not have
any other public methods; mutable objects would.

Covariant return types would make this approach 
straightforward.  In many cases, it may be
possible to retro-fit existing classes with const 
interfaces.  I don’t know how easy it would be
to apply this approach to String/StringBuffer.  
Unfortunately it doesn’t work with arrays.


Submitted On 20-NOV-2001
hlovatt
Continued from above ...

// note - final in immutable form and implements Immutable
public final class Int extends AbstractInt implements 
Immutable {
    
    // note - final in immutable form
    final int value;
    
    public Int(final int value) { this.value = value; }
    
    // for AbstractInt
    public AbstractInt create(final int value) { return new 
Int(value); }
    public int getValue() { return value; }
    
    // for Immutable - return by copy
    public Object toMutable() { return new MutableInt
(value); }
    
}

// note - not necessarily final in mutable form and 
implements Mutable
public final class MutableInt extends AbstractInt 
implements Mutable {
    
    // note - not final in immutable form
    int value;
    
    public MutableInt(final int value) { this.value = 
value; }
    
    // for AbstractInt
    public AbstractInt create(final int value) {
        return new MutableInt(value);
    }
    public int getValue() { return value; }
    
    // for Mutable - return by copy
    public Object toImmutable() { return new Int(value); }
    
    // 'set' functions - the mutable stuff
    public void set(final int value)  { this.value = 
value; }
    public void set(final AbstractInt value)  { 
        this.value = value.getValue(); 
    }
    public void setAdd(final int value) { this.value += 
value; }
    public void setAdd(final AbstractInt value) { 
        this.value += value.getValue(); 
    }
    
}

This technique works for all classes including arrays. 
Typical usage is:

public final class Test {
    
    // note - you could program to the abstract type 
(AbstractInt) but this
    // would require more type conversions. Type casts 
shown are not 
    // necessary with covariant return types, Java v1.5?
    public static void main(final String args[]) {
        final Int a = new Int(2);
        final MutableInt m = (MutableInt) a.toMutable();
        final Int b = new Int(3);
        final Int c = (Int) a.add(b).add(m);    // Int + 
Int + MutableInt
        System.out.println("c = " + c);
        m.setAdd(a);                            // 
MutableInt + Int
        m.setAdd(m);                            // 
MutableInt + MutableInt
        System.out.println("m = " + m);
        final Int d = (Int) m.toImmutable();
        m.setAdd(m);                            // Check d 
not aliased
        System.out.println("d = " + d);
    }
    
}

Continued below ...



Submitted On 20-NOV-2001
hlovatt
Continued from above ...

Compare this with the same functionality using const below. 
The program 
below is written in C++ because Java doesn't have const, 
but you will get 
the idea! Note 1: the Java syntax would be a little 
different but roughly 
the same amount of typing. Note 2: Don't do this in C++ - 
no garbage 
collector!

// 'set' and 'non-set' (const) operations all together
class integer {
public:  
    // construct from primative and integer
    integer(const int value) { this->value = value; }
    integer(const integer* const value) { this->value = 
value->value; }
    
    // 'non-set' (const) methods - the immutable stuff
    // add to primative and integer returning copy
    integer* add(const int value) const {
        return new integer( this->value + value );
    }
    integer* add(const integer* const value) const { 
        return new integer( this->value + value->value ); 
    }
            
    // 'set' methods - the mutable stuff
    // add and set to primative and integer changing self
    void set(const int value)  { this->value = value; }
    void set(const integer* const value)  { this->value = 
value->value; }
    void setAdd(const int value) { this->value += value; }
    void setAdd(const integer* const value) { 
        this->value += value->value; 
    }
    
    // For debugging primarily
    friend ostream& operator<<(ostream&, const integer* 
const);

private:
    // Fields mutable because const gives immutability
    // Typically there would be a large number of fields
    // or a pointer to a structure
    int value;
};

// For debugging primarily
ostream& operator<<(ostream& out, const integer* const 
value) { 
    return out << value->value; 
}

main() {
    const integer* const a = new integer(2);
    integer* const m = new integer(a);
    const integer* const b = new integer(3);
    // const integer + const integer + integer
    const integer* const c = a->add(b)->add(m);
    cout << "c = " << c << '\n';
    m->setAdd(a);				// integer 
+ const integer
    m->setAdd(m);				// integer 
+ integer
    cout << "m = " << m << '\n';
    const integer* const d = m;	// or: const integer* const 
d(m)
    m->setAdd(m);				// Oops, d 
aliased
    cout << "d = " << d << '\n';
}

Comparison of techniques:

1. Comparing the two 'mains' we see little difference 
between having and 
not having const in terms of the required typing. 

2. The problem with introducing const is that we introduce 
a subtle bug, 
you can alias the constant version and it can change! See 
last three lines
of the two 'mains'.

3. As noted by Finking the immutable form is likely to be 
quicker than the 
const form.

4. The immutable form is thread safe, const isn't because 
of aliasing to a 
non-const version.

Conclusion:

Canvas for immutable keyword, as suggested by Gosling, and 
not for const
keyword!


Submitted On 20-NOV-2001
hlovatt
You can get the behaviour requested by Finking using an 
abstract base 
class and deriving from it an immutable class and a 
companion mutable 
class. EG

public interface Immutable {
    // Convert to mutable by copying!
    Object toMutable();
}

public interface Mutable {
    // Convert to immutable by copying!
    Object toImmutable();
}

// No 'set' Operables in outer class and therefore immutable
public abstract class AbstractInt {
    
    // no fields because immutable inner class needs final 
values and 
    // mutable non-final
     
    // abstract methods that mutable and immutable forms 
must implement
    public abstract AbstractInt create(final int value);
    public abstract int getValue();
    
    // add to primative and AbstractInt that are common 
    // to both mutable and immutable forms. Not final to
    // allow overloading for performance reasons if 
necessary
    public AbstractInt add(final int value) {
        return create( getValue() + value );
    }
    public AbstractInt add(final AbstractInt value) { 
        return create( getValue() + value.getValue() );
    }
    
    // For debugging primarily, therefore not final
    public String toString() { return Integer.toString( 
getValue() ); }
    
}

Continued below ...


Submitted On 23-NOV-2001
finking
hlovatt, you first paragraph and hwc, your second paragraph,
capture exactly what I was intending to convey in my orginal
posts. I wish I could have put it so succinctly in the first
place!

One extra point in favour of getting this added to the
language is speed, in addition to my previous 4 points, we
need a const keyword so that:
5. accessors in immutable objects can avoid making defensive
copies - thus saving (a potentially huge amount of) time.
This means immutable objects can finally shed the only ugly
thing about them.


Submitted On 26-NOV-2001
hlovatt
Point 5 added by Finking is a very good point - I wish I 
had included it in my original list!


Submitted On 11-JAN-2002
streissel
Const parameters is really a needed feature.
For example most of the get functions should be able to 
return const. Most of the set functions should take const 
parameters.
Please add const parameters!


Submitted On 19-JAN-2002
cfmdobbie
I have to vote for this, even though I acknowledge the 
added complexity and changes to the current libraries that 
would be required.  Currently I don't feel happy returning 
from a function any object that isn't mutable, due to 
possible abuse by the user of said function.  Some kind of 
const mechanism would put another layer of safety in front 
of my business applications, and help to ensure they 
function correctly.


Submitted On 22-JAN-2002
hlovatt
I have suggested an alternative, see RFE 4617197, which I 
think gets over the problems of a C/C++ style const 
specifier. In particular the syntax is cleaner, you can't 
accidently cast away const, but you can still convert 
between mutable and immutable (const) forms.


Submitted On 08-FEB-2002
shrink_laureate
(continued...)

SOLUTION
Existing code is unaffection; the 'const' keyword should be 
left well alone, because it's inherently confusing.  Three 
keywords should be added:

  "readonly" : marks a reference as not being allowed to 
modify an object.
  "writable" : explicit cast to assign a readonly reference 
to a writable reference.
  "safe" : when used on a method, indicates that it will 
not change the object's state. A safe method may not set 
any values, or call an unsafe method. When used on a 
member, indicates that it will be considered readonly 
inside all safe methods. When used to modify an interface, 
forces that all methods on that interface must be safe.
  "notnull" : because i feel like it. marks a reference as 
having to contain a real value

Code using this would look something like:

  class Thingy {
    Foo foo = new Foo();
    public safe readonly Foo peek()
      { return foo; }
    public void poke(readonly Foo newfoo)
      { foo = newfoo; }
    public void plonk(Foo newfoo)
      { 
  }

  class Doodad {
    readonly Thingy thing = new Thingy();
    public void doFoos() {
        //  these lines are fine
      readonly Foo myfoo = thing.peek();
      thing.poke(myfoo);

        //  these are ok as well
      Foo myfoo2 = (writable) thing.peek();
      thing.poke(myfoo);

        //  these lines generate errors
      Foo myfoo3 = thing.peek();
      thing.poke(myfoo);

        //  so does this line
      thing.plonk(myfoo);

        //  but this one is ok
      thing.plonk((writable) myfoo);
    }
  }

As I hope you can see, those changes to the code doesn't 
add any great complications to the Java syntax, or 
undermine the language's security.  A method can have both 
safe and readonly modifiers: safe indicating that it 
doesn't change the members, and readonly to indicate that 
it returns a read-only reference.

As described above, a safe method could still modify the 
contents of a non-readonly member. By marking the member as 
safe, it inherits the behaviour of the current method - 
hence a safe method sees a safe member as if it were 
readonly, while an unsafe method sees it as a normal 
writable member.

There is a confusion left between a readonly array, and an 
array whose members are readonly. Sadly, there only option 
I've seen here is the kludge suggested by andythomascramer:

readonly Foo[] x;   //  you may not write into the array
Foo[ readonly ] x;  //  you may not write into each member

If anyone can think of a better solution to the last 
problem, let me know. If we can agree on a proposal similar 
to that, I'll be prepared to vote for this.


Submitted On 08-FEB-2002
shrink_laureate
One final note: this is not Design by Contract, and it 
doesn't pretend to be.  However, it does inch Java ever so 
slightly more in the direction of it, by allowing a small 
subset of invariants to be stated in code.  In this 
respect, the notnull keyword is as important as this RFE.


Submitted On 08-FEB-2002
shrink_laureate
The idea of a read-only reference is a nice one, in that it 
makes implicit assumptions explicit, and lets you use the 
compiler to prevent mistakes. But to inherit all, or even 
any, of the syntax from C++ is a mistake.

Unless i'm stupid and blind (you'll get your chance to 
argue this in a minute), the idea being proposed is:
 1. A reference may be flagged as "read-only". You cannot 
use this reference to write to the object, and you cannot 
assign it to an ordinary (writable) reference without an 
explicit cast. This does not prevent the object from being 
changed from elsewhere.
 2. To enforce this, methods are flagged as either non-
modifying and safe to use, or modifying and unsafe. The 
compiler will prevent you from using unsafe methods.
 3. The body of a non-modifying method believes that 'this' 
is a read-only reference, and enforces rules 1 and 2 on it.
 4. All of this is checked at compile-time, not at run-time.

This is a good possibility, and as far as i can see a type-
safe way of programming. For the time being i'm leaving 
aside immutable classes and objects, because they have 
their own RFE (4617197).  When deciding on syntax for this, 
it should follow these rules:

 1. It should not have any harmful effect on existing Java 
code.  Hence, the meaning of keywords like final, transient 
etc should remain unchanged.
 2. It should not undermine the existing Java security 
model, allowing dangerous code to be written.
 3. It should not undermine the current Java syntax.  In 
particular, C++ uses syntactic tricks involving the 
position of the const keyword which do not fit into Java.

A Java method looks like this:
 <modifiers> <return type> <name> '(' <arguments> ') {' 
<body> '}'

The modifiers may be in any order, even if convention 
places them in a certain order, and there are no modifiers 
between the return type, name, arguments and body. This 
will not and should not change - if you want to compromise 
this, give up now.  Specifically, you will never get 
methods that look like this:
   int g(int x) const { }
or this:
   int const g(int x) const { }

Because their meaning is not clear. A variable declaration 
looks like this:
  <modifiers> <type> <name> [ '=' <initial value>];

Again, the modifiers may be in any order but may not appear 
between the type, name and initial value.  Again, this will 
not and should not change.  You will never get code like 
this:
   int[] const x;
or this:
   int[] x const;


Submitted On 11-FEB-2002
Ixchel
In general, I think that shrink_laureate proposal (see 
previous message) is a good one. Some comments on it:
1) I don't like the keyword 'safe', because I think it is 
too vague. ("Safe" in what fashion?) I think naming it 
something like "nonmutating" or something with similar 
meaning would be better. Or, if you were to apply my 
suggestion to use symbols instead of keywords (see below), 
you could instead use the keyword "readonly" for this 
purpose, and use the "@" symbol for the purpose that 
shrink_laureate uses the "readonly" keyword for.
2) I heartily approve of the "notnull" keyword he suggests. 
I'm REALLY tired of writing code that says essentially "if
(foo==null) throw new IllegalArgumentException(whatever)". 
IMHO, this should be prevented at compile time, not runtime.
3) As for the arrays problem, I suggest that in general, in 
Java, declarations are built from left to right (ignoring 
for the moment the C++-inherited abomination that allows 
declarations like "int i[]"). Normally, declarators are 
unary operators that apply to whatever is immediately to 
the left of them. For instance "int []" is an array of int, 
and "int [] [] " is an array of "array of int". As such, 
the logical place for a "readonly" keyword to go would be 
to the right of the item it modifies. Therefore, we would 
have:
    int readonly x; // a read-only int
    int readonly [] x; // An array of readonly ints
    int [] readonly x; // A readonly array of ints
    int readonly [] readonly x; // A readonly array of 
readonly ints.
Since this syntax can get a bit verbose, it might be 
preferable to use some kind of symbol instead of a keyword. 
I'd suggest "&" for "notnull" (this is loosely analogous to 
C++ usage of reference types, which are never legally 
null), and "@" for "readonly". Thus we would have:

    Foo @ x; // a read-only Foo object
    Foo @ [] x;  // An array of readonly Foo objects
    Foo [] @ x; // A readonly array of Foo objects
    Foo @ [] @ x; // A readonly array of readonly Foo 
objects.
    Foo & x; // A non-null Foo object
    Foo [] & x; // A non-null array of Foo objects
    Foo & [] x; // An array of non-null Foo objects
    Foo & @ [] & @ x; // A non-null readonly array of non-
null readonly Foo objects.
    Foo @ & [] @ & x; // Same as above.


Submitted On 12-FEB-2002
shrink_laureate
No offense, Ixchel, but using symbols like & and $ and @ 
doesn't feel at all right. It doesn't feel like Java, it 
feels like Perl.  Not to mention that it doesn't explain 
what the purpose of it is unless you have already learnt 
it, leading to lots of newbie mistakes.

I'm not entirely happy with the word "safe" either, but 
it's a tough concept to describe.  "nonmutating" would be a 
good choice, but I'm always open to ideas.  In either case, 
it should definitely be a keyword modifier, not a symbol 
format.

I don't think I've quite sorted out the ordering of arrays 
yet, but I do have one rule to apply: any modifiers go 
*before* the type, always have done in Java.  That means 
the standard case must be:

  readonly Foo x;  //  x is a read-only foo
  readonly Foo[] x;  //  x is a read-only array

With the entire array's modifiers on the far left, smaller 
modifiers should go somewhere in the middle.  The options 
are:

  Foo readonly[] x;
  Foo [readonly] x;
  Foo[] readonly x;


Submitted On 13-FEB-2002
shrink_laureate
Hey, I hope you guys at Sun are reading this!


Submitted On 13-FEB-2002
shrink_laureate
> RFE 4617197 covers immutable arrays, not null, and has
> clean syntax ;)

Err... not really.  They're different questions entirely.  
As the RFE states, it's a difference between making all 
instances of a class immutable, and making a single 
reference read-only.

I don't like 4617197 because it suggests that inheriting an 
interface gives your class different compile-time 
behaviour, which is just... wrong.  To push that to even 
preventing null being assigned to a known immutable type is 
utterly twisted.  Besides, what if i don't want to make my 
class permanently, irreparably immutable just to prevent 
one instance from being null?  Or say I want to make sure a 
reference to somebody else's object isn't null?  It really 
isn't a solution.

Should I start an RFE for a notnull keyword?  Would that 
help things, or swallow important votes from other 
subjects? Or just be ignored and forgotten?


Submitted On 13-FEB-2002
shrink_laureate
> the kinds of modifiers we are talking about here
> are actually type specifiers, used to construct complex
> types from more simple ones

I think i'm starting to see your point.  If i can 
paraphrase you, you're saying that the ordinary modifiers 
are for external characteristics of a reference, such as 
its visibility, while these codes are for its type, which 
is a separate element.

The problem is that Java's types aren't that dynamic, so I 
didn't instantly see the difference.  Arrays in particular 
have a syntax that's almost designed to prevent any 
flexible modifications of the type.

There are languages that have very dynamic types, but lose 
out on the type-safety, such as SmallTalk and ObjectiveC.  
If I have one disadvantage on this subject, it's that I 
don't know Eiffel, so one of the major points of reference 
is missing.

So... how to create a syntax that clearly shows that they 
modify the type, without being utterly confusing for 
newcomers, and without breaking too many existing Java 
rules.

I'm still resisting the use of @ $ & symbols, because I've 
seen the effect that they had on C and Perl code.  
Especially forbidden are & and *, because Java is still too 
close to C to be free of its confusing influence.

The only thing that springs to mind is to use the generic 
operators < > to show that this is a dynamic type:

  <readonly Thingy> myThingy;
  private <notnull readonly Doodad> myDoodad;
  final <nonmutating Map<Thingy, readonly Doodad>> myMap;

But most people would get tired of typing the brackets so 
often - and i still don't know what to do with the arrays.

*sigh*  if anyone has an answer, that doesn't involve the 
use of symbols, feel free to chip in!

(ps - to anybody who has more interesting things to do with 
their life than learn every programming language under the 
Sun, I'm sorry if this post sounded elitist at all. if you 
feel you have a solution, but don't have all that 
background in other languages and theory and stuff, feel 
free to suggest it - you could prove us all to be idiots.)


Submitted On 13-FEB-2002
hlovatt
RFE 4617197 covers immutable arrays, not null, and has
clean syntax ;)


Submitted On 13-FEB-2002
Ixchel
Yes, but RFE 4617197 doesn't allow me to have both a not-
null and a nullable reference to the same type. It also 
provides no clean way to pass a mutable object to a 
function that promises not to modify it. As such, it's not 
an adequate replacement for 'const' (although I think 
immutable objects as described in RFE 4617197 are useful 
for other things).

As regards shrink_laureate's comment of:
>I don't think I've quite sorted out the ordering
>of arrays yet, but I do have one rule to apply:
>any modifiers go *before* the type, always have
>done in Java.

Hmm. Can't agree with you on that one. Apples and oranges, 
really. Modifiers like 'static', 'final', etc. apply to the 
VARIABLE, not to the TYPE of the variable. As such, putting 
them at the beginning of the declaration is consistent. 
However, the kinds of modifiers we are talking about here 
are actually type specifiers, used to construct complex 
types from more simple ones. They aren't analogous to the 
modifiers that specify the duration, location, or 
visibility of the variable (static, final, public, etc.) 
that is declared of that type.

shrink_laureate, I think that your preference for using 
keywords for these is confusing you into thinking that 
these keywords are in some sense equivalent to other 
keywords because, well, they're keywords. In fact, "const" 
and "notnull" used in this fashion are much more similar to 
constructs like "[]" than they are to constructs 
like "final" or "static" which apply to the variable 
itself, rather than to its type. Hence my willingness to 
use symbols for them. I don't mind not using symbols, but 
if symbols aren't used, we should still keep in mind that 
the behavior of these constructs is semantically similar to 
places that symbols ARE used in Java.

Placing things at the front of the declaration only makes 
sense for things that can only occur once in the 
declaration, and "[]", "readonly", and "notnull" don't fall 
into this category, all for essentially the same reason: 
they must make clear which part of the type they apply to 
by their position. Remember, with the generics proposal in 
place, types can get quite complicated: "List<Integer 
readonly [] readonly> readonly" and such. Having a special 
case for the placement of the first keyword, but not for 
the rest of them would get rather confusing, IMHO. 

After having dealt with this problem in C++ for years, I 
can report that it is highly confusing, both to newbies and 
to advanced programmers. I have met relatively few C++ 
programmers who can correctly explain the meaning of "const 
int * x;" versus "int const * x;" versus "int * const x;", 
and this is largely due to the confusing inconsistency 
between the placement of 'const' in simple cases as versus 
complex ones.

Note that the frequent usage of the syntax "const int x;" 
in C++ is somewhat of a historical accident -- people 
started doing it that way, and the habit got formed. The 
syntax "int const x;" is actually also legal and means 
exactly the same thing, and is furthermore much more 
consistent with the use of more elaborate constructs such 
as "int const * const * const" (a constant pointer to a 
constant pointer to a constant integer). Also note 
that 'const' and 'volatile' are the only type constructors 
in C++ that are represented by keywords instead of symbols. 
[The other type constructors include things 
like "()", "[]", "&", and "*"] This inconsistency 
frequently confuses people.


Submitted On 13-FEB-2002
kriff
Forgive me if this has been mentioned before. I don't have 
time to read all of the comments.

I'm not a C++ programmer, but I've read some articles about 
problems with the const keyword in that language. IIRC, the 
biggest problem was that most methods need to be overloaded 
with const and non-const versions, which leads to an 
explosion of duplicate methods. I think C++ introduced a 
way to cast a const to a non-const but that somewhat 
defeats the purpose of the const keyword.

I've been toying with an idea that involves marking 
references as 'const' at runtime, rather than compile time. 
If an attempt is made to modify an object via a const 
reference then an exception would be thrown.

I haven;t worked out a syntax yet or all the semantics, but 
I expect it would work something like this:

Foo f = new Foo();
Foo fc = (const) f;

f.field = 123;  // OK
fc.field = 123;  // Runtime exception

f.modify();  // OK
fc.modify();  // Throws a runtime exception from the body 
of the method

The advantage of this approach is that existing APIs don't 
have to change to benefit from the new syntax. Methods 
don't have to be marked 'safe' because the 'this' reference 
would carry the 'constness' information. No special syntax 
is required for arrays. Simply cast each element as you add 
them to the array, or cast the array reference itself.

There are some disadvantages, I will admit. This approach 
incurs a check for the 'constness' of a reference each time 
it is used. It also doesn't prevent an object from being 
modified elsewhere. However, this last problem goes away if 
you view 'constness' as the permission to modify an object, 
rather than a guarantee of immutability.


Submitted On 14-FEB-2002
hwc
Woops; sorry; repeat posting.

Thanks for your clarification, shrink_laureate, re. notnull - the mechanism you propose sounds similar to that 
already used to check that variables marked as final are properly initialised.  I wonder if it would allow us to 
go the whole way and define array elements as final too?

I agree that there's no ideal answer to the problem of legacy code but my fix would be rather different. A 
compiler would need to be able to check that methods marked as 'safe' really were and complain if they 
weren't.  It would also need to record that in the compiled class file.  I'd add a switch to the compiler to tell 
it to mark all such methods safe, even if the author had forgotten to do so.  To aid the transition, I'd add 
another compiler switch that allowed you to pass 'readonly' references to unsafe code - you'd get a warning 
message but if you chose to ignore it…

I suspect you could make similar transitional arrangements for your 'notnull' proposal.


Submitted On 14-FEB-2002
shrink_laureate
> I wonder if it would allow us to go the whole
> way and define array elements as final too?

    Thingy [final] doodads;

Now that's a nice idea!  hwc, you are a mine of good 
suggestions.


> my fix would be rather different... I'd add a
> switch to the compiler to tell it to mark all
> such methods safe, even if the author had
> forgotten to do so.

Or possibly nitro-glycerine.  This is bad, bad, bad.

Just because the version of a class that you have access to 
behaves in a notnull-safe or readonly-safe manner doesn't 
mean that a future version of it won't.  You can't trust 
the innards of a class, only its interface - especially 
when it was written by somebody else.  Unless a method's 
argument states that it is nonmutating, it could always 
change without notice.

An equally important, but less technical reason, is that 
developers *should* state such things in the interface.  
Only assigning to a variable once isn't as good as making 
it final, because when you look at the variable and *see* 
that it's final it stops you from breaking that without 
thinking. It also lets the compiler stop you from making 
similar mistakes.

Developers make assumptions when they code, about what can 
be null, what can be changed where, etc.  Putting those 
assumptions into the code itself is good for code safety, 
and good for developer stress levels.  To make it clear 
what this really means, imagine debugging in a language 
where every pointer was just a pointer to *something* - and 
you had no idea what it was.


Submitted On 14-FEB-2002
shrink_laureate
4617197... oh, the immutable types one.  our nemesis.  
gotcha.

Casting as Writable
-------------------

I don't like the casting back to writable either, hwc, but 
it sadly needs to be there. In an ideal, perfect language 
that has always had complete support for all forms of 
Design by Contract (that's Eiffel, if you believe them), 
you shouldn't need it. Unfortunately, there's a lot of java 
legacy code, including the entire set of core libraries, 
that won't use it.

Consider this case:

    readonly Object a = ...;
    readonly Object b = ...;

    if ( a.equals(b) ) ...;

We all know that Object.equals() does not change its 
argument in any way.  However, its signature in Object is:

    public boolean equals (Object other);

You see, it's argument is writable.  So passing a readonly 
value like b into the method would bring up an error and be 
utterly undoable unless there was some way that we could 
cast back.  The options are to automatically make it 
unsafe, which would utterly destroy the point of the whole 
mechanism, or to ask the user to make conscious effort to 
cast it. At least it can't happen by accident.

    a.equals((writable) b);

If you have a better solution to the legacy problem (or 
just as often, the 'somebody else's badly written code' 
problem), please share it.


Assigning Not-Null Values
-------------------------

As for the tricky cases of assigning notnulls, my intention 
is that the compiler would be intelligent enough to know 
when something cannot be null. If there is a known factory 
method that the compiler can scan and make sure always 
returns a real value (or throws an exception), it will 
allow the assignment.

Your array example is a little confusing, because to define 
an array you must always give its size.  However, i see 
your point.  Using notnull does restrict your creativity 
when creating these things: you need to be sure what you're 
doing.

The fact is, much of the time you would not be assigning 
from new values; you would be assigning an existing array 
to the new reference.

    Object[] temp = new Object[number];
    //  ...build the array...
    notnull Object [notnull] array = temp;

The compiler would need to analyze the code for building 
the array, to ensure that it leaves absolutely no gaps 
whatsoever.  But the fact is, that would be a pretty rare 
condition.  Most of the time, your code would be along the 
lines of:

    notnull Object [notnull] array = list.toArray();

This would, of course, make a lot more sense with generic 
programming. :-)  And don't forget that the variable isn't 
necessarily created on the same line as its declaration - 
as long as it does get created soon.

    notnull Object [notnull] array;
    array = list.toArray();


Syntax
------

You know, Ixchel, I'm feeling a lot less flexible that I 
was.  Especially seeing the ease with which hwc described 
his question.  I think keywords like that are fine, as long 
as they're grouped with the type rather than mixed together

    <modifiers> <type> <name>;

    private static ... notnull Thingy [notnull] ... 
myThingies;
    protected ... readonly Hashtable <String, notnull 
Thingy> ... myHashtable;

Beyond preference, can you really see anything wrong with 
that?


Submitted On 14-FEB-2002
hwc
Thank you, shrink_laureate.  Your proposal is almost enough to get me to switch back to this RFE from 
461797 but then you spoil it by allowing people to cast away const with 'writable'.

I like your 'notnull' idea but I'm not sure how it would work in practice without run-time checks.  For 
example:

	notnull SomeObject var = SomeObject.factoryMethod();

Perhaps factoryMethod() needs to be flagged as notnull, too.

	public void someMethod( notnull SomeObject arg1 ) { … }

OK if you pass a nonnull variable but what about a more complex expression.  Do all methods that return 
objects need to be flagged as notnull?

	notnull SomeObject[ notnull ] array = new SomeObject[];

Fails to compile, I assume; how do you initialise the array?  It would work in C++ because the default 
constructor is called for each element.

Somehow there needs to be a way to pass collections of objects from one method to another safely and 
efficiently.  These RFEs get us closer but I'm still waiting for the perfect proposal.


Submitted On 14-FEB-2002
hwc
Thank you, shrink_laureate.  Your proposal is almost enough to get me to switch back to this RFE from 
461797 but then you spoil it by allowing people to cast away const with 'writable'.

I like your 'notnull' idea but I'm not sure how it would work in practice without run-time checks.  For 
example:

	notnull SomeObject var = SomeObject.factoryMethod();

Perhaps factoryMethod() needs to be flagged as notnull, too.

	public void someMethod( notnull SomeObject arg1 ) { … }

OK if you pass a nonnull variable but what about a more complex expression.  Do all methods that return 
objects need to be flagged as notnull?

	notnull SomeObject[ notnull ] array = new SomeObject[];

Fails to compile, I assume; how do you initialise the array?  It would work in C++ because the default 
constructor is called for each element.

Somehow there needs to be a way to pass collections of objects from one method to another safely and 
efficiently.  These RFEs get us closer but I'm still waiting for the perfect proposal.


Submitted On 15-FEB-2002
hlovatt
Hi, even though I support the immutable RFE 4617197 and 
would like to vote against this RFE (if negative votes 
were possible ;) ), I can think of a solution to many of 
the const_casts (writable casts) that it has been 
suggested would be needed. 

Const_cast
----------
The situation re. const_casts isn't as bad as you make 
out. Using C++ style notation (readonly suggestion 
probably better but people are less familiar with it), and 
taking the standard class Date as an example, if Date were 
re-written (see aside below) to use const it would become:

public class Date {
    private long time;
    public Date(final long time) { this.time = time; }
    public long getTime() const { return time; }
    public void setTime(final long time) { 
        this.time = time; 
    }
    // Rest
}

The compiler could split this into two classes, like it 
currently does for inner classes. Generating:

public class Const$Date {
    protected long time;
    public Const$Date(final long time) { 
        this.time = time; 
    }
    public long getTime() { return time; }
    // Rest of const methods
}
public class Date extends Const$Date {
    public Date(final long time) { super(time); }
    public void setTime(final long time) { 
        this.time = time; 
    }
    // Rest of non-const methods
}

Then everywhere you write 'const Date' the compiler 
substitutes Const$Date. You can then write:

Object a = new const Date(1);
Object b = new const Date(2);
boolean equals = a.equals(b);

Note there is no const_cast and a and b are const views of 
a Date object. A const_cast where needed wouldn't need 
special notation, you would simply cast to Date.

This begs the question, why bother with special const 
syntax. The people who wrote Date (and anyone else who 
wants a const view) can trivially, as it stands at the 
moment, split a class into a const part and a non-const 
part. 


Submitted On 15-FEB-2002
hlovatt
Aside
-----
I think you have to re-write a class to mark methods as 
const and arguments as const. I can't convince myself that 
the compiler can do this automatically. Presumably 
everyone else is of this view and hence all the syntax 
suggestions of how to do this.

Unfortunately re-writing classes is unlikely to happen 
(there is such a small advantage), so even if you had a 
const keyword it wouldn't be much use. EG if Date wasn't 
re-written and you were allowed to say:

const Date cd = ...;

you would have to say

l = ( (Date) cd ).getTime(); // (Date) is a const_cast

because getTime isn't marked as const in Date. Also you 
would often, even using my proposal, still have to const 
cast when passed as an argument to many methods.

Immutable
---------
I used to use the above const view idiom (pattern) in my 
code until I discovered that immutable types were much 
better (you don't get aliasing). Presumably James Gosling 
knew how much better immutable types are all along, that 
why he wrote String and StringBuffer and didn't make 
String a const view of a StringBuffer. Now that I 
appreciate immutable types I write:

public abstract class AbstractDate {
    public abstract long getTime();
}
public final class Date extends AbstractDate 
implements ToMutable {
    private final long time;
    public Date(final long time) { this.time = time; }
    public long getTime() { return time; }
    public Object toMutable() {
        return new MutableDate(time); 
    }
}
public class MutableDate extends AbstractDate 
implements ToImmutable {
    private long time;
    public MutableDate(final long time) { 
        this.time = time; 
    }
    public long getTime() { return time; }
    public void setTime(final long time) { 
        this.time = time; 
    }
    public Object toImmutable() { return new Date(time); }
}

This begs the question, why did I bother to ask for RFE  
4617197, I already essentially use immutable types using 
the above idiom (pattern). Because, if immutable types are 
compiler and JVM supported then we get many optimizations 
that aren't currently possible. This will lead to a 
smaller memory footprint and faster running. Also the 
compiler can automatically write clone, readresolve, etc. 
These are considerable advantages, whereas const simply 
saves a couple of lines when you define a class.


Submitted On 18-FEB-2002
shrink_laureate
There you go again, confusing us with immutable classes.  
They're very different concepts.

A const reference isn't a different sort of object from a 
normal reference. What it represents is a promise: I 
promise not to change this object.  I promise that I will 
not generate any side effects you weren't expecting.  I 
promise that calling this method is harmless.

You see the difference? It isn't the object that's 
different.  It's what a section of code is allowed to do to 
it.  Different concepts.

And I can't think of any more messy solution than 
generating 3 or 4 extra classes for each of these I want to 
do. It's supposed to by dynamic!


Submitted On 20-FEB-2002
jessh
If not for the fact that I've used all my votes on more 
near-term pressing concerns (like 4466510 and 4267080), I'd 
vote for this.

After the lack of generics (which, of course is being 
addressed), this issue leads the list of "lost 
functionality" in moving from C++ to Java.  "const" allows 
compiler checking of a whole level of intent and usage that 
Java compilers cannot check -- because the language 
provides no means for the author to convey such intent.

[Of course I want interfaces to allow default method 
implementations in terms of other interface methods (i.e. 
no extension to field usage beyond the current) too....]


Submitted On 21-FEB-2002
shrink_laureate
public Thing[] getStuff() {
  return mStuff;
}

Right now, this is utterly unsafe - the client could change 
the array.

Workarounds:
 1. copy the array - slow at runtime, especially if it's 
big.
 2. write a special ImmutableThingArray class - extra 
pointless work.


Submitted On 21-FEB-2002
shrink_laureate
Ixchel elightened me with:
> Or, put another way, this 
> phrase, "dynamic type", already has a meaning that I 
> suspect you don't intend. Dynamic types are ones that can 
> change at runtime.

You mean, that the object itself is actually turned from 
its own type into another type? Adding, removing and 
mangling fields as you go?

Well, you learn something every day.  (At least, you try 
to.)


> The 'const' implementation in C++, and 
> presumably the 'readonly' and 'notnull' ones in Java, 
would 
> strictly involve static (non-dynamic) typing of 
references. 
> The actual types of objects that those references 
reference 
> at runtime would be somewhat dynamic (polymorphic, that 
is 
> restricted to only types inherited from the type of the 
> reference), but this does not change the fact that Java 
is, 
> absent casting, basically a strongly-typed, and hence non-
> dynamically-typed language.
> ... &c. ...

Yup, that makes sense. I think you and I, Ixchel, agree on 
everything except syntax.


hlovatt countered with:
> If you dislike classes so much why do you do OOP?

Huh?

I love classes.  I love OOP.  What I love most about OOP is 
that every single class has a real, conceptual meaning.  
You have a class for each conceptual object, no more, no 
less.  You don't have a dozen extra versions of the same 
class laying around just in order to pretend you have 
better type-safety than you do.

> Regardless of how a compiler might implement a const view 
> and regardless of the syntax used, a const view can be 
> thought of as inheritance.

Yes... except that it's an inheritance that is totally 
separate from the inheritance of the real classes.

When I design classes, I want to write my code in a way 
that fits in with what I think the class is for.  That 
means that I have my own ideas about the shape of 
inheritance.  I don't want to have to mangle my entire 
class tree to fit in with a specific way of using those 
classes.

If the tree has to be mangled, and classes end up different 
in bytecode, that's the compiler's job.  My job is to 
understand the system I'm trying to write, and write 
classes to model it.  And as far as my personal 
understanding goes, constness is not a property of the 
object, but of the reference to it.  Immutability is what 
you get when you apply constness to the object itself, and 
that's something different.

The beauty of OOP is how it helps me to understand the 
system.  I don't want to sacrifice that whenever I require 
constness.


> Think of a Java, not C++, example that uses per object 
> syntax that cannot be done, syntax aside, with 
inheritance 
> or using final, i.e. something that cannot currently be 
> done.

Think of something that can't be done on a Turing Machine!


Submitted On 21-FEB-2002
hlovatt
In response to shrink_laureate

Trivial response ;)
-------------------
If you dislike classes so much why do you do OOP?

Considered response
-------------------
These statements below describe a const view an object, 
referred to as const x, and a non-const view of an object, 
referred to simply as x.

1. x ''is a'' const x

2. Anywhere I can write const x I can write x

3. The description of x ''promises'' that I can do 
everything with an x that I can do with a const x

4. x ''extends'' const x

5. x ''inherits'' all the properties of const x

They are of course all different ways of saying the same 
thing, that const x only allows me to view the state of an 
x object and not change it (whereas x allows me to view 
the state and change it). But the statements also describe 
an object relationship, i.e. x ''inherits/extends'' const 
x. Therefore a const view can be considered a type of 
inheritance, even if the syntax is different.

Regardless of how a compiler might implement a const view 
and regardless of the syntax used, a const view can be 
thought of as inheritance. I find grouping operations 
together into classes useful. That's why I like OOP. But 
grouping objects into classes inevitable means having 
classes, more than one. It is not my aim to reduce the 
number of classes. Quite the opposite I want more classes, 
more tightly focused. This is a divide and conquer 
approach. Lots of easily understood little classes. I 
think Grady Booch said ''if something is too complicated - 
make more classes''. 

Challenge
---------
Think of a Java, not C++, example that uses per object 
syntax that cannot be done, syntax aside, with inheritance 
or using final, i.e. something that cannot currently be 
done.


Submitted On 21-FEB-2002
Ixchel
shrink_laureate wrote:
> Ixchel wrote:
>> the kinds of modifiers we are talking about here
>> are actually type specifiers, used to construct complex
>> types from more simple ones
>
>I think i'm starting to see your point.  If i can 
>paraphrase you, you're saying that the ordinary modifiers 
>are for external characteristics of a reference, such as 
>its visibility, while these codes are for its type, which 
>is a separate element.

Yes, that is a correct statement of my point.

>The problem is that Java's types aren't that dynamic, so I 
>didn't instantly see the difference.  Arrays in particular 
>have a syntax that's almost designed to prevent any 
>flexible modifications of the type.

Er.. I think this is an incorrect use of the word "dynamic" 
as applies to types. Or, put another way, this 
phrase, "dynamic type", already has a meaning that I 
suspect you don't intend. Dynamic types are ones that can 
change at runtime. The 'const' implementation in C++, and 
presumably the 'readonly' and 'notnull' ones in Java, would 
strictly involve static (non-dynamic) typing of references. 
The actual types of objects that those references reference 
at runtime would be somewhat dynamic (polymorphic, that is 
restricted to only types inherited from the type of the 
reference), but this does not change the fact that Java is, 
absent casting, basically a strongly-typed, and hence non-
dynamically-typed language. (There are some exceptions to 
this, but they mostly involve casting and/or reflection).

In a strongly statically typed language, most type usage 
errors can be detected at compile time, rather than at 
runtime. This increases efficiency of the running code, 
finds errors earlier, and has a variety of other benefits. 
Contrast this with, say, Smalltalk, in which it is possible 
to call a method on an object, only to find out at runtime 
that "there is no definition for that method when called on 
the type of that object". In Java this can't happen, 
because all such errors are caught at compile time.

Anyway, to make your above point with slightly different 
terminology, the issue is simply that Java's typing system, 
while just as statically typed as that of C++, happens to 
provide fewer ways to construct types from simpler types 
than C++ does. In particular, it really provides only one 
such way: the "[]" syntax. (When Generics are added to the 
language, a few more options will appear.)

As an unrelated aside, personally, if I were designing the 
language, all references would be 
implicitly 'final', 'readonly', and 'notnull' unless 
declared otherwise. (I'd have 'mutable' and 'nullable' 
keywords instead). I think its a weakness in Java that you 
currently have to take special steps and invoke more 
verbose syntax to ADD safety, instead of having to take 
special steps to REMOVE it.

Also, as far as the comments that "it would be a huge 
amount of effort to make the libraries const-correct", I 
would note that yes, it is, and that nonetheless, exactly 
such an effort was taken when 'const' was added to C++. So, 
it's a large effort, but not without precedent. As a 
temporary workaround, it might be nice to be able to mark 
certain packages (e.g. JDK packages) as being not const-
correct (via a compiler command-line option?), so that new 
code could call them (unsafely) without using huge numbers 
of casts.


Submitted On 22-FEB-2002
davidtribble
I did not specify an explicit syntax for const declarations, but this can be
deduced from my code examples.

One sticky issue remains, though, which is how to declare const arrays
(or to be precise, arrays of references to const objects).  A few
possibilities:

    const T[]  a;          // Array of const T
    const T    a[];        // Array of const T

This is the simple case.  Reference variables 'a' and 'a[i]' are modifiable,
but the referrent object of 'a[i]' is not.  Thus 'a = b' and 'a[i] = x' are okay,
but 'a[i].poke()' is an error.

    const T[][]  b;       // Array of array of const T

This is trickier.  Variable 'b[i][j]' is modifiable, as is 'b[i]', and also 'b', but the
referrent object of 'b[i][j]' is not.

    const T[const][]  c;       // Const array of array of const T
-or-
    const T const[][] c;       // Const array of array of const T

Variable 'c' is modifiable, but variable 'c[i]' is not.  However, variable
'c[i][j]' is modifiable, but its referrent object is not.

    const T[][const]  d;       // Array of const array of const T
-or-
    const T[] const[] d;       // Array of const array of const T

Variable 'd' is modifiable, as is variable 'd[i]'.  However, variable 'd[i][j]' is
not modifiable, nor is its referrent object.

    T[const][const]   e;       // Const array of const array of T
-or-
    T const[] const[] e;       // Const array of const array of T

Variable 'e' is not modifiable, nor is 'e[i]', nor it 'e[i][j]'.  However, the
referrent object of 'e[i][j]' is modifiable.

Confused yet?  Keep in mind that this is only a suggested syntax.
I don't particularly like it, but it seems to be the most efficient syntax,
and it is the same syntax as that used for const array function
parameters in C99.

(BTW, for those who have argued against using the keyword 'const', I must
point out that 'const' is already a reserved word in Java; we might as well
use it instead of inventing yet another one.)


It might be prudent to simply mandate that arrays cannot be const, and that
only the objects they refer to (their referrent objects) can be const.
If so, the examples for 'a' and 'b' utilize the only valid syntax, and the other
examples are not legal.  The drawback to such a mandate is that while we
could declare methods as returning arrays of const objects, we would not
be able to declare them as returning const arrays (which seems like a
fairly useful thing to be able to do).

Another (better) prudent approach might be to say that only whole arrays
can be const, i.e., the dimensions of an array are either all const or all
non-const.  Thus we could have syntax something like:

    const T[]            a;    // Array of const T
    T const[]            b;    // Const array of T
    const T const[]    b;    // Const array of const T

    const T[][]          d;    // Array of array of const T
    T const[][]          e;    // Const array of const array of T
    const T const[][]  f;    // Const array of const array of const T

The leading 'const' applies to the referrent objects of an array declaration,
and the 'const []...[]' modifier applies to the reference elements of the array
variable itself.


Submitted On 23-FEB-2002
hlovatt
In reply to shrink_laureate, you make two points:

1. The class hierarchy is changed, e.g. if 'X extends Y' 
   this is changed to 'X extends ConstX extends Y extends 
   ConstY'. You see this change in hierarchy as ''total 
   devastating'', whereas I see it as a trivial change.

2. You give the example of a const view array, one 
   approach is to provide a simple wrapper for the 
   existing in-built arrays, e.g.:

public final class ConstIntArray {
    private final int[] array;
    public ConstIntArray(final int[] array) {
        this.array = array;
    }
    public int get(final int index) { 
        return array[index];
    }
    public int length() { return array.length; }
    public int[] constCast() { return array; }
}

You write these const array wrappers once for each of the 
primitive types and for Object, you use them again and 
again in many different programs. In use you do something 
like:

class X {
    private final int[] array;
    ...
    ConstIntArray get() { 
        return new constIntArray(array); 
    }
}

The wrappers for arrays are simple and the overhead of 
writing them once is small, therefore I don't see a 
problem with using them. It certainly isn't true to say 
that you cannot design interfaces that use a const view of 
an array. See previous postings to this forum on more 
sophisticated array classes that offer a const view array 
and also offer performance improvements over the in-built 
array type in Java.



Submitted On 24-FEB-2002
97jaz
Is it possible to vote *against* an RFE?  This is a truly awful idea.


Submitted On 25-FEB-2002
shrink_laureate
I don't deny that it's possible to write a relatively 
simple wrapper around an array that provides const-ness.  
But it isn't an array.  All the functionality of this can 
be duplicated with extra classes and extra work, but that
isn't really a solution.  And no, i don't want operator 
overloading as a solution to that, because of all the 
messes people make with it.

> Confused yet?

Yes, which is why I don't like that syntax. Particularly 
confusing is how you describe the various forms of array. 
Tradition is not a good reason for bad design.

Perhaps we're overlooking the obvious:

(I'm going to keep saying readonly, not const, because I 
don't want people to assume C-like behaviour for it)

readonly T x;
  //  x is a read-only T
readonly T[] x;
  //  x is an array of read-only Ts
readonly array T[] x;
  //  x is a read-only array of Ts
readonly array readonly T[] x;
  //  x is a read-only array of read-only Ts


Submitted On 27-FEB-2002
naoursla
Allow transient variables to be changed in const classes.
transient variables are not really part of the class state. 
const methods need some way to cache data that is 
calculated from data in an object. C++ uses the immutable 
keyword. I thin that transient would be sufficient for Java.


Submitted On 27-FEB-2002
naoursla
Here the description of how I would like const to work:
- const is a modifier that can be applied to a reference, 
  a method, or a class.
- A non-const reference is automatically casted to a const 
  reference.
- A const reference cannot be casted to a non-const 
  reference.
- Any variables accessed through a const reference are 
  also const. 
- A transient reference is never limited by const. 
- For primitive values, const is identical to final.
- static data always receives const explictly or from the 
  class. A const refernce can be used to change non-const 
  static data.
- Only const methods can be called on a const reference.
- In a const method, "this" is const in addition to final. 
  This implies that const methods:
  - can change only transient or non-const static data in 
    a class. 
  - can only call other const methods on data members 
    (including this). 
  - cannot return a copy of a member reference as a 
    non-const reference. A copy must be made, or the 
    return value must be const. 
  - can call non-const methods on non-const parameter 
    references.
- A const class has all methods and static data defined as 
  const. Also known as an immutable class (although 
  currently this is only specified in documentation). 
  i.e. java.lang.String should be defined as a const class.
- const array references make the array and its contents 
  const. This rule is arbitrary. I imagine that one might 
  want an array of Objects where you cannot change the 
  array, but can change the object. However, I cannot 
  imagine a decent syntax to make such a distiction.
- array initializer lists are const and can be used as 
  const paramters.
- methods derived from const methods must be const.
- methods derived from non-const methods may be changed to 
const.
- classes derivied from const classes may be non-const,
  but all methods in base class are restricted to const.


Submitted On 01-MAR-2002
shrink_laureate
> 
> You are mixing up const and final...
> ...Again you are mixing up final and const...
> ...Again const and final should not mean the same thing,
> that is just very confusing.

This is why I don't want to use the word "const".  Hearing 
it, you think it must behave like final, when it 
doesn't.  "readonly" may be an extra keyword for people to 
learn, but it says exactly what it's supposed to say.

Just because C called it const, doesn't mean it's right!

The other reason is that we have to have more than one 
keyword in this scheme to handle readonly-safe methods and 
methods that return readonly references.

> No, const should be illegal for primitive types.

Agreed.  We need to separate the idea of read-only 
references from that of final values.

> const array references make the array and its contents 
> const. This rule is arbitrary. I imagine that one might 
> want an array of Objects where you cannot change the 
> array, but can change the object. However, I cannot 
> imagine a decent syntax to make such a distiction.

I can easily imagine a good syntax for it, but it isn't 
Java! Finding a way to slot this into Java will be 
difficult.

> A const class... Also known as an immutable class

Then why not call it an immutable class?

Why is it that people would rather have a syntax that's 
confusing, buggy and incapable of doing the job it's 
designed for, than just add another two or three keywords 
to the language?


Submitted On 01-MAR-2002
megagurka
> - Any variables accessed through a const reference are
also const. 

What do you mean with variables? Reference fields? Why
should they be
const just because they are accessed through a const
reference? They
should be final in the sense that you cannot change their
value, but
you can still change the value of the object they are
referencing. You
are mixing up final and const.

> - For primitive values, const is identical to final.

No, const should be illegal for primitive types. Again const and
final should not mean the same thing, that is just very
confusing.

> - static data always receives const explictly or from the 
>   class. A const refernce can be used to change non-const 
>   static data.

What do you mean with "static data always receives const
explictly"?
Static data should always be mutable through a const reference
(otherwise you can still change it through the class name),
unless
it's declared final. Exactly like today. Again you are
mixing up final
and const.

> - In a const method, "this" is const in addition to final. 
>   This implies that const methods:
>   - can change only transient or non-const static data in 
>     a class. 

What is "non-const static data"?

>   - can call non-const methods on non-const parameter 
>     references.

This applies to all methods, not just const methods.

> - A const class has all methods and static data defined as 
>   const. Also known as an immutable class (although 
>   currently this is only specified in documentation). 
>   i.e. java.lang.String should be defined as a const class.

Const classes are a bad idea, they are not needed.

> - const array references make the array and its contents 
>   const. 

No, this wouldnt be good, it's two separate things.
Sometimes you want
const array references where you can change the objects in
the array.

> - array initializer lists are const and can be used as 
>   const paramters.

??? An array initializer list just creates a new array. It
should
return a normal reference, not a const reference.


Submitted On 06-MAR-2002
hlovatt
Couldn't agree more with hwc, this proposal is a lot of 
trouble for no gain. It does not increase type safety. RFE  
4617197, Immutable types, gives reduced memory footprint 
and speed.


Submitted On 06-MAR-2002
hwc
Rather than ask why we need two or three keywords, I would
ask why would people use them.  safe, readonly and notnull
are easier to understand than the many proposed meanings of
the single keyword const but most of our methods will then
become something like

safe public readonly notnull MyObject method( final 
readonly SomeObject x )

Would most programmers bother if there weren't clear
performance and safety benefits?  Some would, but compiler
support for immutable objects offers many of the same
benefits with less effort.

C++ gets away with a single keyword because references are
implicitly final and not null.  Java references are more
like C's pointers in this respect with the same problems.


Submitted On 13-MAR-2002
megagurka
I dont agree with hwc and hlovatt. What we are discussing
here are references that cannot change the object they refer
to. That's it. We are not discussing immutable objects or
classes (like RFE 4617197). 

C++ solved this with two keywords: const and mutable. I
think it's a reasonable solution.

>> Would most programmers bother if there weren't clear
>> performance and safety benefits?  

I know I would cause the alternative is to design a special
const interface for each class which is ugly and tedious. If
you have programmed C++ you know that const is used very
often and is a great feature.


Submitted On 17-MAR-2002
ChristianHujer
Although this is not a bad idea, I am against adding this
"feature". The basic problem is that programmers do not know
the difference between identity attributes and peripheral
attributes and because of set write setters for attributes
that must not be changed.
Programmer's should learn good OO style.

Example:
public class Point {
    private double x;
    private double y;

    public Point(double x, double y) {
        setX(x);
        setY(y);
    }

    public double getX() {
        return x;
    }
    public double getY() {
        return y;
    }

    // they will cause big trouble:
    // they instead should be private or protected
    public void setX(double x) {
        this.x = x;
    }
    public void setY(double y) {
        this.y = y;
    }
}

class Rect {
    private Point lowerLeftCorner;
    private Point upperRightCorner;
    public Rect(Point lowerLeftCorner, Point upperRightCorner) {
        this.lowerLeftCorner = lowerLeftCorner;
        this.upperRightCorner = upperRightCorner;
    }
}

class TroubleMaker {
    public static void main(String[] args) {
        Point p1 = new Point(3, 4);
        Point p2 = new Point(7, 9);
        Rect r1 = new Rect(p1, p2);
        p2.setX(p2.getX() + 2); // ouch
        p2.setY(p2.getY() + 3); // ouch
        Rect r2 = new Rect(p1, p2);
    }
}

Movement of Points should instead result in construction of
a new Point, like this:
public class Point {
    // ...
    public Point move(double dx, double dy) {
        return new Point(this.x + dx, this.y + dy);
    }
}

Otherwise programmers will start cloning to be safe that
their objects keep unmodified by called methods.

And const won't solve this when used for method parameter
declarations.


My two cents.


Submitted On 19-MAR-2002
hlovatt
In reply to megagurka, contrasting this proposal with the 
immutable proposal 4617197, would you really rather write:

public final const int const[] const[] maximum(final const 
int const[] const[] other) const {...}

rather than

public final Integer[][] maximum(Integer[][] other) {...}

Note the 4617197 version will also run faster and take up 
less space.

For a proposal that only adds syntax, not functionallity, 
it is a pity that the syntax isn't better ;)


Submitted On 19-MAR-2002
hlovatt
Following on from ChristianHujer point, I have seen this 
sort of thing happen in C++. It doesn't happen in simple 
examples it happens in really conveluted ways that are hard 
to find :( . Using ChristianHujer example and assuming that 
const is allowed in Java and that Rect is declared as 
accepting const arguments. The senario I have seen is that 
the initial version of the code is:

Point p1 = new Point(3, 4);
Point p2 = new Point(7, 9);
Rect r1 = new Rect(p1, p2);
Rect r2 = new Rect(p1, p2);

This compiles and runs fine, but infact contains a subtle 
mistake. p1 and p2 should have been declared const. The 
compiler doesn't pick this up because it is OK to pass a 
non-const to Rect that is expecting a const. 

Now the trouble begins, during maintenance the above is 
changed to:

Point p1 = new Point(3, 4);
Point p2 = new Point(7, 9);
Rect r1 = new Rect(p1, p2);
p2.setX(p2.getX() + 2); // ouch
p2.setY(p2.getY() + 3); // ouch
Rect r2 = new Rect(p1, p2);

This again goes through the compiler without mistake.

Constrast this with the immutable C proposal, the initial 
mistake of forgetting the const keyword is picked up by the 
compiler because you can't pass a mutable to an immutable 
(unlike const were a non-const can be passed to a const). 
Note the syntax is also helpfull, whereas it is easy to 
forget const you are far less likely to ADD Mutable and you 
would have needed to add Mutable to the declaration of p1 
and p2 and to the declarion of the constructor Rect, all by 
mistake, highly uinlikely!

Therefore assuming that Point is an immutable type (see RFE 
4617197), the original code is unchanged:

Point p1 = new Point(3, 4);
Point p2 = new Point(7, 9);
Rect r1 = new Rect(p1, p2);
Rect r2 = new Rect(p1, p2);

Now during the code maintenance the code becomes

Point p1 = new Point(3, 4);
Point p2 = new Point(7, 9);
Rect r1 = new Rect(p1, p2);
MutablePoint p3 = p2.toMutable();
p3.setAddX(2); // now OK
p3.setAddY(3); // now OK
Rect r2 = new Rect( p1, p3.toImmutable() );

Or since Point is so quick to create, you wouldn't bother 
with a mutable form, therefore the example becomes:

Point p1 = new Point(3, 4);
Point p2 = new Point(7, 9);
Rect r1 = new Rect(p1, p2);
Point p3 = new Point(p2.getX() + 2, p2.getY() + 3);
Rect r2 = new Rect(p1, p3);

Both of which are bug free :)


Submitted On 21-MAR-2002
megagurka
hlovatt, I dont understand what you mean. There is no bug in
the following code, it does exactly what the programmer wants:

Point p1 = new Point(3, 4);
Point p2 = new Point(7, 9);
Rect r1 = new Rect(p1, p2);
p2.setX(p2.getX() + 2);
p2.setY(p2.getY() + 3);
Rect r2 = new Rect(p1, p2);

If the programmer didnt want the r1 to change when p2 is
changed, he/she would pass a copy of p2 to the Rect constructor.

Again you are talking about immutable objects. This RFE is
NOT about immutable objects. Declaring a method parameter as
const only mean that the object cannot be changed through
that parameter. It can still be changed through other
non-const references.

I'm not saying immutable objects are not useful, but it's a
different subject.


Submitted On 29-MAR-2002
andythomascramer
Hlovatt's comparison of 
    public final const int const[] const[] maximum(final 
const int const[] const[] other) const {...} 
to
    public final Integer[][] maximum(Integer[][] other) 
{...} 
relies on his proposal that all arrays containing immutable 
objects must themselves be immutable. The latter's 
simplicity thus derives from absence of choice.

Also, the latter form omits the "final" before the 
argument, necessary for equivalence with the former. But 
it's generally accepted that declaring formal 
arguments "final" is allowing the implementation to intrude 
upon the interface.

Also, the syntax for declaring array references const is 
not yet determined. It might be simply that a single const 
specifies that a reference to a multi-dimensional array 
cannot modify any member of the array, in any dimension. 
Thus, a reference of type const int[][] would point to a 2D 
array of integers, and be unable to modify the 2D array at 
all. Or more flexibility could be provided, at a cost to 
simplicity -- e.g., int [const][const]. 

Regardless, in Hlovatt's former statement, the 
first "const" before the return type and argument has no 
purpose.

Also, the trailing const on the former provides a compile-
time check not provided by the latter. Again, the 
simplicity results from less functionality.

Also, either 'Integer' in the latter does not refer to 
java.lang.Integer, or Hlovatt's proposal breaks existing 
code (because of his proposal that arrays of immutable 
objects _must_ themselves be immutable). If the former, it 
requires either an import or qualification. If the latter, 
it’s a futile proposal.

An accurate comparison, then, would be between the 
following:
    public final const int [][] maximum(const int[][] 
other) {...} 
to
    public final HLovatt.Integer[][] maximum(HLovatt.Integer
[][] other) {...} 

The former offers greater flexibility and requires 
significantly less memory.

However, an either-or battle between const-restricted 
references and immutable types is illogical. Both const-
restricted references and immutable types would be useful. 


Submitted On 29-MAR-2002
andythomascramer
David Tribble's "Comprehensive Theory" placed recently in 
the description of this RFE has a common flaw: in a few 
places, it confuses const-restricted references with 
immutable objects.

Consider, for example:
  "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."

Contrast that with:
  "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."

The former presumes that all const-restricted references 
point to immutable objects. The latter does not. (And the 
former requires run-time checks; the latter only compile-
time.)

Consider this class:
  public class MyClass {
    private const AnotherClass m_reference;
    public MyClass( const AnotherClass reference ) {
      m_reference = reference;
    }
    …
   }

Other code can create MyClass, passing it a reference to a 
mutable object, following Tribble's latter rule:

  AnotherClass ac = new AnotherClass();  // Mutable
  MyClass o = new MyClass( ac );
  ac.nonConstOperation();  // Legal

But this breaks Tribble's former rule: the member variable 
is declared const, but the object to which it points is not 
immutable.

I'd like to suggest this alternative wording:
  "Any reference variable declared 'const' is 
   restricted to 'const' operations on the object 
   to which it refers."

Read as a whole, Tribble's specification (and later remarks 
on arrays) is appropriate for this RFE, and almost perfect. 
He clearly understands the concept. 

The specification’s occasional confusion with immutable 
objects, however, is unfortunate, and likely to confuse 
other readers. I encourage Mr. Tribble to amend the 
specification, and Sun to update the description.


Submitted On 29-MAR-2002
andythomascramer
David Tribble's remarks on const-restricted references in 
arrays are wonderfully comprehensive. However, they don't 
address the similar issue of const-restriction for 
references to arrays of primitives. 

For example, a method might want to expose an internal 
array for read-only access. Without const-restricted 
references to arrays of primitives, I've found it necessary 
either to copy the array or make a fervent plea to clients 
in the method documentation. The former can harm 
performance, the latter allows error.

Using a syntax parallel to Tribble's for array references 
supporting dimension-specific const-restriction:
	public double[const] getArray() const { return 
m_myArray; }

Using a syntax parallel to Tribble's for array references 
NOT supporting dimension-specific const-restriction:
	public double const[] getArray() const { return 
m_myArray; }

(I find the former more readable for 1-dimensional arrays, 
but realize this comes with greater complexity for multi-
dimensional arrays. I would find the latter functionality 
usually sufficient.)

Both of the return types are references restricted to const 
operations on the array to which they point. They are _not_ 
references to immutable arrays.

The C++ syntax "const double[]" is not parallel to 
Tribble's suggested syntax for arrays of references to 
objects. In Tribble's "const T[]", the const specifies that 
the members themselves are const-restricted references. 
Therefore, "const double[]" should not be supported.


Submitted On 01-APR-2002
hlovatt
I think const fails this "less is more" test, but I am 
willing to be convinced otherwise. I am most definitely in 
favor of improved compile time checking (static checking). 
So give me an example of how type safety is improved with 
const, in a way that is safer than the current alternative 
of using objects, inheritance, and interfaces and is 
better/safer than using immutable types. 

I have asked for examples of why const is worth while twice 
before in this forum, on both occasions people replied with 
const arrays. On both occasions I pointed out that you can 
do them with wrappers (plus other techniques). The reply to 
the wrapper suggestion, on both occasions, was along the 
lines of instead of writing 'i = ia[0]' you now had to 
write 'i = ia.get(0)' (like you would for ArrayList) and 
that this was unacceptable to them. My own personal bias is 
that I don't point much weight on shorter syntax, I prefer 
easier to understand syntax and/or more functionality. So I 
don't think that the "'get' is too long" argument is a good 
enough argument for a language extension. Also the 
immutable proposal gives even better (both shorter and 
clearer) syntax for unchanging arrays, so this is a poor 
argument on two counts.

So please, give me a good example of were const might be 
used.


Submitted On 01-APR-2002
hlovatt
In reply to andythomascramer:

I think my original comparison is valid (but see A to D 
below), 
namely:

    public final int const[] const[] maximum(
    final int const[] const[] other) const {...} 
    
compared to using immutables as defined in RFE 4617197 
(incl. 
subsequent discussions), i.e.:

    public final Integer[][] maximum(Integer[][] other) 
{...} 

My reasoning is:

1. You suggest that the immutable form will take up more 
memory 
   (presumable because you think extra pointers will be 
needed). 
   This isn't true, immutables don't require extra 
pointers, 
   unlike const. Also, immutable execute quicker than const.

2. I was replying to megagurka who was advocating C++ like 
   syntax, hence all the const's (I will come back to this).

3. The immutable RFE 4617197 makes immutable types final as 
well 
   as making arrays of immutables themselves immutable, 
hence 
   final argument in const version.
   
4. All the const's aren't necessary, point B below, but the
   const after the method declaration is necessary. In an 
   immutable class all the methods can't change the fields 
   (they are immutable). Note this is compiler checked, 
this is
   opposite to what you said.

The areas I did cheat in are:

A. As you point out some of the syntax problems with const 
are 
   because you specify const for each dimension of an 
array; 
   but you suggest that you can't have some changeable and 
some 
   unchanging dimensions with immutables, this isn't true: 
   MutableArray<Integer[]> or a custom array class for 
example.
   
B. I did put an extra const in for an int, I have removed it
   from the above. The extra const isn't required for 
primitive 
   types but would be needed for classes or interfaces.

C. The file in which maximum is defined in requires the 
import 
    java.lang.immutable. I didn't show this because all I 
was 
    showing was the method definition.

As I have already said; I was replying to another post that 
advocated C++ style syntax, but I do agree with you that 
better 
syntax has been suggested for const references. However I 
still 
don't think const is worth adding, even with better syntax. 
When 
would you use it in preference to immutable? Hardly ever!


Submitted On 01-APR-2002
hlovatt
In reply to megagurka:

> hlovatt, I don't understand what you mean. There is no 
> bug in the following code, it does exactly what the
> programmer wants:

The code was posted as an example of a type of bug seen in 
real programs, originally given as an example by 
ChristianHujer, and therefore must be a bug (it is an 
example of one!). The mythical programmer didn't want r1 to 
change, he/she made a mistake.

The point of my posting was to say that this type of bug 
happens in real code and that const doesn't help to prevent 
this. As I said in my posting it is an example, no one is 
suggesting that in such simple code a mistake would be 
made, but in a large project when r1 and r2 are in separate 
packages let alone separate classes and files, this type of 
thing can inadvertently happen. In fact this type of bug is 
so common it is given a name, const aliasing. 
ChristianHujer expressed similar opinions in his posting, 
as have many other to this forum.

At present people are unlikely to write Rect without 
copying the point arguments in the constructor, because 
most people are aware that point might change. However if 
const exists there is the temptation to write Rect 
accepting const arguments to save the copying. This is when 
the trouble starts, because the user of Rect now has to be 
very careful to avoid const aliasing problems. There is 
nothing the writer of Rect can do to help the user of Rect 
from accidentally having a const aliasing problem. Thus far 
from decreasing bugs, I think const will increase them 
because it will encourage bad practice in the name of 
optimization. With immutable you don't get the alias 
problem and you get an even larger speed up.

What I am saying is that const isn't very useful (in fact 
it is positively harmful). Not that the compiler is 
implementing const incorrectly or that const and immutable 
are the same. I am also saying that immutable is better 
than const and that we shouldn't add const to Java 
because "less is more". (I interpret Sun's "less is more" 
phrase to mean: something has to pull its weight, it has to 
be useful in many circumstances, you don't want lots of 
things that might be used in similar circumstances, and 
there isn't a better alternative. I don't interpret "less 
is more" to mean less typing.)


Submitted On 11-APR-2002
bbringert
This proposal doesn't seem to cover the const-ness of method
parameters and return values when methods are overridden.
For example:

<pre>
public class Foo {
   public void peek(const Foothing thing) {
    ...
   } 
}

public class Bar extends Foo {
   public void peek(Foothing thing) {
     // do something nasty to thing
   } 

}

const Foothing thing = ...
Foo foo = new Bar();
foo.peek(thing);

</pre>

It seems like overriding methods must not only be as
restrictive as the overridden method when it comes to method
constness, but also regarding the constness of method
parameters (return value constness would work the other way
around I guess).



Submitted On 18-APR-2002
MatteS
We have developed a formal theory of how to construct a 
const for a Java-like language. In the language it is 
possible to declare a member variable as read-only and then 
that variable will not be able be used to change the 
transitive state of the object to which the variable 
referes. furthermore, we have also included the possibility 
to declare a variable as context which means that the 
variable will be treated as a read-only variable within 
methods invoked via read-only objects and treated as an 
ordinary references otherwise. 

The proposal has been presented both at the Formal 
Techniques for Java Programs Workshop at ECOOP 2001 in 
Budapest and at the Sixth International Conference on 
Computer Science and Informatics 2002. You may download the 
proposal from http://www.dsv.su.se/~matte/.

The proposal considers method parameters, method returns, 
local variables and member variables. It has been proved to 
keep the read-onlyness of a reference in reference 
transfers, i.e. returns, assignements and parameter 
passing. The read-only properties can be statically checked 
and thus does not impose any run-time or memory overhead, 
and, if adapted to Java, it would not require any change to 
the virtual machine.

Any comments could be useful to further improve the 
proposal. 

Thanks  
Mats Skoglund, matte@dsv.su.se


Submitted On 19-APR-2002
Ixchel
I just read through the above-mentioned paper. I have a few 
comments:
1) Overall, I like the approach. The ability to 
transitively protect data is a nice touch.
2) I think keywords "read", "write", "context", and "any" 
will not be acceptable as they are too widely used as 
method and variable names. New keywords will be needed.
2) I think that some provision needs to be made for caching 
of data within "read" methods. C++ uses 'mutable' for this. 
Simply allowing class members to be declared 'write' would 
be sufficient, I think.
3) Inheritance and overriding need to be considered. For 
instance, can I declare the methods "Thing flagellate(read 
Thing x)" and "Thing flagellate(write Thing x)" in the same 
class? One in a superclass and the other in a subclass? Can 
the second override the first?
4) The presence of the value 'null' needs to be considered. 
When can it be assigned, and to what. (Note: I'd still like 
to see a 'notnull' keyword or the equivalent in Java at 
some point).
5) I'm not sure that I understand the desirability of 
the 'any' qualifier. Wouldn't it be sufficient to use 
a 'read' qualifier, and allow an implicit cast from 
a 'write' reference to a 'read' reference?
6) Regarding backwards compatibility, what is the default 
qualifier for a variable which is not declared with one? 
How do these variables interact with the other modes?


Submitted On 19-APR-2002
Ixchel
Another question:
7) How does your proposed syntax handle more complex types, 
such as multidimensional arrays and generic types? What 
about array initializers? Presumably, one wants to be able 
to declare such entities as, for instance, a 'read' array 
which contains 'write' elements. Also, in this case, 
does 'context' in an array element refer to the mode of the 
array that contains it, or the object that contains that 
array?


Submitted On 22-APR-2002
MatteS
I shall try to answer your questions as good as I can.
2) The proposal was originally focused on class-based 
object-oriented programming languages in general and not 
just for Java. The keywords are just syntax and were chosen 
mostly for convinience. I don't have any problem with 
changing the syntax to something more acceptable. Any 
suggestion is welcome!

2, second) You are perfectly right, adding the possibility 
to declare member variables as 'write' would not be to 
hard. The reason why we didn't do it originally is also for 
convinience. A 'write' member variable could end up 
referring to the same object as a 'read' or 'context' 
member variable and thus, in order to account for that in 
the proofs, we would have to add more constraints for the 
proof system and we just didn't want to do that.

3) Inheritance is considered to some degree in our 
proposal. We simply say that the modes of a overriding 
method must be the same as the modes of the overridden. We 
have experimented with some covariance/contravariance on 
parameters and method returns but I cannot recall the exact 
outcome of those experiments so I leave that issue open for 
the moment. 
For now, this means in our proposal that the example "Thing 
flagellate(read Thing x)" and "Thing flagellate(write Thing 
x)" would not be allowed. The problem is to determine which 
method will be bound to in runtime. We do not want to bind 
a read reference to a method that takes a write formal 
parameter. This could perhaps be determined in some cases 
for a specific program. However, in the general case this 
is much harder to determine due to the dynamic binding of 
methods so we have to be conservative. Also, we do not want 
to reject older programs just because we have added a 
subclass to the inheritance hiearchy which by 
conservativness *might* by bound to.

4) We have not considered 'notnull' in our proposal.

5) The 'any' qualifier is just dynamic sugar added to our 
proposal. In our proposal a 'read' variable can contain 
only a read reference, a 'write' variable only a write 
reference and a 'context' variable contains a reference 
with the same mode as the mode of the reference used to 
invoke the method where the context variable is used. 
An 'any' variable can contain either a read reference or a 
write reference with no respect to the mode of the 
reference used to invoke the method where it is used. This, 
however, requires a dynamic check to be performed on the 
variable before it is used in order to 'cast' it to the 
right runtime mode. Other solutions are of course possible, 
e.g. throwing an exception if the variable is used 
wrongfully. The problem is that we need dynamics to 
determine this so the development of the 'any' part of the 
proposal has been postponed for the moment.

6) For backwards compatibility the default qualifier for a 
local variable, formal parameter, method return and methods 
would be 'write' and for member variables the default would 
be 'context'. With those default settings you can write 
ordinary programs without using any read-only features 
unless you need them. 

7) We have not yet considered arrays and other complex 
types at all so any suggestion is welcome. 

Mats Skoglund, matte@dsv.su.se


Submitted On 01-MAY-2002
shrink_laureate
I like the proposal MatteS. I could even live with the 
syntax, once it's been sugared up with a few defaults (ie, 
to not break or alter existing code).

However, it isn't complete without a way of marking the 
insides and outsides of arrays. (Generics are easier to 
handle). And as you can read on this page, that is a hard 
area to agree on.


Submitted On 13-MAY-2002
kinsalis
I think that this feature would be best left out of the
language as it isn't really necessary, and I think if you're
worried about things getting changed then you clone them.
Hell: I'm sure some people think it'd be nice to have inline
assembly and no checking of memory access etc, but that sort
of stuff is what things like c\c++ are good for, this is one
bug I wish I could vote DOWN (suggestion for improvement in
the bug voting scheme?), no need to hack into the java spec
to keep the c++ programmers happy: they already did that
with .net and c# :)


Submitted On 13-MAY-2002
megagurka
To say that you can achieve the same effect as this RFE by
cloning objects, you really haven't understood what this RFE
is about. Cloning is a totally different concept.


Submitted On 14-MAY-2002
shrink_laureate
This RFE really has very little to do with C++, and .NET is 
no closer to it than Java.  It's an advanced component-
oriented feature, on the road to design by contract, not a 
throwback to the bad old procedural days.


Submitted On 26-MAY-2002
manish_jethani
Yes, I've been asking for this since long.  The const 
qualifier should be added to the Java language - for all 
the reasons that everyone else has mentioned (go and search 
comp.lane.java.*).


Submitted On 11-JUL-2002
SteveCrook
It seems plain that this isn't going to happen, and for all 
the wrong reasons (though I do have some sympathy). It 
would be a huge upheaval to the current codebase and I'm 
sure that a lot of code would be broken. I remember my 
problems in C++ trying to introduce the use of const into 
an app that had ignored it. Still, for a modern language to 
not have this feature is bonkers and it does rather betray 
the languages origins. Sooner or later I suspect that Sun 
will have to bite the bullet and do this. The longer they 
leave it the more painful it will be for all of us. Just 
think of all the classes that wouldn't have been written 
yet if this had been done in the release after the RFE was 
submitted. If they can't do const and generics take 
forever, what hope is there for full DBC?
 


Submitted On 26-JUL-2002
shrink_laureate
There is no hope for DbC.  Sun clearly isn't prepared to make 
the changed needed to keep Java at the top of the pile, so 
sooner or later somebody else is going to take their place.

So far, the alternatives I see are:
 - C# on .NET is a nice language, but doesn't distinguish 
itself from the Java it copied, and also comes with too much 
political baggage.
 - Perl 6 is coming along nicely, but isn't intended to have 
the type-safety and strict correctness that makes Java what 
it is - and which read-only references and DbC will help to 
bring up to spec.

Once again, i feel in a language-writing mood. Who's with 
me?


Submitted On 28-AUG-2002
fuchssa
OOOh yea this is a glaring omission from a superb OO 
language like Java.  I'm aghast that such a useful feature 
with no side effects isn't supported.
  In my favorite C++ books they always mention "const-ness", 
and how valuable it is to laying a good code structure.
 I will go out of my way to vote for this one!


Submitted On 29-OCT-2002
davidtribble
I'd just like to point out that classes already exist in the standard
library that act like they are 'const' classes.  Perhaps the most
notable are classes 'String', 'Integer', 'Character', et al, in
package 'java.lang'.

This fact should not cause any major problems, though, if 'const' were
eventually adopted by Java.  For example, the following pairs of
methods below would be *functionally* identical, even if the compiler
treats them as *semantically* different:

    String getName() { ... }              // A1
    const String getName() { ... }        // A2

    void setName(String n) { ... }        // B1
    void setName(const String n) { ... }  // B2


Submitted On 22-NOV-2002
susomc
it would be useful add a new keyword inmutable, with the 
following functionality

You have to forbid casting an inmutable parent as a mutable 
child
but only in the case you have declared the parent as 
inmutable

I mean

inmutable class I {
protected int a;
}

class M extends I {
void modify() {
a = 5;
}
}

M m;
I i;
m = (M)i; (FORBIDEN!!!) (only in this case because i is 
declared inmutable)
i = (I)m; {ALLOWED}

The programer should be responsible of returning only 
inmutable object references from an inmutable class, even if 
this objects are mutable. You can also return copies of the 
objects.



Submitted On 02-DEC-2002
jordansamuels
The pros of this outweight the cons.  Unlike other possible 
language additions to Java borrowed from C++ or other 
languages, this feature does not seriously impact developer 
who don't wish to use the feature.  Its value to the 
developers who do wish to use it is almost immeasurable; 
others have already commented on Design by Contract.  For 
Java to be a serious, mature language it must adopt 
something of this nature.


Submitted On 11-DEC-2002
eboukobza
One should also consider 'const' feature may be trouble and 
misleading.

Take for example:

const HashMap myData = new HashMap();

Can I use myData.iterator() ?
Can I use myData.entrySet() ?

Either the response is yes and 'const' is broken since:

Iterator iter = myData.iterator();
iter.remove()

will actually modify myData... OR... myData is just about 
unusable !!!

Make it by design !!!

Eric


Submitted On 11-DEC-2002
Ixchel
CONST REFERENCES AND IMMUTABLE CLASSES ARE TWO 
COMPLETELY DIFFERENT THINGS!

I put this in all caps because there still seem to be people 
posting comments that claim that immutable classes are in 
some way replacements for being able to declare particular 
references (variables, parameters, etc.) as 'const'. If what 
you want is immutability, go look at bug #4617197, which 
deals with that subject, rather than this one.

Please don't reply to this feature request telling us how to 
create immutable objects. We know. There are lost of 
immutable objects already in Java. Java.lang.string, 
java.lang.Integer, etc. That's not what this feature request is 
for. A const reference allows A PARTICULAR USER of an 
object to guarantee that THAT USER won't change it. An 
immutable class guarantees that NO USERS of an object will 
change it once it is constructed. These are entirely different 
concepts with completely different purposes.


Submitted On 11-DEC-2002
Ixchel
In response to the recent article by eboukobza:

The way this is handled in C++ is by having 'iterator()' when 
called on a const object return a const iterator, and by 
having iterator() when called on a non-const object return a 
non-const iterator. An iterator declared 'const' iterator 
doesn't allow access to the remove() operation, while the a 
non-const iterator does. In C++, this might be declared as a 
pair of methods in the same class:
    const Iterator iterator() const { ... }
    Iterator iterator() { ... }
At compile time, the compiler will choose the correct method 
depending on whether the object the method being invoked 
on is const or not.
There are some proposals (above) for collapsing these two 
declarations into a single one by using a keyword that means, 
basically, "const-if-the-object-being-called-on-is-const, else 
non-const".


Submitted On 12-DEC-2002
eboukobza
The purpose of this RFE is to provide read-only access to an 
Object just like Collections.unmodifiableCollection() does.
Compile time decision is not always possible, especially when 
you work with interface !

Take the following example:

package a;
public class A {
  public int peek() const { ...}
  public void poke(int v) {...}
}

package a;
public interface Data {
  public A getData();
}

package b;
public class B implements Data {
  const A someData = new A();
  A getData() const { return someData; }
}

package c;
public class C {
  Data myData;

  public C(Data d) {
    myData = d;
  }

  void doSomething() {
    A data = foo.getData();
    data.poke(1);
  }
}

package c;
public class Main {
  public static void main(String[] args) {
    try {
      Data data = Class.forName(args[0]).newInstance();
      C c = new C(data);
      c.doSomething();
    } catch (Exception e) {}
  }
}

Package a is an API and is compiled alone (i.e. packages b & 
c not in classpath).
Package b is an implementation of that API (compiled with 
package a in classpath).
Package C is an application using B implementation (compiled 
with package a ONLY in classpath).

Now... What did the implementor of class B meant ?... What 
will happen when compiling/running C ?...

My point is that const alone can NOT give guaranty of 
readonly access. This IS misleading !!!

A 'const' keyword may be useful (especially for small 
applications) and will not cause much trouble as long as it is 
designed as a compiler HINT to make best effort to enforce 
readonly access. BUT... what will be the next step ?... 
Programmers will want readonly guaranry and this is only 
possible by either breaking the dynamic binding of the runtime 
or creating immutable object.

Now... Tell me want users REALLY want ?... If they want a 
compiler hint... no problem (as long as they don't ask for more 
tomorrow)... But if they want read-only access guaranty 
(which, by the way, would be a great feature)... THIS IS NOT 
THE WAY TO DO IT since you can't escape creating a stub to 
control the access (unless you want to loose dynamic 
binding).

My bottom line is that I'm tired of RFE's that go to the 
direction of loosing dynamic binding (they are way too many 
of them and a few in the top 25 RFE's). The fact that a 
feature exist in C/C++ doesn't meant it have to be in Java or, 
at least, it doesn't mean it has to be implemented the same 
way in Java. Dynamic binding is the stongest feature of Java; 
they are not too many languages out there providing it, and 
none of them can provide Java performance.

Hope I made myself clear now,
Eric


Submitted On 19-DEC-2002
M.R.Atkinson
An alternative way to get similar functionality is:

Add the following keywords to Java[1] immutable, function,
update, read and notnull; with the following semantics:


immutable
---------

This is discussed more fully in bug id=4617197.


function
--------

This is used to indicate that a method has no side effects.
All its parameters must be "immutable" classes or marked
"read", it is not allowed to modify "this", nor is it allowed
to access static variables (neither read or write to them).
All methods it calls are also to be "function".

When used in interfaces this means that classes
implementing the interface must have a "function"
method of the same signature. 

Subclasses of a class with a "function" method may override 
it but in that case it must be also a "function".


read
----

As a method marker this is used to indicate that a method
does not alter any of its parameters (or "this"), or any
object reachable from its parameters or "this". It is only
able to call methods that are "function" or "read". It may
only read or write static variables that are declared
"read"[2].

When used in interfaces this means that classes
implementing the interface must have a "function" or "read"
method of the same signature. 

Subclasses of a class with a "read" method may override it
but in that case it must be a "function" or "read" method.

As a parameter marker it indicates that the parameter (or
any object reachable from the parameter) is not modified
during the method[3]. It is redundant on parameters that
have primitive or "immutable" types. It is also redundant on
"function", "read" and "update" method parameters as they
are "read" by default, and furthermore cannot be "update".
[4]

Methods in subclasses that override (or implements a
interface containing) a method that has "read" parameters
must have the same parameters as "read". 

class, instance and local variables may be marked as "read", 
do not allowed to be update methods to be called on them.
Although if they are not declared final they may be changed 
to another instance.

Continued...


Submitted On 19-DEC-2002
M.R.Atkinson
update
------

As a method marker this is used to indicate that a method
does not alter any of its parameters, but may change "this"
(or objects reachable from "this"). The only methods it is
able to call are marked "update", "read" or "function". It
may read or write static variables.

When used in interfaces this means that classes
implementing the interface must have a "function", "read"
or "update" method of the same signature. 

Subclasses of a class with a "read" method may override it
but in that case it must be a "function", "read" or "update"
method.

As a parameter marker it indicates that the parameter may
be changed by the parameter. It is not allowed (will result
in a compile time error) on parameters that have primitive
or "immutable" types.

Methods in subclasses that override (or implements a
interface containing) a method that has "update"
parameters may alter these parameters to be unmarked or
"read". 


notnull
-------

This indicates that a parameter may not take a null value.
Parameters marked as "notnull" will throw an
IllegalArgumentException if they are passed a null value. In
many cases the compiler can detect assigning a null value
to a "notnull" parameter and will issue a compile time error.





notes
-----
[1] It would probably be necessary to add a new class of
    keywords "keyword_or_ident" to the language, and then
    distinguish whether these new keywords are keyword or
    identifier in Java source by their context.

[2] static read variables may be written to as they cannot
    be used to modify the instance. This allows output and
    logging to be used.

[3] for "function" methods this will always be true. For
    "read" and "update" methods this is only true on the
    same thread. Once a "read" parameter is written to a
    static variable it is available to be modified by a
    different thread.

[4] "Read" parameters only guarantees the contract from
    the client code point-of-view, the method cannot assume
    that a "read" parameter will remain constant over the
    lifetime of the method, the client code could modify it (or
    an object reachable from it) in annother thread. If it
    important that the parameter remain constant over the
    lifetime of the method, then the method must
    synchronize on the parameter.



Submitted On 19-DEC-2002
megagurka
> The purpose of this RFE is to provide read-only access to an
> Object just like Collections.unmodifiableCollection() does.
> Compile time decision is not always possible, especially when 
> you work with interface !

You're wrong, it's possible (Java is no different from C++
at compile time). Your example is incorrect, in class B you
have the line:

  A getData() const { return someData; }

which would generate a compiler error since you cant convert
a const reference (someData) to a non-const reference.


Submitted On 19-DEC-2002
M.R.Atkinson
Perhaps I should point out that use of function, read and
update to mark methods does almost everything a const
keyword would do, but makes it easier to indicate the
programmers intent and reason about programs. They also
potentially allow a JVM to perform extra optimisations
(especially for function methods).

function methods are ideal for implementing interfaces like
comparable. Almost all methods for Immutable classes are
also functions, although some may have to be read methods if
they access static fields. update methods are used for mutators.

All three make the jonathanfinn noted problem with 

   static void add(Matrix a, const Matrix b) {...}

impossible.

They also solve the nasty syntax required for arrays, they
also work for interfaces, generics, primitives, immutables.

The one problem they don't resolve is one that has not been
brought up on this list. Reference type parameters that are
reachable by annother thread are liable to change during the
execution of a method (even if it is marked function, read
or update). Defensive programming could synchronise on each
such parameter, but this is error prone an may lead to
deadlocks. Lightweight immutable types, like primitives
cannot be synchronized on (as they may be pass-by-value).


Submitted On 23-DEC-2002
eboukobza
> > The purpose of this RFE is to provide read-only access to 
an
> > Object just like Collections.unmodifiableCollection() does.
> > Compile time decision is not always possible, especially 
when 
> > you work with interface !
> 
> You're wrong, it's possible (Java is no different from C++
> at compile time). Your example is incorrect, in class B you
> have the line:
> 
>   A getData() const { return someData; }
> 
> which would generate a compiler error since you cant 
convert
> a const reference (someData) to a non-const reference.
> 

The example did NOT convert to a non-const reference. You 
can read the line above as:

  const A getData() { return someData; }

I was just using the syntax used by the writer of the RFE.

Anyway... By trying to argue on a stupid example, you are 
just showing how much my main point is right ;)

People... If you want read only guarantee just ASK FOR IT... 
not for some kind of implementation like this... The people 
responsible for Java in Sun already proved they are able to 
provide features in the best possible way (and no... I'm not a 
Sun employee).

By asking for loosy implementation of features you're just 
killing the language !

I wish I could VOTE AGAINST this RFE and alikes.

Eric


Submitted On 09-JAN-2003
andylarder
Creeping featurism???? The lack of const has got to be the 
most brain-dead part of Java apart from the lack of operator 
overloading. Get them sorted!

Oh well, I'm sure MS .NET will support const soon anyway ;-)


Submitted On 13-JAN-2003
MartinHilpert
why not making it more easy and interpret the final keyword 
so that not (only) the reference variable is final but also the 
referenced object, i.e. the object's state  can't be changed. 
same effect as "const" but doesn't introduce a new keyword 
that is effectivaly the same as the already well known "final" 
keyword.


Submitted On 13-JAN-2003
pervel
MarintHilpert, that would be a very bad idea as it would break 
a lot of existing code relying on the current semantics of final.


Submitted On 17-JAN-2003
megagurka
>> You're wrong, it's possible (Java is no different from C++
>> at compile time). Your example is incorrect, in class B you
>> have the line:
>> 
>>   A getData() const { return someData; }
>> 
>> which would generate a compiler error since you cant convert
>> a const reference (someData) to a non-const reference.
>> 

> The example did NOT convert to a non-const reference. You 
> can read the line above as:
> 
> const A getData() { return someData; }
> 
> I was just using the syntax used by the writer of the RFE.

No, it's not the same thing.

A getData() const ...

  means that the method can't change the object pointed to
by 'this',
  'this' is a read only reference.

const A getData() ...

  means that you return a read-only reference to an object
of type A.

> People... If you want read only guarantee just ASK FOR IT... 

What do you mean with read only guarantee? This RFE is about
read only references, not read only objects. I think it
would be a valuable addition to Java.


Submitted On 28-JAN-2003
keithkml
personally I don't want this. I never liked that
functionality in C++, as it just cluttered method signatures
and I never really cared about it anyway. let's all use
immutable view objects!


Submitted On 09-FEB-2003
dnoyeB
Reiterating my negative feelings toward this unnecessary
idea.  This would take work away from interfaces.  Currently
what the poster is requesting is exactly what interfaces are
for.  What he really wants appears to be automatic inferred
creation of an interface that only allows access to
non-modifying methods.

By the time you get finished marking all your methods with
the const moniker, you could have created the necessary
interface.  exact_same_result.

Again someone please explain why this is not achieveable
with interfaces or why its better with the const moniker??


Submitted On 24-FEB-2003
dkf
If there was just a way to say "this array does not permit 
assignment" that'd be good enough.  Well, good enough for 
me.  Others might prefer massive const poisoning of the API, 
but it scares me the more I think about it...


Submitted On 25-FEB-2003
Anjum
How about using these keywords (idempotent and immutable):

public class A
{
   // This method can change the state of this object
   public void doSomething()
   {
   }

   // This method is guarenteed NOT to change the state of 
this object
   public idempotent int doSomethingElse()
   {
   }
}

public class B
{
   // Using the immutable keyword guarantess to the caller 
that "stuff" will not be changed
   public void doStuff(immutable C stuff)
   {
      stuff.doSomething(...);   // <---- Compiler error!!!!
      stuff = new C();          // <---- OK
      stuff.doSomethingElse();  // <---- OK
   }

   public doStuff2(final immutable C stuff)
   {
      stuff.doSomething(...);   // <---- Compiler error!!!!
      stuff = new C();          // <---- Compiler error!!!!
      stuff.doSomethingElse();  // <---- OK
   }
}


Submitted On 11-MAR-2003
megagurka
> Again someone please explain why this is not achieveable
> with interfaces or why its better with the const moniker??

Two reasons:

- It's more work to do it with interfaces.

- Having an interface with "read only" methods doesn't
guarantee that the implementation doesn't change it's
internal state when these methods are called. With a const
equivalent, the compiler can detect this and produce an error.


Submitted On 11-MAR-2003
megagurka
> If there was just a way to say "this array does not permit 
> assignment" that'd be good enough.  Well, good enough for 
> me. 

Why don't you just wrap the array in a class? You shouldn't
pass arrays around in a program, use ArrayList's or
something better.

> How about using these keywords (idempotent and immutable):

You also need a 'mutable' keyword for fields that can be
changed in an idempotent method.


Submitted On 12-MAR-2003
hlovatt
In reply to Megagurka.

I think you are mistaken in a number of areas with your 
arguments.


1. Const is not necessarily less work than a const interface, 
for example:

1a. A const interface to a multidimensional array may be very 
much simpler than a const keyword (e.g. C++).

1b. New syntax is something everyone has to learn whether 
they use it or not (because other people will use it). 
Therefore the total work for everyone may well be higher.

1c. You end up with double methods, a const and non-const 
version (see 2 below).


2. The compiler cannot give the protection you ask for (it can 
give no more protection than a const interface), e.g.:

void method1() const {
     SomeOtherClass.method2( this );
}

Is method1 const or not, it depends on method2.

EG:

void method2( Object o ) {
     NonConstType nco = (NonConstType) o;
     nco.changeConst();
}

Clearly you wouldn't do this deliberately but it may happen by 
mistake and the compiler can't help. This is the same as 
assigning to a void* in C++, the C++ compiler can't stop this.

Another example, should this be banned:

constObject.toString();

You can't call toString because it isn't const! If toString is 
declared const in Object all current code is broken that 
declares its own toString and legitemete uses of say counting 
the numer of calls to toString aren't allowed. What happens in 
C++ is that almost all methods end up occuring twice, once 
with a const signature and once without and you have to 
overload both!


3. Const and const interfaces introduce a false sense of 
security and make programs difficult to debug. Experience 
from C++ tells us that const will be used as an optimization 
instead of making a clone and then there will be problems 
when the value changes (the well documented const aliasing 
problem in C++).



A better alternative is immutable types, see:

http://developer.java.sun.com/developer/bugParade/bugs/461
7197.html


Submitted On 17-MAR-2003
megagurka
hlovatt, I'll respond to your arguments although you seem to
be repeating them over and over. Also, a const keyword is
not a replacement for immutable types, and vice versa.

> 1a. A const interface to a multidimensional array may be very 
> much simpler than a const keyword (e.g. C++).

Can you give an example?

> 1b. New syntax is something everyone has to learn whether 
> they use it or not (because other people will use it). 
> Therefore the total work for everyone may well be higher.

It would require some learning, yes. But the alternative
today is that almost noone uses const interfaces. Just look
at the collections library for example. Immutable containers
use the same interface as mutable. That stinks!

> 1c. You end up with double methods, a const and non-const 
> version (see 2 below).

No. In that case your design is bad.

> 2. The compiler cannot give the protection you ask for (it
can 
> give no more protection than a const interface), e.g.:

The compiler cannot protect against stupid casts (unless you
remove the possibility to cast to non-const), but it can
protect against code like this:

class Test {
  private int x;

  public int getX() const {
    x = 4;   // <-- Compiler error
    return x;
  }
}

This is something that wouldn't be detected using const
interfaces.

> You can't call toString because it isn't const! If
toString is 
> declared const in Object all current code is broken that 
> declares its own toString 

toString() should clearly be a const method from the
beginning of Java. Changing it to a const method today
would, as you say, break existing code. I don't know any
solution to this problem.

> and legitemete uses of say counting 
> the numer of calls to toString aren't allowed. 

Sure it would. I don't know if you are familiar with C++ (it
doesn't seem so), but there is a keyword called mutable that
takes care of this case.

> What happens in 
> C++ is that almost all methods end up occuring twice, once 
> with a const signature and once without and you have to 
> overload both!

??? I've almost never implemented the same method twice in
C++ (with the exception of some reference counting classes),
and I always use const where I see fit.

> 3. Const and const interfaces introduce a false sense of 
> security and make programs difficult to debug. 

So, you are saying we shouldn't have any protection
mechanisms because they "introduce a false sense of security
and make programs difficult to debug"? What a stupid
argument. Introducing const in Java does not protect against
stupid programmers, it protects against good programmers
making small mistakes that will be detected by the compiler.

> Experience from C++ tells us that const will be used as an 
> optimization instead of making a clone and then there will be 
> problems when the value changes 
> (the well documented const aliasing problem in C++).

Const is not about protected the object from changes, it's
about protecting from changes through a specific reference.
You should always be prepared that the object can change,
unless it's an immutable object. As I said before, immutable
objects and const references are not the same thing. They
are both useful.


Submitted On 17-MAR-2003
hlovatt
Megagurka, here is an example that shows using interfaces to 
be simpler and clearer than a const keyword. 1st const 
version assuming C++ like const.

public class Matrix {
    private int[][] values = new int[ 3 ][ 3 ];
    public Matrix( ... ) { ... }
    public Matrix add( final const Matrix left,
       final const Matrix right ) const { ... }
    public void set( final int r, final int c,
                      final int value ) const {
        values[ r ][ c ] = value;
    }
    public void get( final int r, 
                          final int c ) const {
        return values[ r ][ c ];
    }
    public void copy( 
               final const Matrix out ) const {
        for ( int r = 0; ... )
            for ( int c = 0; ... )
                out.values[ r ][ c ] = 
                              values[ r ][ c ];
    }
    public const Matrix max( 
              final const Matrix that ) const {
        if ( ... ) return this;
        else return that;
    }
    public Matrix max( final Matrix that ) {
        if ( ... ) return this;
        else return that;
    }
}

Notes:

0. Only add and get are cleanly expressed using const, for 
the other methods const is just baggage. I would say 
misleading baggage since you don't instantly think that a 
const method changes the this reference. It isn't that const 
isn't doing what it should do, it is, the point is that const isn't 
very useful!

1. Values isn't really constant inside a const method since the 
content can change in a const array, i.e. no syntax for 
methods to specify that values is of type 'const int const[] 
const[]' where 'const int const[] const[]' means that 
elements of values as well as values are const. See set.

2. Same goes for arguments to methods, they aren't really 
const. See copy, from its signature which way does it copy, 
to this or from this? The compiler is of no help!

3. The example shows mutations of an array object, but any 
object will behave the same. Const is useful in procedural 
languages but looses its usefulness in OO because of this 
feature. Final has the same unfortunate consequences in 
Java, most people find final objects that change state 
confusing.


Submitted On 17-MAR-2003
hlovatt
4. The max method is a common example of needing a double 
function, const and non-const. Joshua Block has stated that 
experience with the C++ STL and similar led him to eliminate 
const and non-const forms in the interfaces for Collections 
because of this bloat.

Now lets look at the interface version.

public class ConstMatrix {
    protected int[][] values = new int[3][3];
    public ConstMatrix( ... ) { ... }
    public Matrix add( final ConstMatrix left,
              final ConstMatrix right ) { ... }
    public void get(final int r, final int c) {
        return values[ r ][ c ];
    }
    public void copy( final ConstMatrix out ) {
        for ( int r = 0; ... )
            for ( int c = 0; ... )
                out.values[ r ][ c ] = 
                              values[ r ][ c ];
    }
    public ConstMatrix max( 
                     final ConstMatrix that ) {
        if ( ... ) return this;
        else return that;
    }
}
public class Matrix extends ConstMatrix {
    public Matrix( ... ) { super( ... ); }
    public void set( final int r, final int c,
                            final int value ) {
        values[ r ][ c ] = value;
    }
    public Matrix max( final Matrix that ) {
        if ( ... ) return this;
        else return that;
    }
}

This interface version is clearer because it groups together 
methods that don't change the matrix, whereas the const 
marker is positively misleading! They have about the same 
type safety and yet the interface version doesn't break old 
code, doesn't require any extensions, and can be done today!

You mention that the above pattern for const isn't common. 
It is fairly common in one form, when the non-const class is 
kept package private, e.g. BigDecimal. The reason for this is 
that const isn't that useful in OO, except as an optimisation 
for an immutable. One of the big drawbacks of the const 
keyword proposal is that it doesn't support this common 
usage of keeping the mutable form private!

Plus the previously mentioned problems with class Object and 
any other base class.

So I have given an example that clearly shown there are 
down sides to const and almost no advantages, can you think 
of an example that really must use const and couldn't use the 
above pattern and/or an immutable?


Submitted On 20-MAR-2003
jordansamuels
This is not creeping featurism.  It's a crucial element in 
industrial-strength software design.


Submitted On 23-MAR-2003
hlovatt
jordansamuels; but we can already do const references, see 
post immediately above yours :). Do you have a counter 
example?


Submitted On 25-MAR-2003
brettw1
You people are all on crack.  If you want to be protected
from yourselves, pick another language.  I have worked on
several large scale java projects over the past few years,
and inadvertantly modifying object states in methods is not
a that occurs often enough for a language feature.  In fact,
of the thousands of bugs I have probably fixed over these
projects, that particular one might have happened twice.  Go
bloat somebody else's language, or go back to C++.  Or
should we throw in templates, operator overloading, and
multiple-inheritance, as well?


Submitted On 28-MAR-2003
tzervos
I do agree with brettw1's remarks: "Go
bloat somebody else's language, or go back to C++.  Or
should we throw in templates, operator overloading, and
multiple-inheritance, as well?". 
Simple things make life easier. If your developers write bad code try to enforce good-code-practices or show them how to write better code!
I also agree with guill's remarks: "It`s a lot simpler to understand someone else code in Java language that in C++, thanks to the confusing 
features that don't exist in Java.".


Submitted On 31-MAR-2003
megagurka
to hlovatt:

I still think a const keyword is better and simpler than
const interfaces, but I agree with you that it will be a
hell of a lot of work to add it to the Java language today
(and it will break a lot of existing code). It should have
been there from day one. Adding it today is probably not
worth it.

brettw1 writes:
> You people are all on crack

No, I prefer coke :-)

> Or should we throw in templates, 

No, but generic types are desperately needed (and coming soon).

> operator overloading, and

No. Operator overloading makes the code harder to read, and
the benefit is small.

> multiple-inheritance, as well?

Multiple inheritance is not needed when you have interfaces.


Submitted On 31-MAR-2003
hlovatt
Megagurka, most of the proposals put forward in the forum 
have been minor variations on the C++ theme; perhaps 
different keywords, for example. They don't tend to address 
issues of practicality or really even address where const 
might be used.

I am *** against *** the following proposal, but a method I 
did think of for const before proposing immutable types 
(4617197) is given below. I am posting the proposal now so 
that it might spark some discussion other than simply re-
hashing C++'s concept of const.


Proposal
========

0. Use const where you would currently use final for 
variables, fields, and arguments. const would behave like final 
currently does except it could not be applied to methods or 
classes to mean cannot be overridden.

1. If final is used for anything other than cannot override then 
issue a depreciated warning.

2. Allow const as a qualifier to a class to mean that all its 
methods are to treat all fields (even those declared higher up 
the class heirarchy) as though they were declared const 
(final). Note this does not mean that methods cannot be 
overridden and it does not mean that its fields are really 
const (final). It means that when in one of its methods the 
fields are treated as though they were declared const (final). 
Like other class qualifiers the const class qualifier is not 
inherited by sub classes. For an example, see "For" point 3 
below.

3. Make all fields etc. which are of a type that has the const 
qualifier themselves automatically const (final). EG the 
keyword const in "const ConstMatrix cm = ...;" is redundant, 
but not an error, because ConstMatrix is a class that is 
already qualified with const. Also see point 6 below. 
Note "const Matrix x" and "ConstMatrix x" are different (they 
are of different types), however they both share the 
characteristic that "x" cannot be assigned to.

4. The return type of a method may not be qualified with 
const. The programmer probably means to return a const 
class, e.g. ConstMatrix, therefore flag this as an error. Also it 
is an error in Java to have the returned object from a method 
on the left hand side of = and therefore a const qualified 
return type has no meaning.

5. Modify RTTI for new const qualifier. In particular, class 
Modifier to have field CONST and method isConst. These are 
simply aliases for existing field FINAL and existing method 
isFinal. Also class Class needs a new method isConst that 
returns true when a class is declared const.

6. A minor modification to the JVM is necessary, namely an 
extra tag bit is needed to mark the class as const. The const 
qualifier on variables etc. behaves like final currently does. 
The const qualifier to a class is only enforced by the compiler 
not by the JVM. The compiler is responsible for marking 
variables of a type that is a const class as const (final).

7. You can't mark an interface as const. It doesn't make 
sense, const is an implementation detail and anyway it isn't 
inherited by derived types. All fields in an interface are 
automatically static and const (final), i.e. no change from 
status quo.


Submitted On 31-MAR-2003
hlovatt
For
===
Plus points for this proposal are that:

0. It elevates confusion over final having two meanings

1. Doesn't break existing code

2. Provides C++ like level of protection; better is some ways, 
worse in others

3. Similar amount of typing to C++, e.g.:

public abstract const class ConstMatrix {
    protected int[][] values = new int[ 3 ][ 3 ];
    public ConstMatrix add( ConstMatrix left,
                      ConstMatrix right ) { ... }
    public void get(const int r, const int c) {
        return values[ r ][ c ];
    }
    public void copy( ConstMatrix out ) {
        for ( int r = 0; ... )
            for ( int c = 0; ... )
                out.values[ r ][ c ] = 
                                values[ r ][ c ];
    }
    public ConstMatrix max( ConstMatrix that ) {
        if ( ... ) return this;
        else return that;
    }
}
public class Matrix extends ConstMatrix {
    public Matrix( ... ) { ... }
    public void set( const int r, const int c,
                            const int value ) {
        values[ r ][ c ] = value;
    }
    public Matrix max( const Matrix that ) {
        if ( ... ) return this;
        else return that;
    }
}

4. Splits a class into 2 classes so that access control and 
own constructors can be given to both const and non-const 
forms. Alternatively, as shown, a C++ like version were const 
form is just a reduced interface of non-const form is possible. 
Note const form that behave like C++ are "abstract const", as 
in above example.


Against
=======
The argument against is that "less is more", i.e.:

0. The uses for const references are limited in OO, see point 
1 below.

1.  It is generally better to use immutable types instead. On 
the rare occasions that a const reference is really needed 
just use a hand coded const interface.

2. The distinction between "const Matrix" and "ConstMatrix" is 
too subtle to be useful, it is just confusing.


Summary
=======
Don't do it. Instead do:

http://developer.java.sun.com/developer/bugParade/bugs/461
7197.html


Submitted On 30-APR-2003
pmurray
You need a another constraint: a const parameter may not 
be passed as a non-const parameter to another method. Or 
thrown as an exception. Or assigned to a non-const member 
variable.

Otherwise I can give my const parameter to myself by 
passing it to a method. Or by wrapping the const in an 
exception class and throwing it to myself.


Submitted On 30-APR-2003
hlovatt
Reply to pmurray.

When you pass a field to a method it passes a copy, so within 
the limitations of the protection provided by const (final) this 
hasn't broken the type checking. But I agree that the 
behaviour isn't very useful, hence I favour immutables. The 
passing to methods and passing to exceptions are yet more 
examples of the const aliasing problem that is well known in 
C++. People who are strong advocates of const don't see this 
as a problem, see discussions in this forum, but for me this 
limitation makes const marginally useful at best.


Submitted On 17-MAY-2003
tektoon
I vote against! The whole 'const' concept is a pain. When you really start thinking about it, you need several concepts of 'read-only-ness', for several clients/users of 'your' class, for which 'const' doesn't help you at all.
That's why C++ needs a 'feature' to actually cast const away! Adding 'const' is a bad idea!


Submitted On 21-MAY-2003
michaelkopp
I actually lost track about what is discussed here.
C++ does not have the best solution for const correctness 
but java has none. I do not consider the proposal to actually 
have to code an imutable object or an read-only interface a 
solution for that.

So stop to bully around how bad C++ const is.

The main problem is how do you make sure that an object 
given to a method is not modified in that method. there is no 
compiler check what so ever. 

What if the object is thrid-party? i do not want to write 
wrappers for all of my third party objects.

Now here comes the real interessting part. what if the 
method is third party? How do I make sure that the third 
party method does not modify my object.

None of the 2 is possible in java without copying the object 
(what a performance nag) or hand coding it.
I aggree that the 2nd example is not possible in C++ either 
(methods can be const, but const_cast and mutable are 
breaking that) and that therefor the C++ solution is not good 
enough.

Never the less I'd like to see a solution for this problems.
- Compiler Check to make sure that a method marked 
as 'readonly' does not modify any members (which does 
include methods called in that method)
- Compiler Check that parameters/fields/variables marked 
as 'readonly / imutable' are not modified.

These two points also need runtime checking.

We all know that this would be a major effort, but frankly 
speaking it should have been there from the start.


Submitted On 28-MAY-2003
bhaskarn
Yes. Please implement this. The collection classes in
java.util are particularly in need of this. Generally they
must throw runtime exceptions when an "immutable" collection
is modified. This makes for very fragile implementations
where runtime tests must be used in place of compile time
checks.


Submitted On 28-MAY-2003
jesusla
Please, implement this much needed feature in Java. Hacks
such as Collections.unmodifiable<Container> should have
never existed in the first place but instead implemented
using const and non-const methods.
Granted, the effort to upgrade all the existing JRE classes
to const-awareness is huge, and not until it is complete
will this const feature yield its fruits, but it's definitely worth
it.


Submitted On 30-MAY-2003
dakokes
I would like very much for this to be done. One thing I'd
like to mention, and I apologize if it had already been said
in one of the comments, is that  if you are going to have
you will need a 'mutable' keyword, similar to C++, to mark
class members which const methods can change without
violating constness. They are members which are not
considered part of the object's 'externally visible' state,
or more precisely members that the object's abstract state
does not depend on. It is necessary, if const methods and
references are to be useful, to have this ability. One
common use case is for caching, where in an accessor you use
an instance variable to cache the result of a complex
computation. Calling the accessor may necessitate an
assignment to this variable, but it doesn't really change
the object so the accessor should still be declared const.
Allowing this instance variable to be declared as "mutable"
will allow this, whereas without it you would get a compile
error.


Submitted On 29-JUN-2003
hlovatt
People may not have picked up on this, but the variance 
proposal adds read-only arrays to Java. Read-only arrays 
seem from the discussions in this forum to be the most 
common requirement of people who like const references.

See:

http://developer.java.sun.com/developer/bugParade/bugs/485
6545.html

With this proposal you would write:

T[+] readOnlyArrayOfTsOrSubTypesOfT;
T[-] writeOnlyArrayOfTsOrSuperTypesOfT;
T[=] readWriteArrayOfOnlyTsNotSuperOrSubTypes;
T[] existingArrayThatMayThrowAnArrayStoreException;


Submitted On 07-JUL-2003
barbyware
It is possible add Conditional compilation (like C)


Submitted On 14-JUL-2003
cpell
I'm with brettw1 and tzervos on this.  If you feel like Java
needs const, it's because you haven't yet learned how to
program Java in such a way that you don't need const.

Many programmers seem to fall under the impression that once
the method signature and body are written, they are done. 
This is not the case in OO design.  Every public class and
public method requires a contract.  If you don't provide a
contract you haven't finished programming the method or class.

If I want to write a method that is guaranteed to never
modify its argument, I say so in its contract (that is, its
javadoc).  If you want to be sure my method won't modify
your object, read the javadoc.

I can only guess that this concept was overlooked because,
traditionally, programmers have hated adding documentation.
 I'm guilty of it too.  But in an OO world, documentation is
much more important than it ever was in C or C++.  It
doesn't just explain things, it defines things.

What I see in the comments here is that many people want
"const" so the compiler can do the work of a contract.  It
would be nice to have strong checking for immutable objects,
but the comments make it clear (to me, at least) that the
complexity of adding "const" far outweighs the benefit. 
Contracts in the form of javadoc are much clearer to me,
while the amount of additional work needed to fully support
"const" seems daunting.

I think most of the proponents of "const" are looking for a
programming shortcut.  I think we can do it with the tools
already provided, and I think we should.  I'm sorry that
writing wrapper classes and full javadoc is work, but OO
often is that way:  a lot of early work saves a huge amount
of work later.


Submitted On 13-AUG-2003
dkf
I agree with cpell on the point of "contracts" for classes, 
objects and methods.  Taking the time to develop them and 
making sure you stick to them saves your bacon, time and 
time again.  (Mind you, this isn't a feature of OO design.  It's 
a feature of all high-quality programming.  OO doesn't make it 
suddenly become a requirement; you should have been doing 
it all along.)


Submitted On 27-AUG-2003
cyberguide
The const feature is the hottest one i was always wondering 
about, why it has not made it into the language in the first 
place.
Another cool feature in Java would be to allow for operator 
overloading and for this one, there is already a working 
implementation to be found with the JUMP compiler (don't 
know the address anymore).

Hope const will be a feature for the next version after Java 
Tiger (1.5). I really do!


Submitted On 14-SEP-2003
gbishop
I see no value in this.  I vote against it.


Submitted On 17-SEP-2003
jessh
cpell and dkf are full of it here.

Textually described contracts are all well and good -- and 
downright necessary in most cases, but unless/until the 
compiler knows about them and enforces them for you they 
don't replace 'const' at all.

The entire point of 'const' is to express more intent in a form 
that the compiler can understand and enforce -- thereby 
forcing at least a portion of the contract (beyond arg, return, 
and throws types) to be obeyed at compile time vs. runtime.

C++ may have screwy syntax due to pointers and references 
here, but at least one can express this aspect of contracts 
and have it statically enforced at compile time.

[On the flip side, someone argued for operator overloading.  
This is a straightforward recipe to code that can only be 
maintained by its author as there is no realistic way to 
prevent someone in a sizable team from using this feature in 
such a way that no one else can follow the code -- the 
opportunities for accidental obfuscation are endless!  
Operator overloading is really cool IF (and only if) you're the 
one writing *all* of the code.]


Submitted On 12-DEC-2003
carstenklein1
No need for that one, really.

Please do consider implementing well defined interfaces,
perhaps even incorporating dynamic proxies.

I presume that it would be too much of a problem of
implementing this into the VM or even the Java APIs.

Immutable and Mutable interfaces are good.

Consider that in C++ you are always like forced to use the
const cast operator to cast away constness on many occasions.

Therefore I don't believe that this proposal would do any
good to the language, as it did to C++.





Submitted On 25-FEB-2004
Niklas_Bergh
> Immutable and Mutable interfaces are good.

Indeed, but how can the compiler enforce that they so are?
First after that is possible then I think this request could
be closed.


Submitted On 08-MAR-2004
hlovatt
I have written a compiler available for download that
includes immutables and mutables that are compiler enforced
(in addition to other features). It uses the concept of a
marker interface to identify an immutable (see RFE 4617197).

It is a free download from:

pec.dev.java.net

Under the Lesser GNU Public Licence. 

Let me know what you think.


Submitted On 09-MAR-2004
JoeSB
I vote for it.

I think it improve Design By Contract for java.

Just becasue it's not in java the first day, doesn't mean 
it should be in java after all.

If you vote against this one, then would you vote that 
putting 'final' keyword on method parameter and on 
member variable be removed?
Because using 'final' in those two way really give you 
not much benefit. You can check by yourself that you 
didn't reassign the value to a variable.

The point is that, the check is done by compiler. And it 
does what you expected.

I have seen places in javadoc that say "This return the 
internal data, without copy, for perfromance. So Don't 
modify the returned value" Why do we need this 
comment at all? are we asking for const here?

Now that java 1.5 is here and there is annotation. I 
think we should have @const as some compiler & 
runtime attribute.


Submitted On 16-MAY-2004
mdernst
The paper "A practical type system and language for reference
immutability" makes a concrete proposal regarding "const" in the
context of Java, and provides experience with a prototype
implementation.  The paper will appear in OOPSLA 2004, and
comments on
the proposal or the paper are welcome.  The abstract appears
below,
and you can find the paper itself at:

http://pag.csail.mit.edu/~mernst/pubs/ref-immutability-oopsla2004-abstract.html


A practical type system and language for reference immutability
Adrian Birka and Michael D. Ernst
To appear in OOPSLA 2004

This paper describes a type system that is capable of
expressing and
enforcing immutability constraints.  The specific constraint
expressed is that the abstract state of the object to which an
immutable reference refers cannot be modified using that
reference.
The abstract state is (part of) the transitively reachable
state:
that is, the state of the object and all state reachable
from it by
following references.  The type system permits explicitly
excluding
fields or objects from the abstract state of an object.  For a
statically type-safe language, the type system guarantees
reference
immutability.  If the language is extended with downcasts, then
run-time checks enforce the reference immutability constraints.

In order to better understand the usability and efficacy of
the type
system, we have implemented an extension to Java, called Javari,
that includes all the features of our type system.  Javari is
interoperable with Java and existing JVMs.  It can be viewed
as a
proposal for the semantics of the Java "const" keyword, though
Javari's syntax uses "readonly" instead.  This paper
describes the
design and implementation of Javari, including the type-checking
rules for the language.  This paper also discusses
experience with
160,000 lines of Javari code.  Javari was easy to use and
provided a
number of benefits, including detecting errors in
well-tested code.


Submitted On 08-JUL-2004
JessHolle
Actually JoeSB's idea of using 1.5's annotations via an @const or some such seems quite interesting.

In general providing additional design-by-contract features via annotations and compiler warnings and/or errors based on these annotations seems promising.  The annotation processor could default to these being warnings, but these could be boosted to errors for clean, new code areas in large projects.  Moreover, static analyzers could look at the annotations in the resulting class files and allow one to audit violations, mark known violations (or violations against certain packages) as "ignore", and alert one to new violations.

Overall, this would allow a "strict as you need it" approach -- assuming core libraries like rt.jar were well annotated for design-by-constract concerns like constness.


Submitted On 08-JUL-2004
David Silver
I consider this a misguided attempt to turn Java into C++.   
After six years of programming in C++, coming to Java 
(back in 1998) was a relief.  Finally , a language where the
 other programmers on my team didn't have a loaded gun 
pointed at *my* foot (let alone the bloody stumps they were 
hobbling around on).  It wasn't just the safety afforded by 
Java's memory model.  It was also the fact that my code 
was now immune to shoddy, non-const correct code.

class Shoddy
{
    private int x;
    public int getX()     // NOT const-correct
    { return x; }
}

class UsesShoddy
{
    private Shoddy shoddy;
    public int getY() const    // Now I'm in const-correctness hell.
    { return shoddy.getX(); } // ERROR: getX() is not const.
}

The solution in C++ is an ugly const_cast<> of this.  
According to supporters of this RFE, however, we should
never need to cast away const or declare fields mutable.
In that case, the only solution is to not use the 
non-const-correct class, or rewrite it.  Got some old code
that isn't const correct?  Re-write it.  Only got the class
files?  Tough luck.  

The point I want to make is that const correctness is an
all-or-nothing affair.  (Particularly if you want to be autocratic
about disallowing const casts.)  If you want to be 
const-correct, you'd better hope that everybody else is too.

Honestly, this RFE has the hallmarks of a deliberate attempt
to sabotage the language.  It  won't be getting my vote.  
I really wish that  votes could be cast against RFEs, as well 
as for them, because despite the number of votes for this, I 
wonder if they are a true indication of how the community 
feels about this.  Sun: take note.


Submitted On 08-JUL-2004
JessHolle
Despite previous comments on my part in favor of this RFE, I do have to agree with David Silver on one point: in C++ const-awareness/safety *is* an all or nothing affair -- at least from the point of core, etc, libraries on up.  In general, a given body of code effectively cannot use const unless all the libraries it directly depends on make proper use thereof.

This means that this RFE would require at least the level of backwards and cross-library compatibility design work that went into 1.5's generics.  Without such finely finessed solutions as we now see in 1.5 generics, this RFE *would* be harmful.

In essense, if this can't be done right then the cure is worse than the disease....


Submitted On 22-AUG-2004
hlovatt
musheno, see the Immutable pattern here:

https://pec.dev.java.net/nonav/compile/index.html

For how you might  enforce immutability with a compiler. You can also vote for Immutable types in Java here:

http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4617197


Submitted On 22-AUG-2004
musheno
If I am not mistaken, that would be impossable, as a subclass would be free to override that piece of functionality, plus, to allow non mutability you could only send cloned objects, but there is no way to ensure this, as the compiler would have to process the entire call chain, and what happens when the framework I rely upon changes, My code will not compile, or wolnt run? Plus how will the compiler "Ensure" the method is non mutable (including any delagated mutations)?


Submitted On 07-SEP-2004
171110
The last official evaluation is from 1999 - 5 years ago. It's #2 RFE, couldn't Sun provide an updated evaluation with more detail?


Submitted On 15-SEP-2004
NiclasH
I totally agree with David Silver's post on 2004-July-08.
Although it 'seems' like a good idea at first, it is a very nasty feature that really screws up for others when misused.


Submitted On 17-SEP-2004
Quartz
I agree that this would be one more featurism for the language.  I'm already cautious about the static imports AND autoboxing (however, I like the idea of generics and full-fledged enums).  There are quite a few compilers that can help you with that, if you so desire (google JML).  Anotations might help some time in the future.  As soon as people figure out how to make them work with the new instrumentation layer...


Submitted On 30-SEP-2004
aldo_g
I agree partially resolve this using 1.5 annotations, for parameters and methods, and let the compliler check
posible violations


Submitted On 03-OCT-2004
herohero3
i'm agree that it is a great enhancement but plx think about these :

1) For these C, C++ developer PLX study the the usage of "final" key word clearly b4 air ur opinion here. cuz  "final" can do most of the stuff that "const" can.

2) Const parameters: no pass by reference in java. do we need const parameters?

3)Also we can do something like this:
void function(final Object Foo){}

4) u can use the immutable design pattern


Submitted On 03-OCT-2004
herohero3
i read some of ur opinion is just want to eliminiated the cloning of array so why not just adding a "readonly" key word for array of all diminension just like that of c#


Submitted On 12-OCT-2004
muminc
One vote from me. This is one feature that I really miss from c++ 


Submitted On 15-OCT-2004
jaubourg
(my apologies for the possible english mistakes to come: english is not my mother tongue... thanks)

I find the reactions against a const modifier quite stunning.

But, surely, it


Submitted On 15-OCT-2004
jaubourg
(too big a post? I'll split)

I find the reactions against a const modifier quite stunning.

But, surely, it's Sun's answer that puzzles me the most:
"One can design around this (using interfaces, wrappers etc.)"

Really? And to what extend?

Let's take a simple example (and with generics, why not?):

public interface Setter<T> {

     public void set(T value);
}

public interface Getter<T> {

     public T get();
}

public interface Container<T> extends Setter<T>, Getter<T> {    
}

All right, so we have our interfaces. Let's get to the implementation:

public class DefaultContainer<T> implements Container<T> {

     private T object = null;

     public void set(T value) { object = value; }

     public T get() { return object; }
}

Since we wanna be able to enforce immutability, we need a wrapper:

public final class ImmutabilityWrapper<T> implements Getter<T> {

     private final Container<T> container;

     public ImmutabilityWrapper(Container<T> c) { container=c; }

     public T get() { return container.get(); }
}


Submitted On 15-OCT-2004
jaubourg
Here, so everytime I wanna ensure immutability, I wrap my Container in an
ImmutabilityWrapper and my problems are handled, right?

NO WAY!

For instance, let me code a completely stupid subclass of DefaultContainer:

public class StupidContainer<T> extends DefaultContainer<T> {

     public T get() { set(null); return null; }
}

Hmmm... What's going on?

Now an ImmutabilityWrapper that wraps a Container is not guaranteed to prevent changes
made to the internals of the Container because we have created a new subclass that breaks
the tacit contract.

TACIT: That's the problem. Take a look at the JDK javadoc and count the number of methods
for which the doc specifically states which methods will be called on every single parameter
and on the object itself (because you realize that's the only way you can know what behavior
to expect out of the call): of course, none.

Beside, the documentation has no value when it comes to compile-time checks, so what would
be the point?

Believe me, breaking a tacit contract happens more often than one would desire, especially
in big projects with lots of people involved, and it is definitly not always as obvious
as the StupidContainer example.

So back to our problem. How can we prevent this?

1) "Let's make DefaultContainer final!"
   cool, what prevents me from directly implementing Container?

2) "Screw this interface, let's make an abstract class"
   I can still subclass it and redefine its methods

3) "All right, so let's make the method final... or even the class: done!"
   Sure, now that you don't have interfaces, how will you provide an immutability wrapper?

4) "Bah! through another class, of course!"
   What if I want to have another kind of immutable getter? I can't subclass since
   get is final now.

You can toy around all you want, there are only two ways to GUARANTEE immutability:

1) scraping inheritance altogether: you provide only final classes (or classes with
   critical methods being final) and you forget about interfaces. Good bye Mr.OO Design.
   Let's be honest, you CAN do without interfaces... just use reflexivity. Hello Mr.
   Cumbersome Code.

2) you clone every single object you pass as a parameter and don't want changed, before
   every single call. Hello Mr.Garbage Collector.

Sure, nice workarounds.

And please note I didn't take a complicated example. There are much more intricated situations
where there are strictly NO workaround.


Submitted On 15-OCT-2004
jaubourg
I generally stay away from this kind of "philosophical" discussions. You know: people want
something that looks like a feature from another language. Other people say they're fanboys
of the given language, that java is better that way, that the earth is flat and so on and so
on.

I've been programming in Java for a good ammount of time now and I had been programming with
C, C++ and Ada before. I won't list Java's strengths in regard to other languages: suffise
to say it has quite a lot, at least enough for it to be my programming language of choice
(and I'm not alone, am I?).

However, this very RFE raises some interesting questions concerning Sun's policy regarding
Java's future. Since Day 1 is the lack of expressiveness in method contracts the obviously
weakest point in all of the language specification. This is really no news... and I am
NOT saying the situation is better in such or such language, I'm just saying we have a
LACK here.

Where are we at now? We have annotations (which require quite intricated reflection API
calls for runtime management) and we have generics (which current implementation, as far
as I'm concerned, given the warning noise level and lack of RTTI, is nothing more than a
proof of concept).

I will make the best use I can out of all these new constructs because I believe they enhance
the language. However, it saddens me that adding const correctness in Java is officially
regarded by Sun as "creaping featurism". Contract specification is unavoidable if and when
one works on a huge code base. If we can load classes at runtime unknown at compile time,
in a flexible OO world where subclassing (and more specifically, implementing) is the design
of choice, then we DO NEED const correctness ensured or else the state of the program can
go havoc with no way for the developper to work against it preemptively.

The workarounds currently used do not avoid the issue, they just give coders the illusion the
problem is solved, leading to more difficulties when the program's behavior becomes erratic for
no apparent reason.

So, please, tell us this is not a priority from your point of view but don't pretend this is
not a problem.


Submitted On 25-OCT-2004
hlovatt
jaubourg,

See the Immutable pattern here:

https://pec.dev.java.net/nonav/compile/index.html

For how you might  enforce immutability with a compiler. 
This compiler is a free download under LGPL.

You can also vote for Immutable types in Java here:

http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4617197

Both the above links show how immutability can be 
enforced and solve the problem you posted.


Submitted On 24-NOV-2004
hwc
I support hlovatt's proposal but there's still the question of how to make better use of existing code.

Perhaps we can start with const methods.  There could be a @pure annotation, checked by the compiler, to indicate that a method does not modify the object.  Such a method could only be overridden by another @pure method.

Then we have const references, marked @const.  No methods can be called through a @const variable unless they are marked @pure.  Similarly, elements of a @const array cannot be modified.

Then we have const classes.  This suggests another annotation, @immutable, indicating that public member variables are not only final but also @const, and that all public methods are (implicitly or explicitly) @pure.  This attribute could (and should?) be applied to classes such as java.lang.String.

Finally we have immutable values which behave like primitives: never null, no ==, not synchronised etc.  This seems a stronger guarantee than annotations can provide, hence the need for a new compiler like hlovatt's PEC, but perhaps const annotations are a useful step from current Java.


Submitted On 30-NOV-2004
hlovatt
You can do everything needed for const and more already 
(no language extension is necessary or desirable), e.g.

abstract class ConstInteger {
    abstract int getValue();
    abstract ConstInteger instanceOfSelf( int value );
    ConstInteger add( final ConstInteger rhs ) {
        return instanceOfSelf( getValue() + rhs.getValue() );
    }
}

final class ImmutableInteger extends ConstInteger {
    final int value;
    ImmutableInteger( final int value ) {
        this.value = value;
    }
    int getValue() { return value; }
    ConstInteger instanceOfSelf( final int value ) {
        return new ImmutableInteger( value );
    }
}

class ValueInteger extends ConstInteger {
    int value;
    ValueInteger( final int value ) {
        this.value = value;
    }
    int getValue() { return value; }
    ConstInteger instanceOfSelf( final int value ) {
        return new ValueInteger( value );
    }
    void set( final int value ) {
        this.value = value;
    }
}

The above pattern is better than const in many ways, 
including catching casting away of const on 
ImmutableInteger and allowing individual visability control 
(e.g. package access for ValueInteger).

The advantage of the PEC is that it checks that the 
immutable integer really is immutable, see

https://pec.dev.java.net/nonav/compile/javadoc/pec/compile/immutable/Immutable.html

for details of  writting this example using the PEC.

If  a JVM understood immutable, RFE 4617197, then it 
would be able to do some optirmizations, as described by 
hwc above, that are not possible with const.

So in conclusion I don't think that const is either necessary
or desirable, instead of refactoring old code by adding 
const or writing new code with const, refactor/write using 
the above pattern instead. If you want to ensure that you
have used the pattern correctly, use the PEC.


Submitted On 13-DEC-2004
gbishop
This is not a featureism, it


Submitted On 13-DEC-2004
gbishop
This is not a featureism, it's a way to strengthen a contract when programming.  No reason not to do it.


Submitted On 20-DEC-2004
hlovatt
gbishop,

Except that existing mechanisms are already superior :) See post immediately above yours!


Submitted On 03-JAN-2005
Laie_Techie
gbishop, that would break the class hierchy!  We would either need two separate trees (one for mutable, one for readonly) or multiple inheritance.

Besides, I believe the mutable class should inherit from the read-only one:

public class Integer
{
     public int getValue();
}

public class MutableInteger extends Integer
{
    public void setValue( in newValue );
}


Submitted On 03-JAN-2005
Laie_Techie
Here


Submitted On 04-JAN-2005
wwk_killer
Heh, looks like time to close this RFE -- at least until all 779 people will not evaluate third-party solution: 

Submitted On 08-MAR-2004 
hlovatt 
I have written a compiler available for download that
includes immutables and mutables that are compiler enforced (in addition to other features). 
http://pec.dev.java.net
Let me know what you think.

I will NEVER support this RFE. Or even regard as lawful.


Submitted On 04-JAN-2005
ray
And on and on it goes, making the case for Sun to free Java or developers to look elsewhere (if they haven't already).  I was, as an employee of a major licensee, asking for const before Java was at version 1.0.  This particular request was filed 6 years ago.  And Sun has never seriously considered it or some better way to solve the problem.


Submitted On 21-JAN-2005
nevgeniev
I can't understand any objection regarding const. The immutable interfaces are completely different story.

Just imagine how fast and slim swing could be if it does not clone tons of objects on every getter... 


Submitted On 27-JAN-2005
hlovatt
Are but you would have to clone. Just because your view of an object is constant doesn't mean that someone elses view is constant and the object can't change. This is the source of the const aliasing bugs in C++. The only way to avoid copying is to have immutability a const reference is not sufficient.


Submitted On 30-JAN-2005
Ixchel
I don't know how many times this has been said in this forum, but it seems that it has been ignored by certain people every time that it has been said, so I'll say it again in capitals in the hopes that, maybe, just perhaps it will finally sink in:

IMMUTABILITY AND CONST CORRECTNESS ARE TWO COMPLETELY DIFFERENT FEATURES WITH DIFFERENT INTENDED USES, WHICH SOLVE DIFFERENT PROBLEMS.

I am a big fan of immutable objects. I use them a lot in my coding. I would be thrilled if the Java language included explicit support for them. However, even if it did, I would still want enforced const-correctness AS WELL.

Immutability is not a substitute for const-correctness. In the cases where true const-correctness is desired, the only way to make immutability do the job is to make an immutable copy of every object that you want to protect from modification from even a single client.

Basically, the difference is as follows:

An Immutable object cannot be modified BY ANYBODY once it is constructed.

A const-correct object cannot be modified BY CERTAIN CLIENTS, namely those which have been handed only a 'const' reference to the object. However, other clients (those with non-const references to the object) can still modify it. This is not a bug -- it's a feature. It allows the programmer to restrict modifications to the object to only a few, carefully controlled locations, while allowing many locations to get 'read-only' access to those modifications.

These two features are NOT the same. Having support for immutable objects would not fulfill most of the needs that are making people ask for the 'const' keyword, as it is defined in C++. There are some limited forms of the 'const' keyword that can be simulated via Java interfaces, but other forms (such as arrays containing const elements) simply cannot be done in Java without wrapping the entire object in a holder class.  Even the interface tricks will only work if you have the ability to modify the code of the object in question to add interfaces to it, which you certainly can't do for classes such as the JDK libraries.

The name 'const' is a bit deceptive, because it implies 'constant', and that's not what this keyword actually means. What it really means is "readonly". Immutability does not provide for readonly objects -- it only provides for truly constant ones. Thus, it is not the subject of this particular Request For Enhancement. If immutability is what you want, then RFE 4617197 will probably meet your needs. However, as should be clear from the examples given in the description, THIS RFE (which is currently at the #2 position in the most-requested language features) is for C++-style 'const', not immutability.

I would be quite happy to see both the immutability RFE and the const RFE make it into the Java language. However, they are not even close to being the same thing, and neither one can fully substitute for the other.


Submitted On 01-FEB-2005
hlovatt
Ixchel,

Yes const references and immutability are different, however if you have immutability then you don't need const references. In particular:

1. const references are often abused and used as though they are immutables leading to bugs

2. Your example of having an section of code that can change a value and a section of code that can only view the value is better accomplished using an immutable with a companion mutable (value semantics class). Change the mutable and then make an immutable version of it. See:

https://pec.dev.java.net/nonav/compile/javadoc/pec/compile/immutable/ImmutableValueConversions.html

The advantage of using an immutable instead of a const view is that it is thread safe, e.g. in GUIs and database applications.

3. The const reference functionality you want is provided by an interface, see:

https://pec.dev.java.net/nonav/compile/javadoc/pec/compile/immutable/Immutable.html

Particularly the section beginning "A typical development cycle". However I would recommend using it, see points 1 and 2 above.

4. Immutables can be used for arrays, see:

https://pec.dev.java.net/nonav/compile/javadoc/pec/compile/immutable/ImmutableArrayList.html


Submitted On 14-FEB-2005
maxgilead
"Yes const references and immutability are different, however if you have immutability then you don't need const references."
If you don't care about memory overhead of creating possibly thousands of object all the time, yes, they can be used instead. But then, we can write special wrappers, so immutables are also not needed as well? This is not about what is possible or what is not, it's about making programmer more effective and your applications more bug-free and efficient.

"1. const references are often abused and used as though they are immutables leading to bugs"
Are you proposing to remove all language features which can be misunderstood by some groups of people?

"2. Your example of having an section of code that can change a value and a section of code that can only view the value is better accomplished using an immutable with a companion mutable"
See above. Programmer efficiency, application efficiency.

"3. The const reference functionality you want is provided by an interface, see: https://pec.dev.java.net/nonav/compile/javadoc/pec/compile/immutable/Immutable.html"
With all due respect, that code is terrible, bloated and presents a method which can solve only limited range of problems.

"4. Immutables can be used for arrays"
That's irrelevant.


Submitted On 14-FEB-2005
hlovatt
In reply to maxgilead ,

I think you are missing the point, the case when the overhead of object creation is too high is a rare case and can be covered with a const interface. The common cases are best covered using immutables and therefore it is better to add immutables instead of const references.

For example immutables have far fewer bad uses than const references, so why add something  (const references) that are going to get abused when we can add something that is superior instead.


Submitted On 27-FEB-2005
musheno
This is a bad idea!
Reason: if you were to impose "constantness" on a method, or variable it would cease to be mutable.
if it is not mutable, whats wrong with a final method, and have done with it.
If you are looking for a way to encapsulate a procedure, there are better ways of doing that to.
So, it cant be:
1: dont modify. (if it is use final)
2: dont modify, but do another procedure (use a procedure object, this may need work in jdk).
3: Dont modify, but allow instances to do a differant procedure (if this is the case see 2, note: base class should be non mutable).
So what do we have left? To implement this the thing must be either modifyable (ignores the whole point), or without any design scemantics (which is bad form anyway).
as there are plenty of workarounds, I say we drop this.
Todd_Musheno@yahoo.com
PS: feel free to publish, or send me mail reguarding this topic.


Submitted On 02-MAR-2005
martinr2
Doesn't a "const" keyword scheme obstruct any "lazy evaluation" pattern?

I mean:
Imagine you have a method that does _not_ change the _observable_state_ of an object, but actually _does_ change the internal state, e.g. by performing some costly computations and storing the result in some internal  variable(s). Next time it's called, it doesn't perform the computation any more, but just returns the result.

It seems you can't declare the method "const" then, although it would be desirable, because the observable state is unchanged.
Am I getting something wrong?


Submitted On 03-MAR-2005
AlexLamSL
IMHO, the proposed "const" keyword would:

-bring about more inefficiencies if implemented for run-time

-leads to "Const pollution" as mentioned even if it is only implemented for compile-time

-is not a general enough "security" policy anyway so it is not worth all the trouble mentioned above

I hope others would agree with me - I can put up some examples as well if any of you like~


Submitted On 14-MAR-2005
sjasja
> Doesn't a "const" keyword scheme obstruct
> any "lazy evaluation" pattern?

Yes. String.hashCode() is a simple example. Making it
"const" (which it presumably would need to be) would
be a nasty slap in the face of the principle that interface
and implementation should be separate.

If a method is best implemented by modifying object state,
it should not be visible in the interface.


Submitted On 19-MAR-2005
Agile.Logic
The arguments presented against this feature in the evaluation are extremely weak.

Re: Creeping featurism - some would call this the evolution and enhancement of the language. This is subjective opinion only. Which features are allowed to creep and which aren't?

Re: Too late now - this is just a subjective opinion, and not backed by any fact. Why is it 


Submitted On 20-MAR-2005
landrain
> The arguments presented against this feature in the evaluation are extremely weak.

I agree. Within a few months/years, they will wonder why people move to the Nice programming language.


Submitted On 21-MAR-2005
megagurka
> Doesn't a 


Submitted On 21-MAR-2005
megagurka
> Doesn't a "const" keyword scheme obstruct any "lazy evaluation" pattern?

No. You add a new keyword (in C++ it's called 'mutable') which you use to indicate that a class field can be modified from a 'const' method, and that this field is not really part of the object state but only a performance enhancement. Of course you only use this keyword for caching etc.


Submitted On 21-MAR-2005
megagurka
> Yes. String.hashCode() is a simple example. Making it
> "const" (which it presumably would need to be) would
> be a nasty slap in the face of the principle that interface
> and implementation should be separate.

Wrong. Object.hashCode() is typical example of a method that would be declared as 'const'. Calling this method shall NOT modify object state. If String.hashCode() caches the result, it should do so in fields marked with 'mutable'.


Submitted On 21-MAR-2005
AlmogJava
I think its great that this RFE is canceled! Good for you Sun for showing some backbone and not giving in to idiocy and pressure from the clueless masses!
The whole 


Submitted On 21-MAR-2005
fbottin
It's too late now? That's great to hear that Sun, but this RFE is SIX YEARS OLD!
Who is late then?


Submitted On 21-MAR-2005
dmbdmb
Wow, closing this issue is a really bad decision. It makes validating program correctness so much more difficult and error prone. Boo on you.


Submitted On 21-MAR-2005
cdandoy
With 787 votes, this RFE was second in the Top 25 list and it has been in the top 3 for years.


Submitted On 24-MAR-2005
sjasja
> You add a new keyword (in C++ it's called 'mutable')

Talk about a slippery slope. Kludge on top of kludge, all for the fear that somewhere there are hordes of programmers that keep accidentally modifying objects.

(Are there? I've been coding most of my life, and I can't recall ever accidentally modifying an object, or seeing someone else have an accidental modification bug. Is there a particular programming style that leads to that being such a common bug?)

If you want C++, you know where to find it. Not every language has to be C++ by another name.


Submitted On 27-MAY-2005
gkbuck
I'm glad Sun rejected this.  It might have been workable had it been part of Java since day-one, but it's too late to shoehorn a solution into the language at this point.  Besides, as others have pointed out, there are several ways to design around the need for it.


Submitted On 31-JUL-2005
benegiamo
Is incredible that Sun close this RFE. It's, actually, the 2nd of RFEs (also if closed...).

Reading the thread seems that instead to enhancing the language to allow better development, someone don't want break the toy and others don't want resemble too much to other existing languages.

A language is useful if developers can use it efficiently to solve problems, when a language don't help developers it must be corrected. And this issue don't help developers!

Loosing more than 6 years in a so important topic is a big error (also if the RFE was still open). And alternatives are worst: immutable classes are much more complicated that a simple keyword.

The "community contribution" don't seems to be listened too much by Sun this time.

P.S. Of course this is an extra "post-mortem" vote for this RFE.


Submitted On 15-OCT-2005
gbishop
I object.

sjasja is incorrect.  It is quite common for novice developers (in my case IBM Global Services to the tune of $4M) to develop code that passes in, say a String[], whose 1st member is null if there are no errors upon return (a-la C).  The String[] gets populated as a side effect of calling a method instead of throwing a normal exception.

Once this has been done there is no way to fix it.  Even marking the parameter as final does not help, because it is a member of the array that is being changed, not the array itself.

Yes, of course it is poor coding style.  Unfortunately it is now 12,000,000 lines and 400 files of ENTERPRISE CODE portions of which will be used for DECADES with no way to find the problems or fix them short of examining every single method.

I for one don't like reading hundreds of 2000 line methods written by novices who have very strange ideas about what "normal" coding style is.

What we need is a keyword like const or and enhanced final that marks this method and all methods descending from it for a compile-time check so that objects within it cannot be modified.

xxxxx@xxxxx  2005-03-01 22:19:57 GMT is wrong.  Const (I prefer enhanced final) need not result in code "pollution".  I want to mark the parameters, not the methods.  Also with regard to compatibility with no code-pollution, thisalso is not a problem.  Ditto for hashCode and the Collection classes.  I think this shows remarkable lack of vision.


Submitted On 13-JUN-2007
Sjasja, it would seem you've never programmed in an environment with lots of programmers. If you do not like this addition, you do not have to use it, if it is, hopefully, someday added to Java. The fact that Java should be simpler and more intuitive than C++ does not bury the fact that it should include some of it's advantages.
Furthermore, it is at the very least illogical not to expand the language with new capabilities.


Submitted On 30-JUL-2007
Mark_McKay
const correctness is an excellent safety feature.  Java should support it either via a const keywork or something equivilent


Submitted On 29-MAR-2008
AndrewMedico
Add my vote for const references. Letting the compiler verify contracts by checking const-correctness is a good thing.


Submitted On 18-SEP-2008
stianr
This is also a post-mortem vote for this feature. I don't think closing this shows any "backbone" as stated previously, but instead shows a total lack of understanding of the amount of control you need when you have lots of programmers (novices) and millions of lines of code that has to work properly. Having readonly parameters and methods is very powerful, and designing around the problem is _not_ a solution (you can't have core objects of the java api inherit your const interfaces can you).
Saying "I've never changed an object by mistake" is showing that the problem is not understood clearly. The problem is not that YOU change your object by mistake, but that those who wrote the class you use do so (and they intended to, but forgot to tell you).
Having a const/readonly or whatever in the parameter decleration (in C++) tells the user that the object is not supposed to be changed (which is not a big information). On the other hand, the lack of "const" states very clearly that "watch out, I WILL change your object here, so if you don't want to make a copy". The latter in my opinion is a very important piece of information when you're using ancient code written by someone not accessible, and with a sourcecode which is not inheritly understandable (sounds familiar?)...

Here's to hoping this issue will be re-opened someday and this feature added to Java (I mean there ARE a couple of good things in C++, and const is one of them).



PLEASE NOTE: JDK6 is formerly known as Project Mustang