Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can you extend Java to introduce passing by reference?

Java is pass-by-value. How could you modify the language to introduce passing by reference (or some equivalent behavior)?

Take for example something like

public static void main(String[] args) {     String variable = "'previous String reference'";     passByReference(ref variable);     System.out.println(variable); // I want this to print 'new String reference' }  public static void passByReference(ref String someString) {     someString = "'new String reference'"; } 

which (without the ref) compiles to the following bytecode

  public static void main(java.lang.String[]);     Code:        0: ldc           #2                  // String 'previous String reference'        2: astore_1        3: aload_1        4: invokestatic  #3                  // Method passByReference:(Ljava/lang/String;)V        7: return    public static void passByReference(java.lang.String);     Code:        0: ldc           #4                  // String 'new String reference'        2: astore_0        3: return 

The code at 3: loads the reference onto the stack from the variable variable.

One possibility I'm considering is to have the compiler determine a method is pass by reference, possibly with ref, and change the method to accept a Holder object which stores the same reference as our variable. When the method completes, and possibly changes that reference in the holder, the variable on the caller side's value is replaced with the holder reference's value.

It should compile to an equivalent of this

public static void main(String[] args) {     String variable = "'previous String reference'";     Holder holder = Holder.referenceOf(variable);     passByReference2(holder);     variable = (String) holder.getReference(); // I don't think this cast is necessary in bytecode     System.out.println(variable); }  public static void passByReference(Holder someString) {     someString.setReference("'new String reference'"); } 

where Holder might be something like

public class Holder {     Object reference;     private Holder (Object reference) {         this.reference = reference;     }     public Object getReference() {         return this.reference;     }     public void setReference(Object reference) {         this.reference = reference;     }     public static Holder referenceOf(Object reference) {         return new Holder(reference);     } } 

Where can this fail or how could you improve it?

like image 710
Sotirios Delimanolis Avatar asked Jan 22 '14 04:01

Sotirios Delimanolis


People also ask

What is meant by pass by reference in Java?

Pass by Value: It is a process in which the function parameter values are copied to another variable and instead this object copied is passed. This is known as call by Value. Pass by Reference: It is a process in which the actual copy of reference is passed to the function. This is called by Reference.

Does Java support passing by reference?

Java always passes arguments by value, NOT by reference.


2 Answers

The usual idiom I've seen for pass-by-reference in Java is to pass a single-element array, which will both preserve run-time type-safety (unlike generics which undergo erasure) and avoid the need to introduce a new class.

public static void main(String[] args) {     String[] holder = new String[1];      // variable optimized away as holder[0]     holder[0] = "'previous String reference'";      passByReference(holder);     System.out.println(holder[0]); }  public static void passByReference(String[] someString) {     someString[0] = "'new String reference'"; } 
like image 178
Jeffrey Hantin Avatar answered Sep 29 '22 11:09

Jeffrey Hantin


To answer your question:

Where can this fail?

  1. Final variables and enum constants
  2. 'Special' references such as this
  3. References that are returned from method calls, or constructed inline using new
  4. Literals (Strings, integers, etc.)

...and possibly others. Basically, your ref keyword must only be usable if the parameter source is a non-final field or local variable. Any other source should generate a compilation error when used with ref.

An example of (1):

final String s = "final"; passByReference(ref s);  // Should not be possible 

An example of (2):

passByReference(ref this);  // Definitely impossible 

An example of (3):

passByReference(ref toString());  // Definitely impossible passByReference(ref new String("foo"));  // Definitely impossible 

An example of (4):

passByReference(ref "literal");  // Definitely impossible 

And then there are assignment expressions, which seem to me like something of a judgement call:

String s; passByReference(ref (s="initial"));  // Possible, but does it make sense? 

It's also a little strange that your syntax requires the ref keyword for both the method definition and the method invocation. I think the method definition would be sufficient.

like image 45
Kevin K Avatar answered Sep 29 '22 12:09

Kevin K