Archiv

Archiv für November, 2009

Java und Call-By-Reference

23. November 2009 sep 1 Kommentar

Hey, ich arbeite ja mal wieder an einem Projekt, und bin dort ein mal auf ein kleines Problem gestoßen. Nämlich einen nativen Typen in einer Funktion zu bearbeiten. Eigentlich kein Problem. Zumindest kann man diesen ja zurück geben, per return. Jedoch hatte ich dort schon einen anderen Rückgabewert.  Also, kann man sich nun noch eine neue Klasse schaffen, um dort mehrere Sachen zurück zu geben. Jedoch war mir das nicht elegant genug.

Dann kam ich auf eine Idee, welche ich aus C, C++ und C# kenne. Nämlich das Call-By-Reference[1]. Unter C# ist es wie folgt möglich.

TryParse( String str, ref int value );

Doch unter Java ist das nicht so einfach. Denn folgendes ist dort der Fall. Da sehr viele Programmierfehler auf Zeiger zurück zu führen sind, hatte man die Zeiger in der Sprache sozusagen abgeschafft. Sie sind für uns also nicht mehr sichtbar. Nun ist die objektorientierte Programmierung ohne Referenzen aber nicht möglich. Denn auf jedes Objekt, welches instantiiert wird, gibt es eine Referenz. Diese Referenz wird als Kopie an eine Funktion übergeben. Und die Funktion arbeitet dann damit. So ist es möglich, dass Eigenschaften in einem Objekt geändert werden könne und außerhalb der Funktion diese Änderungen auch noch “aktiv” sind. Sie wurden also nicht zurück geändert. Jedoch kann man das Objekt an sich nicht verändern. Also neu instantiieren und dies dann über die Parameter zurück geben. Native Datentypen werden alle als Kopie übergeben. So fällt der Aspekt des Änderns weg. Also dachte ich mir, es gibt ja Wrapper-Klassen und so wollte ich eine nutzen. Denn dort werden wieder die Referenzen weiter gegeben und ich könnte die Eigenschaften ändern. Aber mir ist dann aufgefallen, dass ich die Eigenschaften in der Wrapper-Klasse nicht bearbeiten kann, da mir die Zugriffskontrolle dies verbietet. Blöd! Also wollte ich mir selber eine Wrapper-Klasse schaffen. Jedoch kann es ja sein, dass Java so was bietet. Also machte ich mich auf die Suche und hab nichts gefunden. (Wenn es so was gibt dann sagt mir Bescheid! :D ) Naja. Wie auch immer. Im Java-Forum[2] wird davon gesprochen einfach ein Array-Objekt zu übergeben. In einem Array sind die Werte gespeichert. Von dem Array wird dann eine Kopie der Referenz übergeben und ich könnte meine Werte bearbeiten. Funktioniert zwar, war mir aber nicht schön genug.

Nach einiger erfolgloser Suche habe ich mir dann eine eigene Wrapper-Klasse geschrieben.

package org.seplog.javrsimulator.util;

/**
 * Diese Klasse ist eine Wrapper Klasse. Hierdurch können alle möglichen
 * Typen, Klassen und Objekte einer Funktion als Referenz übergeben
 * werden.
 *
 * @author Sebastian Koschmieder
 * @date 17.11.2009
 * @mail sep@seplog.org
 * @param < T >
 *            Ist der Typ der Klasse, welche übergeben wird.
 */
public final class ByReference< T > {

    /******* Member ****************************/

    /**
     * Dies ist der Wert, welcher als "Referenz" übergeben wird.
     * Da mit diesem Wert durch beide Bearbeiter gleichermaßen
     * bearbeitet werden können muss, findet keine
     * Zugriffskontrolle statt.
     */
    public T value;

    /******* Konstruktoren *********************/

    /**
     * In dem Konstruktor wird nur die Variable übergeben.
     *
     * @param value
     *            Dies Variable wird als Referenz behandelt.
     */
    public ByReference( T value ) {
        this.value = value;
    }

}

Die Verwendung dieser Klasse ist ganz einfach. Ich instantiiere mir ein ByReference-Objekt, welchem ich im Konstruktor mein Objekt gebe. Danach übergebe ich die ByReference-Klasse an die Funktion. Beide, also Aufrufer und die aufgerufene Methode können nun das Objekt gleichermaßen bearbeiten.

package org.seplog.javrsimulator.util;

public class Program {

    public static void main( String[] args ) {

        ByReference< Integer > reference = new ByReference< Integer >( 42 );
        System.out.printf( "Wert: %d\n", reference.value );
        changeRef( reference );
        System.out.printf( "Wert: %d\n", reference.value );

    }

    public static void changeRef( ByReference< Integer > reference ) {
        reference.value = 1337;
    }
}

Links

  1. Referenzparameter – Wikipedia
  2. Lösung Java-Forum
Categories: Informatik Tags: , ,