C# copies C++ behavior where you can pass a struct by value or reference, and you can mark the parameter as readonly. C# also has in/out parameters. Essentially, you can program in C# exactly like you would in C++.
https://learn.microsoft.com/en-us/dotnet/csharp/language-ref...
The footgun with C# structs are that you can accidentally box them onto the heap. To avoid that you can define `ref struct`s that cannot be boxed. `ref struct`s follow the C# disposable pattern.
https://learn.microsoft.com/en-us/dotnet/csharp/programming-...
https://learn.microsoft.com/en-us/dotnet/csharp/language-ref...
The mutability difference is that part of a struct can be modified in place, which value classes can’t: the value of a complete value-class variable (or array slot) can only be modified (reassigned) as a whole. This is presumably because object references to value-class objects can be created, and those objects should be immutable so their identity doesn’t matter.
The other solution is to stack allocate and pass a pointer but as i said, unlike in C#, i do not think it's possible to do that in Java.
In Go, you can stack allocate but when you send a pointer (that escapes), the compiler will heap allocate the object.
People really misuse/misunderstand this term: Java objects are passed by their pointers ("references") being copied.
The alternative is pass by reference, which is done by e.g. c++, rust, who actually have references (Java doesn't). A good litmus test is whether you can write a swap method that actually changes your local variables.
I do not know how this is called.
But under the hood it can (and will) do a modification in place.