[java] final vs const

Started by
13 comments, last by Son of Cain 17 years, 1 month ago
In C++, you very often see parameters marked const, while in Java code you almost never see final parameters. I can't remember whether this is something that can even be done, so forgive me if you can't. I wonder why, when there is such an uproar over const-correctness, why my Java text, for instance, makes no use of final parameters, even for parameters that are little more than flags. for instance:

// C++
void foo( const int& x )
{
    // blah blah
}

// Java, the way it's always shown
public void foo( int x )
{
    // blah blah
}

In Java all variables are passed by reference, no? So you'd think it would be used extensively?
Eric Richards
Advertisement
I don't think final has much to do with const. AFAICT it only prevents reassignment, a bit like a const pointer (not pointer to const). Java has no way of marking member functions as const either, so unless you use public variables there wouldn't be much you could do if you could get a true const java object...

// what I think java final references are like in c++int var, other;// /I *think* this is the syntaxint * const x = &var;x = &other; // illegal// in java land:class help {	help(){ val = 42; }	public int val;	public static void main( String [] args )       {           final help h =  new help();	   whatever(h);       }	public void modify()	{           val += 17;	}    public static void whatever( final help param )    {	System.out.println(param);        // allowed call mutating methods	param.modify();        // allowed mutate directly	param.val = 17;         // this would cause an error	//param = new help();    }}


I use references to const and pointers to const all the time in c++, so much so that I use the term "const pointer" for them which technically means a const pointee. I almost never use const pointees...
C# and .NET do not have const marking for methods either. This is an intentional feature removal for a few reasons, 1. Because it puts a serious burden on class writters to be const correct, so it wouldn't be appropriate for VB types. 2. Const correctness is all or nothing, once any aspect of your framework is enforcing const-correct behavior, all of it must be const-correct to be usefull (If any of you remember the transition from non-const correct to const-correct in C++ I'm sure you remember how hard it was when you started marking things const, but then couldn't invoke non-const methods without using const_cast). 3. It is incredibly hard to make correct const decisions for class heirarchy functions / interface methods ... sure you know what your class is today, but what about after you add features tommorow. What about some other classes that also want to use your interface and do other "side-effect" things that your interfacei itself doesn't require (nor prohibit).

This is 1 of 2 fundamental features removed from Java / C# that I don't agree with (as in I don't think it allows the language to truely be appropriate for everything), but I do understand the logic behind it (its actually slightly similar to why C# didn't implement exception specifiers / checked exceptions). Basically, if the user is going to be allowed to "const_cast", why make them have const in the first place. And if they are not going to be allowed to const_cast, then they are in for a lot more work and trouble wedding code from multiple vendors (read, mission impossible).
As mentioned, const and final do different things. Const is (generally) much more useful, but also more tedious to maintain and get right. In java an immutable interface is often used to provide an alternative to const (eg. an ImmutablePoint interface with getX() and getY() but no corresponding set() methods, which a Point class implements). This gets you most of the benifits with only a little more typing (some might argue that making the const interface explicit is more useful too).

Garbage collection also removes some typical uses of const - in Java it's often easier to return a copy of an object rather than trying to mark it as unmodifyable in some other way.

I find 'final' is generally useful for method params and local primatives where it catches accidental reassignment. Member variables marked as final are also useful - they can (and must) be only set in the constructor, so in there you validate your input params and set up your object. From then on all other methods can be safe knowing that no other method has reassigned or nulled out important objects that it needs to work.

IMHO final is something of an aquired taste in Java. Non-const-correct C++ code is frustrating and can be very error prone, but Java code written without final tends to be pretty much the same (although you might catch a few bugs a bit earlier).
Quote:Original post by Megaman_22
In Java all variables are passed by reference, no?


Hi,

in Java all variables are passed by value! :)
The tricky thing is that the "reference call"
works copying the reference itself... so that's why
we should call this by value.

That way the changes on the parameter are also visible
on the argument of the method call because the two
references are pointing out the same istance in the heap!


Quote:Original post by Clawer
Quote:Original post by Megaman_22
In Java all variables are passed by reference, no?


Hi,

in Java all variables are passed by value! :)
The tricky thing is that the "reference call"
works copying the reference itself... so that's why
we should call this by value.

That way the changes on the parameter are also visible
on the argument of the method call because the two
references are pointing out the same istance in the heap!


I think you are being a little silly. ALL values passed in all CPUs are put there "by value" in the sense you are saying ... the only way to put something on the stack or in a register is to "copy" it there. But the term call-by-value, means that the thing put on the stack or register is the actual value to be manipulated, while the term call-by-reference means that the thing put in the stack / register is an address to the thing to manipulate.

In Java, all non-primative objects ARE passed by reference in the normal sense of the word ... or they are reference objects passed by value (which is semantically equivelent by definition).
Your vision is more straightforward and that's the most important thing!

Anyway, to be honest, I think you can find what I said on every Java beginning book. On the Deitel & Deitel Java Beginning that was explicitly declared; I don't remember an equivalent thing on the D&D C++ Beginning. That's why I figured out what I wrote!

Quote:Original post by Xai
In Java, all non-primative objects ARE passed by reference in the normal sense of the word ... or they are reference objects passed by value (which is semantically equivelent by definition).

It is most certainly NOT equivalent. A call-by-reference language propagates changes to the arguments themselves, whereas a call-by-value language only allows this through reference variables (such as, in Java, non-primitive types). The acid test of whether a language is call-by-value or call-by-reference:

void swap(int a, int b){    int temp=a;    a=b;    b=temp;}int i=1;int j=2;swap(i, j);if(i==1) print("call-by-value"); else print("call-by-reference");

(Change "int" to "Object" if you like; there's no difference.)
Its not totally correct to say that Java is call by value. Call by value to me means that a object or a C struct gets copied onto the stack, not just a pointer but all of its variables as well. This isn't the case in Java - if you call a mutator on the object that was passed to you it will be reflected by the calling program. So "call by reference" means something different in Java than in C++, but I would still say that it more correct to say it was call by reference than call by value. Ironically, it works exactly like when you pass pointer to function in C or C++. If you reassign the pointer itself in the function it doesn't change anything outside of it. But since there are no pointers in Java, you have to call it something else. I guess you could think of it as "call by link"
Quote:Original post by SunDog
Its not totally correct to say that Java is call by value.

It's absolutely correct to say that.

Quote:
Call by value to me means that a object or a C struct gets copied onto the stack, not just a pointer but all of its variables as well.

Call by value means that the value of the expression given as the actual parameter is copied into the formal parameter. That's exactly what Java does.

Call by reference means that the formal parameter is an alias to the variable given as the actual parameter. This is impossible in Java, since there is no such thing as a reference to a variable in Java, only pointers to objects, which in Java are called references, although calling a method on a null "reference" yields a null POINTER exception. Funny, isn't it? :)

Quote:
This isn't the case in Java - if you call a mutator on the object that was passed to you it will be reflected by the calling program.

You don't pass objects. It's impossible for a variable in Java to store an object. Variables only hold "references" to objects.

Quote:
Ironically, it works exactly like when you pass pointer to function in C or C++.

That's exactly what happens.

Quote:
But since there are no pointers in Java, you have to call it something else.

There are: pointers are called references in Java. (But you can't do pointer arithmetic on them.)

Java is call by value.

This topic is closed to new replies.

Advertisement