Sign in to follow this  
Megaman_22

[java] final vs const

Recommended Posts

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?

Share this post


Link to post
Share on other sites
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 syntax
int * 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...

Share this post


Link to post
Share on other sites
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).

Share this post


Link to post
Share on other sites
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).

Share this post


Link to post
Share on other sites
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!


Share this post


Link to post
Share on other sites
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).

Share this post


Link to post
Share on other sites
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!

Share this post


Link to post
Share on other sites
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.)

Share this post


Link to post
Share on other sites
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"

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
I think we're playing a semantics game here. You could say that it is always "call by value". But you have to qualify that by saying that "objects can only be accessed through references". In other words, when an assignment takes place, the object is not copied but the reference to the object is. To copy an object requires explicity invocation of a clone() function or a copy constuctor. Consider the following code

class Test {

class MyClass {
public int x;
}

void someFunc(int a, MyClass b) {
a = 1;
b.x = 1;
}

public static void main(String argv[]) {

int a = 2;
MyClass b = new MyClass();
b.x = 2;
someFunc(a, b);

System.out.println(a + " " + b.x);
}
}

In a call-by-value passing (like say C), it should print "2 2" and not "2 1" as it does in Java. The object B does not get copied onto the stack, but the function receives a reference to the object. Since the terminology of the Java language is such that pointers to objects are called "references". I think it is not incorrect to say that its pass-by-reference. From someone who comes from a C++ this may seem wrong, but different languages define things in different ways and there is no standard to say that something is "wrong" because a language defines it in a slightly different way.

Share this post


Link to post
Share on other sites
Quote:
Original post by SunDog
You could say that it is always "call by value".

Let's see what the language specification has to say:

Quote:
The Java Language Specification, Third Edition, page 211
When the method or constructor is invoked (§15.12), the values of the actual argument expressions initialize newly created parameter variables, each of the declared Type, before execution of the body of the method or constructor.

There you have it, black on white.

Quote:
Original post by SunDog
But you have to qualify that by saying that "objects can only be accessed through references".

Quote:
The Java Language Specification, Third Edition, pages 44/45
There are three kinds of reference types: class types (§8), interface types (§9), and array types (§10). [...]
An object is a class instance or an array.
The reference values (often just references) are pointers to these objects, and a special null reference, which refers to no object.


Quote:
Original post by SunDog
In other words, when an assignment takes place, the object is not copied but the reference to the object is. [...] Consider the following code

Quote:
The Java Language Specification, Third Edition, page 46
If two variables contain references to the same object, the state of the object can be modified using one variable's reference to the object, and then the altered state can be observed through the reference in the other variable.


Quote:
Original post by SunDog
void someFunc(int a, MyClass b) {
a = 1;
b.x = 1;
}

In a call-by-value passing (like say C), it should print "2 2" and not "2 1" as it does in Java.

That has nothing to do with call by value. The difference is that "MyClass b" is an object in C, whereas it is a reference to an object in Java.

Quote:
Original post by SunDog
I think it is not incorrect to say that its pass-by-reference.

It is incorrect. If it were pass-by-reference, you could assign a different object to b in someFunc, and this would have to have a side effect on the caller (which is not the case, thus it is not pass-by-reference).

With the line b.x = 1; your are not changing b, because the identity of the object is preserved. b still points to the same object. Consider this:


MyClass x = new MyClass();
MyClass y = x;
x.changeState();
assert x == y;
MyClass x = new MyClass();
assert x != y;

Share this post


Link to post
Share on other sites
Technically, you are right, the 'value of the reference' is whats passed. I guess my point was, that if you took say a freshman CS student who had just learned C++, then introduced them to Java, if all of what you said was 'Java is call by value', then they would probably expect it to behave like it does in C++. You *can't* pass anything to the function other than the reference to the object 'Value of the object' has no meaning in Java(besides the value of the objects variables)

Share this post


Link to post
Share on other sites
Quote:
Original post by SunDog
\if you took say a freshman CS student who had just learned C++, then introduced them to Java, if all of what you said was 'Java is call by value', then they would probably expect it to behave like it does in C++.

Then just explain to them that Java uses pointers for its object-typed variables. It's better than lying to them that Java is call-by-reference and screwing them up the first time they expect it to actually behave that way.

Share this post


Link to post
Share on other sites
As far as comparisons to C or C++ are concerned, Java is "call by value" - quotes of the specification above prove that. But people often see it as a "bad thing", fooling themselves that such a behavior is dangerous to performance and other issues. But the average beginner fails to see that this trade-off is exactly what makes Java more interesting, given the arguments already posted by SunDog. Therefore, discussing such aspects is rather pointless for the average programmer, whose choices based on productivity, portability, and other characteristics, are not affected by the concepts discussed above.

But Java is "call by value", yes it is, no matter what the language actually does with pointers and references, you can't argue with that =D

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this