0

I started with java a couple of weeks ago. Before that i had multiple years working with c/c++ on embedded targets and with c# with UI Stuff on Win PCs.

I got this very simple example:

public class StreamProcessing {

    public static void main(String[] args) {
        Stream stream = new Stream(); //after this line: Stream string empty

        StreamFiller.fillStream(stream);   //after this line: Stream string not empty any more
        StreamPrinter.printStream(stream);

    }

}

I'd expect that whatever StreamFiller.fillStream() does, the argument is copied. However it looks like fillStream is modifying the actual stream object itself. The Stream class basically contains a string

public class Stream {
    private String content = "";
    int index = 0;

    public char readChar() {
        if (index < content.length()) {
            return content.charAt(index++);
        } else {
            return 0;
        }
    }

    public void writeString(String str) {
        content += str;
    }
}

The Streamfiller should modify it's stream copy but not the original reference

public class StreamFiller {

    public static void fillStream( Stream stream ) {
         stream.writeString( "This is a" );
         stream.writeString( " stream." );
    }        
}

Please correct me if I'm wrong, but since the actual text of the string class is allocated on the heap, both the StreamProcessing () Stream object and the (supposed copied) local object of fillStream() point to the same address on the heap (yeah i now it's not an actual memory address like in c/c++ but some unique object identifier)

So is my assumption correct? Non trivial objects (aka objects allocated on the heap) are passed by reference?

thx for your help :)

Dr.Death
  • 63
  • 7
  • 1
    In Java, Objects are always passed by reference, only primitives like `int` are passed by value. Heap or stack does not matter. – Robert Oct 05 '19 at 22:00
  • This is duplicated all over SO and the web. The reference is passed by value; there's no copying going on. – Dave Newton Oct 05 '19 at 22:00
  • 3
    Possible duplicate of [Is Java "pass-by-reference" or "pass-by-value"?](https://stackoverflow.com/questions/40480/is-java-pass-by-reference-or-pass-by-value) – Janus Varmarken Oct 05 '19 at 22:19

2 Answers2

0

Even though in Java everything is passed by value, there is a difference between how primitive data types (such as int, char and boolean) and how reference data types are passed to a method. When passing the value of a primitive data type, this value can only be changed in the scope of the particular method. When passing the value of a reference data type, the reference will remain the same but the value will change globally (or in whatever scope the object was initialised).

See also this for more information: https://docs.oracle.com/javase/tutorial/java/javaOO/arguments.html

greg.
  • 23
  • 5
0

The Java language does not let you make heap / stack distinction in your code the way C and C++ do.

Instead, it divides all data types in to two groups:

  1. Primitive types:
    These are simple built in numerical types such as int, double or boolean (not a numerical type in Java).
    Note that String is not such a type!

  2. Object types:
    If it is a class, it is an object type. This goes for built in types such as String and for user defined types such as your Stream class.
    For these types, all you ever see is a reference, whether you are looking at a local variable, class member, instance member, or function parameter.

Lets look at a simple example:

public class A {
    public int a;

    public static void main(String [] args) {
        A var1 = new A();
        A var2 = var1;

        var1.a = 42;

        System.out.println("var2.a = " + var2.a);
    }
}

If you compile and run this example it will print 42.
In C++ the line A var2 = var1; would have invoked a copy constructor and created a new object but in Java there is no such thing. If you want a copy, you need to invoke clone method explicitly.

What is held in var1 and copied to var2 is just a reference. So both vars "point" to the same object.

And again - it does not matter if the class is trivial or not. Even if a class is completely empty, you will still only be given and work with a reference to any object of this class.

As for the primitive types mentioned earlier, Java has wrapper classes such as Integer and Boolean for them. You might want to read about "boxing" and "unboxing".

One more thing to note is that some types are immutable - that is, they do not provide a way to change their data once created.

String in Java is an immutable type, but it is also a bit different from any other type.
It has special privileges.
While Java does not support operator overloading like C++ does, for String type the language does provide a special + operator that preforms string concatenation.

How ever, since String objects are immutable, any concatenation operation will create a brand new String object, even one like this:

String a = "Hello";
a = a + " world!";

This creates a new string "Hello world" and stores the reference to it in a, leaving the reference to old "Hello" string to be garbage collected at some future point.

Lev M.
  • 4,162
  • 1
  • 6
  • 21