Simulating C# ref parameter in Java

As I was saying a few posts ago (Beginning Java for .NET Developers), on the 8th slide, there are no ref and no out method parameter modifiers.

These are rarely used in .NET anyway so you can’t really complain of their lack in Java. Furthermore, some of their legitimate uses, such as the static TryParse methods on value types are not applicable in Java. Why? Because in Java the primitives (int, long, byte etc. – the equivalent of the basic value types in .NET) are not part of the type hierarchy and they have reference-type wrappers (Integer etc.) which would solve the issue of returning the result in case of ‘TryParse’ style of parsing. How’s that? It’s like :

public static Integer tryParseInt(String intString) {
    try {
        return Integer.parseInt(intString);
    } catch (NumberFormatException e) {
        return null;
    }
}

No need for a ‘out’ parameter or ‘ref’. But! Let’s try and simulate ‘ref’ using a generic class written this way :

public class Ref<T> {
    private T value;

    public Ref() {
    }

    public Ref(T value) {
        this.value = value;
    }

    public T getValue() {
        return value;
    }

    public void setValue(T value) {
        this.value = value;
    }

    @Override
    public String toString() {
        return value == null ? null : value.toString();
    }
}


Now, suppose we have a class PhoneNumber that expects a number as [firstPart]-[secondPart] (both being integer, positive numbers). This class could look like :

public class PhoneNumber {

    private final int firstPart;
    private final int secondPart;

    private final static int NOT_FOUND = -1;

    public PhoneNumber(int firstPart, int secondPart) {
        this.firstPart = firstPart;
        this.secondPart = secondPart;
    }

    public int getFirstPart() {
        return firstPart;
    }

    public int getSecondPart() {
        return secondPart;
    }

    @Override
    public String toString() {
        return Integer.toString(firstPart) + "-" + Integer.toString(secondPart);
    }
}

We will also suppose that another allowed string representation of a phone number would be “private” (irrespective of the casing). We want to create a static tryParse method on that class. If the given string is not a valid phone number we could return null. But in case of the “private” value we would be also forced to return null. There would be an ambiguity. Therefore we would need some kind of disambiguation. One way would be to use the Ref class defined above like so :

public static boolean tryParse(String phoneNumberString, Ref<PhoneNumber> phoneNumber) {
    if (phoneNumberString == null || phoneNumberString.isEmpty()) return false;
    if (phoneNumber == null) throw new IllegalArgumentException();

    phoneNumber.setValue(null);
    if (phoneNumberString.toLowerCase().equals("private")) {
        return true;
    }
    int dashIndex = phoneNumberString.indexOf('-');
    if (dashIndex == NOT_FOUND || dashIndex == 0 || dashIndex == phoneNumberString.length() - 1) {
        return false;
    }

    String firstPartString = phoneNumberString.substring(0, dashIndex);
    String secondPartString = phoneNumberString.substring(dashIndex + 1, phoneNumberString.length());
    int firstPart;
    int secondPart;

    try {
        firstPart = Integer.parseInt(firstPartString);
        secondPart = Integer.parseInt(secondPartString);
    } catch (NumberFormatException e) {
        return false;
    }

    phoneNumber.setValue(new PhoneNumber(firstPart, secondPart));
    return true;
}

An example of using that code could be

    public static void main(String[] args) {
        String s1 = "555-1234";
        String s2 = "555";
        String s3 = "saldkfjasdf";
        String s4 = "PRIVATE";
        String s5 = "";
        String s6 = null;

        Ref<PhoneNumber> pn1 = new Ref<PhoneNumber>();
        Ref<PhoneNumber> pn2 = new Ref<PhoneNumber>();
        Ref<PhoneNumber> pn3 = new Ref<PhoneNumber>();
        Ref<PhoneNumber> pn4 = new Ref<PhoneNumber>();
        Ref<PhoneNumber> pn5 = new Ref<PhoneNumber>();
        Ref<PhoneNumber> pn6 = new Ref<PhoneNumber>();

        boolean b1 = PhoneNumber.tryParse(s1, pn1);
        boolean b2 = PhoneNumber.tryParse(s2, pn2);
        boolean b3 = PhoneNumber.tryParse(s3, pn3);
        boolean b4 = PhoneNumber.tryParse(s4, pn4);
        boolean b5 = PhoneNumber.tryParse(s5, pn5);
        boolean b6 = PhoneNumber.tryParse(s6, pn6);

        System.out.println("Parsing '" + s1 + "' : " + b1 + ", Ph# : " + pn1);
        System.out.println("Parsing '" + s2 + "' : " + b2 + ", Ph# : " + pn2);
        System.out.println("Parsing '" + s3 + "' : " + b3 + ", Ph# : " + pn3);
        System.out.println("Parsing '" + s4 + "' : " + b4 + ", Ph# : " + pn4);
        System.out.println("Parsing '" + s5 + "' : " + b5 + ", Ph# : " + pn5);
        System.out.println("Parsing '" + s6 + "' : " + b6 + ", Ph# : " + pn6);
    }

Upon running this piece of code we would receive :

Parsing '555-1234' : true, Ph# : 555-1234
Parsing '555' : false, Ph# : null
Parsing 'saldkfjasdf' : false, Ph# : null
Parsing 'PRIVATE' : true, Ph# : null
Parsing '' : false, Ph# : null
Parsing 'null' : false, Ph# : null

This way we were able to simulate a ref parameter. However some might argue that this is not the only solution and we could have defined another class called ParseResult encapsulating a boolean representing the success of parsing and a T representing the parsed value (in case the parsing succeeded). Of course we could do this, it would be a good alternative. However, for the C# / .NET developers the Ref would be closer to their existing knowledge.

Regarding the out parameter things are not so bright. That’s because of two things : first, the called method should be enforced to set at least once a value to the out parameter on each execution path and in C# this is enforced by the compiler while in Java I see no way to enforce it. Second, the solution (if one would exist) should restrict the called method to only set the value but not read it while the method caller should be able to read and write.

In conclusion at least we can simulate ref with Ref. This pattern is also used in EventArgs and other derived classes, in .NET.

  1. You can also create an array with one item…

Leave a Comment


NOTE - You can use these HTML tags and attributes:
<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>

This site uses Akismet to reduce spam. Learn how your comment data is processed.