# Aufrufer einer Funktion ermitteln



## multiholle (28. Jan 2010)

Wie kann ich ermitteln, welches Obejekt die Funktion einer Klasse aufgerufen hat? In etwas so:

```
public ClassA {
  public static void something() {
    ClassB.anything();
  }
}

public ClassB {
  public static void anything() {
    String className = ...; // "ClassA"
    System.out.println("called anything() from " + className);
  }
}
```


----------



## Ebenius (28. Jan 2010)

Gar nicht. Zum Logging, kann man den Namen der Klasse und Methode ermitteln: Thread.getStackTrace(). Mehr aber nicht.

Üblicherweise ist der Bedarf einer solchen Funktionalität ein Zeichen für einen Design-Fehler. ;-)

Ebenius


----------



## MQue (28. Jan 2010)

Ich würds, wenn man das schon benötigt, so ungefähr machen, also weg mit den Klassenmethoden -> Klassenmethoden und Klassenvariablen würde ich nur selten verwenden, static - Methoden und Variablen gibts nur ein einziges mal für eine Klasse und alle Objekte teilen sich die static Dinger.


```
package classinvokation;

class ClassA {
  public void something() {
    ClassB cb = new ClassB();
    cb.anything(this);
  }

    @Override
  public String toString() {
    return "[ClassA: " + this.hashCode() + ", " + this.getClass() + "]";
    }
}

class ClassB {
  public void anything(ClassA ca) {
    String className = ca.toString();
    System.out.println("called anything() from " + className);
  }
}

public class Main {

    public Main() {
        ClassA ca = new ClassA();
        ca.something();
        }

    public static void main(String[] args) {
        new Main();
        }
    }
```


----------



## Gast2 (28. Jan 2010)

Das ist doch Murks. Bringt in diesem speziellen Fall was, aber dann kannst du auch gleich jeder Funktion noch drei weitere Paramter mitgeben:


```
public void irgendEineFunktion(String param1, String param2, 
                   String callingClassname, String callingClassFunktion, int callingClassLineNr){
System.out.println("Was called by "+callingClassname+"."+callingClassFunktion
     +"("+param1+", "+param2+") at line "+callingClassLineNr);
}
```

Aber ich schließe mich da Ebenius an, der sinn dahinter leuchtet mir auch nicht ein, bzw sollte es den Bedarf gar nicht geben. (Höchstens zu Demonstrationszwecken)


----------



## FArt (28. Jan 2010)

http://www.java-forum.org/allgemeine-java-themen/89896-teuer-verwendung-stack-trace.html


----------



## Atze (28. Jan 2010)

wenn er das bei jeder methode haben will, vielleicht wäre das endlich mal nen grund für AOP


----------



## MQue (28. Jan 2010)

fassy hat gesagt.:


> Das ist doch Murks. Bringt in diesem speziellen Fall was, aber dann kannst du auch gleich jeder Funktion noch drei weitere Paramter mitgeben:
> 
> 
> ```
> ...



Was ist denn mit dir los, mir ist auch nichts besseres eingefallen für diesen Problemfall, hätte ja sein können, dass für den TO ein anderes Design ohne static auch möglich ist. Das gleich als Murks zu bezeichnen ohne einen besseren Vorschlag zu liefern find ich schwach außerdem musst du das schon dem TO überlassen.


----------



## multiholle (28. Jan 2010)

Der Hintergrund des ganzen liegt in der Ausgabe von Informationen/Warnungen/Fehler. Ich wollte eine Tool-Klasse schreiben, die diese Funktionen zur Statusausgabe zur Verfügung stellt. Ich möchte einen String als Meldung an diese Funktion übergeben und die Tool Klasse sollte dann so eine Ausgabe erzeugen:


```
[28.01.2010 13:51:32.3] ExampleClass: Everything is OK.
```

"ExampleClass" wäre dann die Klasse, die die Information ausgibt. Ließe sich das auch noch anders realisieren?


----------



## MQue (28. Jan 2010)

Wenn nur der Klassenname ausgegeben werden soll, woher die Meldung kommt, dann würde ich dir nochmal meinen Code empfehlen,


----------



## Ebenius (28. Jan 2010)

Für den Zweck kannst Du meiner Meinung nach den StackTrace benutzen.

Ebenius


----------



## multiholle (28. Jan 2010)

Ich habe es jetzt so gelöst, ist das in Ordnung?

```
package tools;

import java.io.PrintStream;
import java.text.SimpleDateFormat;
import java.util.Date;

public class Console {
	public static void printInfo(String info) {
		// Aktuellen StackTrace holen
		StackTraceElement[] stackTrace = Thread.currentThread().getStackTrace();
		// Aufrufende Klasse ermitteln
		String callingClass = stackTrace[2].getClassName();
		// Ausgabe
		print(info, callingClass, System.out);
	}
	
	public static void printError(String error) {
		// Aktuellen StackTrace holen
		StackTraceElement[] stackTrace = Thread.currentThread().getStackTrace();
		// Aufrufende Klasse ermitteln
		String callingClass = stackTrace[2].getClassName();
		// Ausgabe
		print(error, callingClass, System.err);
	}
	
	private static void print(String message, String callingClass, PrintStream output) {
		// Datumsformat festlegen
		SimpleDateFormat dateFormat = new SimpleDateFormat("dd.MM.yyyy HH:mm:ss");
		// Info zusammenbauen und ausgeben
		output.println(
				"[" + dateFormat.format(new Date()) + "] " +
				callingClass + ": " + message);		
	}
}
```


----------



## Ebenius (28. Jan 2010)

Schaut so aus. 

Ebenius


----------



## SlaterB (28. Jan 2010)

wenn du mit der Verschachtelung aufpasst, könnte der doppelte Code 

 // Aktuellen StackTrace holen
        StackTraceElement[] stackTrace = Thread.currentThread().getStackTrace();
        // Aufrufende Klasse ermitteln
        String callingClass = stackTrace[2].getClassName();

auch direkt in die print-Methode ab Zeile 26, 
dann nur stackTrace[3] und darauf aufpassen, dass niemand die Methode direkt aufruft


----------



## multiholle (28. Jan 2010)

Hier noch etwas kürzer. Bin soweit ganz zu frieden. Die Ausgabe sieht dann so aus: 

```
[28.01.2010 15:33:55] communication.client.Client: 3 + 2 = 5
```


```
import java.io.PrintStream;
import java.text.SimpleDateFormat;
import java.util.Date;

public class Console {
	public static void printInfo(String info) {
		print(info, System.out);
	}
	
	public static void printError(String error) {
		print(error, System.err);
	}
	
	private static void print(String message, PrintStream output) {
		// Aktuellen StackTrace holen
		StackTraceElement[] stackTrace = Thread.currentThread().getStackTrace();
		// Aufrufende Klasse ermitteln
		String callingClass = stackTrace[3].getClassName();
		// Datumsformat festlegen
		SimpleDateFormat dateFormat = new SimpleDateFormat("dd.MM.yyyy HH:mm:ss");
		// Info zusammenbauen und ausgeben
		output.println(
				"[" + dateFormat.format(new Date()) + "] " +
				callingClass + ": " + message);		
	}
}
```


----------

