Click here to Skip to main content
15,894,646 members
Articles / Programming Languages / Java

Simulating C# ref Parameter in Java

Rate me:
Please Sign up or sign in to vote.
4.00/5 (1 vote)
18 Nov 2013CPOL2 min read 11.3K   2  
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:

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

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

Java
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:

Java
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 also be 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<t> class defined above like so:

Java
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:

Java
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:

Java
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<t> 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<t> 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<t>. This pattern is also used in EventArgs and other derived classes, in .NET.

This article was originally posted at http://blog.andrei.rinea.ro?p=415

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer (Senior) IBM, Business Analytics
Romania Romania
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions

 
-- There are no messages in this forum --