Is Java a good language to learn Besides C++ ??

Pages: 12345
The pointers (references) are passed by value, so there is no contradiction.
Last edited on
I'm not sure if you're joking or being serious.
I'm serious. To put it in C++ terms, there's a difference between:

void foo(Object* obj);
and
void foo(Object*& obj);

In Java, it's always the former.
closed account (z05DSL3A)
It is old but is still relevant:
Does Java pass by reference or pass by value?
http://www.javaworld.com/javaworld/javaqa/2000-05/03-qa-0526-pass.html
On the other hand, if I can make changes to P in a function unrelated to P, does that still count as value? The pointers inside the function are copies, explaining why badSwap() doesn't work, but they still point to the real object. In my eyes, that's behaviour that can't be explained to someone who doesn't know what pointers are.

Especially when these two functions have an entirely different result:
1
2
3
4
5
     static public void increase(int a) { a = a+1; } // Does nothing
    static public void increase(Point p) { // Changes the passed Object
        p.x = p.x+1;
        p.y = p.y+1;      
    }

Even more basic, this:
1
2
3
4
5
6
7
8
int myInt = 6;
int yourInt = myInt;
increase(myInt);
// myInt is still 6
Point myPoint = new Point(5, 6);
Point yourPoint = myPoint;
increase(yourPoint);
// myPoint is now (6, 7) 

That's some of the most confusing stuff I've ever seen.

To be honest, you can't claim "passes by value" and hide behind "yes, but everything is a pointer!" in a language that doesn't have pointers. The behaviour is, in my eyes, inconsistent, which as far as I'm concerned is far, far worse than the original "everything's a pointer" idea I had of Java.
Last edited on
closed account (z05DSL3A)
Everything is a reference; however, unlike C++, references are copied into functions by value (in the same way that C++ copies pointers into functions).

It would appear that a Java reference is somewhere between a C++ pointer and C++ reference, which seems to be what causes confusion.
In my eyes, that's behaviour that can't be explained to someone who doesn't know what pointers are.

Yes, and therefore you first explain what pointers are (which are called references in Java).

void increase(Point p) { // Changes the passed Object

You're not passing an object (that's not possible), but a reference to an object.

in a language that doesn't have pointers.

But it does. You can't perform pointer arithmetic on them, but it doesn't change the fact that (Java) references behave very similar.
Last edited on
@Athar: That's my entire point; try explaining the concept of "a reference" to beginners. "It's the object, but also not" is generally not a great start. It's very difficult to conceptually separate "the object" and "the data of the object". (What's an object except for a collection of member variables?)

Then, try explaining why passing "an object" to function doesn't actually pass an object, but a reference. The result? Changes to 'the object' itself do nothing, but changing any of its members does. Since operators can't be overloaded, the copy ('=') operator is just there to confuse people. Unless you're dealing with primitive types, of course. But don't confuse 'int' with 'Int'!

You can survive in C++ for the basics without ever knowing about pointers and references, just by ignoring anything that has a * or & near it. Java takes away that option by hiding their references behind the scenes, which leads to 'unexplainable behaviour'.

I'll take my references and pointers explicitly, thank you.

[/six-years-of-bitterness-caused-by-unexplainable-Java-behaviour]
Objects communicate trought messages.
You can pass them any message (that they understand). There is one exception, in the case of arguments of methods you can't 'assign' them.

Also, in any way can modify yourself (can't touch this)
Last edited on
@Gaminic
You're exaggerating a bit.

It's very difficult to conceptually separate "the object" and "the data of the object".

Is it? I have an unversity script about C# targeted at non-CS programming newbies and it uses only one page to explain all of that. There's a cute little sketch with models of RAM cells, like you'll find in some C++ books when they explain pointers and an explanation that the references and the objects themselves are separate.
And it's all good.
Last edited on

static public void increase(int a) { a = a+1; } // Does nothing
static public void increase(Point p) { // Changes the passed Object
p.x = p.x+1;
p.y = p.y+1;
}


These are two different methods - you are not comparing argument passing semantics here.

Better example:
1
2
static public void increase(int a) { a = a + 1; } // Does nothing; passed by value
static public void increase(Integer a) { a = a + 1; } // Does nothing; passed by value 


There is no semantic difference between passing a primitive object and normal object in Java. There are some differences with regard to using == and equals (but modern JVM languages have fixed that).

In 1995, when Java was first designed, they wanted to make everything an object, but they didn't know how to make small objects fast and the overhead was too huge. So they came out with primitive types. If Java was designed today, for sure everything would be an object (like in Scala), without any overhead.
Last edited on
Java has only nine types, and they are all primitive types:
boolean - need I explain?
byte - signed 8-bit integer
char - unsigned 16-bit integer
short - signed 16-bit integer
int - signed 32-bit integer
long - signed 64-bit integer
float - 32-bit float
double - 64-bit float
reference - equivalent to C++ pointer except that they can only refer to null or valid object instances

Classes are definitions for instantiating objects, and objects can only be handled through references. Since references are primitive types and not objects you cannot have references to references.

All types in Java are passed by value to methods.

References are passed by value.

Let me clarify: to change what a reference refers to means to set it to refer to null, or to set it to refer to a valid object of they type it references; to change the object being referenced means that the object being referenced is a mutable type with methods to change its state or public member variables.

1
2
3
4
Cow ref; //a variable of type reference, which can only reference null or a Cow
ref = null; //changing what the reference refers to
ref = new Cow(); //changing what the reference refers to
ref.setMilk(8); //changing the object being referenced 



References are passed by value to methods, therefore when you change what a reference refers to you are changing the local method copy of the reference. The object being referenced is not affected in this case, nor is the copy of the reference variable outside of the method in the calling code.
Last edited on
@Athar:
Of course I'm exaggerating a bit. It's fueled by years of "My university/faculty thinks Java is the best language ever, then fails to teach it properly, then fails to notice all students that didn't fail the Java class immediately turned to C++ if they ever needed to program again". I think Java is overly complicated in its efforts to simplify everything. It has the air of "Don't worry about those scary pointers!", but invisible monsters are much scarier than those you can see. I think the "Everything is an object" and "Everything should belong to at least one class" is a nonsense mentality. The more I learn about Java, the more I see convoluted 'If we hide this, it'll be more user-friendly!' nonsense that simply makes it harder to understand any problems you might encounter.

I'm not trying to convey an objective view here. All I was trying to point out is that saying 'Java passes everything by value' is a semantically correct but utterly useless statement. That's like telling a waiter you haven't received your steak yet and the waiter answers "Yes you did, but I ate it while you weren't watching". Semantically different, but either way, the restaurant still owes you a steak.

@rapidcoder:
That's not a better example; that's worse. Integer is wrapper class for the int primitive type (what?) that mimics the behaviour of ints. If I could access Integer.value, the problem would be the same: changing an Object through a function is impossible; changing the members of an Object through a function is entirely possible. Which doesn't make sense, in a 'Java passes variables by value' world.
Last edited on

If I could access Integer.value,


So what? You can't access or change an int value, too. There is no a.value here:
 
int a = a + 1;


You are creating a new int here, that is one bigger than the previous one. The pass-reference-by-value holds. Internally a new object is not created, but semantically the result is just the same as if primitive type variables were references / pointers to immutable objects. No dragons here, it is very simple and consistent: pass-reference-by-value and pass-by-value are semantically *equivalent* for immutable types.

In Scala/C#/Ceylon/Kotlin and many other modern languages you have just a one single unified Int type. You don't know what is
below, the compiler might have put there a primitive type for faster operation, but also it might have put there whatever valid int implementation using objects. If there were a semantic difference, such unification would not be possible, because then the compiler could easily break your programs.
Last edited on
You're using your example to dodge the problem, but you're not answering it:

If Java passes by value, why can I change the members of an Object "passed by value"? (I know the official reason: because "the reference" is passed by value. In my eyes, that's a nonsense answer, because 'pass by value' means (or should mean) the parameter used to call the function will remain unchanged.)
the parameter used to call the function will remain unchanged

It does remain unchanged, but you already know that.

Now one could discuss whether the forced indirection via references and the somewhat related question of whether garbage collection really makes sense, but that's a different topic.
I keep leaving myself open for those answers, so I'll try to be a bit more precise.

Statement 1: Nobody cares about the reference of an Object. They care about the Object.
Statement 2: An Object is a collection of data (member variables).
Statement 3: Changing the data of an Object equals changing an Object.
Statement 4: If a function signature asks for an Object of type T, the parameter passed to it is (conceptually) an Object.

Now, please answer me without juggling semantics why "Java passes by value" still holds when I can change the value of member of an Object passed by value.

Or, the other way around, explain to me how the following (conceptually) makes sense:
1
2
3
4
Point A = new point(50, 50);
Point B = A;
doSomethingWith(B);
// A is now changed 

Why would I ever want that to be the standard behaviour?
closed account (z05DSL3A)
Gaminic,

from your code:
Point A = new point(50, 50);

In Java A is not the object, it is a reference to the object. This is where the comparison with C++ pointers comes in as it is a reference to an object of type...

So having said that, the C++ simile would be:

1
2
3
4
Point* A = new point(50, 50);
Point* B = A;
doSomethingWith(B);
// A is now changed 


or a fuller example:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
#include <iostream>

void Change(int* int_ptr)
{
    int_ptr = new int(3);
}

void Change2(int* int_ptr)
{
    *int_ptr = 3;
}

int main(int argc, char *argv[])
{
    int* fred = new int(10);

    int* ben = fred;

    Change(fred);

    std::cout << *fred << std::endl;

    Change2(ben);

    std::cout << *fred << std::endl;

    return 0;
}
10
3
I know that. I know what happens behind the scenes. I'm asking why you would want it that way. In C++, you can get that behaviour if you explicitly make things references/pointers. In Java, that's the standard behaviour. I'm calling that stupid, because you'll see 'Point A = B' long before you find out the truth of 'behind the scenes' Java.

I'm worried about the inconsistencies it brings. Why does "A = B; change(B);" change A unless it's a primitive type? Why can I use a function to change everything about A and B, except swapping them (directly)?

In C++, the first time you do
1
2
3
int a[10] = { <numbers> };
int b[10];
b = a;

you'll be very confused because it leads to odd behaviour. You'll post on the forum, they'll explain you about pointers, you'll think "Oh, that's handy!" and you'll one day use that information to write better code.

In Java, the first time you copy any non-primitive type variable, you'll be very confused. You'll post on the forum, they'll explain the concept of pointers, you'll think "Oh, that's handy!" and they'll say "Can't use'em though. They're always there, but only implicitly. All the confusion, but very few of the benefits!".

Yes, I understand why it works this way. I can't understand why anyone would want it to work that way.
without juggling semantics why "Java passes by value"

Passing by value or not is already a question that falls pretty much into the category of "juggling of semantics".

Why would I ever want that to be the standard behaviour?

Because most of your classes aren't point classes and it actually doesn't happen all that often that you truly want to create a copy of an object. Objects usually represent entities/data records, control elements, managers, wrappers for resources, etc. which usually are not meant to be copied. And when they are, there's still clone().
There are of course exceptions like vectors and matrices, which can be a chore to work with in Java. The lack of operator overloading isn't helping the matter either.

So there are advantages and disadvantages to the approach, but if there was The One True Way™ to do it, probably every language would do it that way.
Pages: 12345