Klassennamen im statischen Umfeld

Andi_CH

Top Contributor
Ich kann nichts dafür, aber in der Software hier ist beinahe alles statisch.

Kann ich (z.B. für eine Log-Ausgabe) den Klassennamen ermitteln? (Es geht eigentlich nur um Faulheit ;-) copy paste der log-Funktionalitäten)

Ganz elegant wäre, wenn ich trotz ererbter log-Funktionen der Name der Klasse erhalte aus der ich "log" aufrufe.

Bis jetzt wird der Klassename als
Code:
private final static String = "BlaBla";
in jeder Klasse gespeichert und die log-Funktionen gezwungenermassen repliziert, da die Vererbung ja nicht richtig klappt und änderungssicher ist das definitv auch nicht.

Java:
String s = (new Test3()).getClass().getName();
erachte ich irgendwie als suboptimal

(Nein, JLog oder was auch immer kommt nicht in Frage, das würde einen kompletten Systemumbau bedeuten und dafür bekomme ich kein grünes Licht :-( )
 
Meine Implementation zu diesem Thema benutzt ebenfalls den Stacktrace um an den Klassennamen zu kommen.

Java:
// Trick to get the class name in a static way
Exception e = new Exception();
StackTraceElement[] sTrace = e.getStackTrace();
// sTrace[0] will be always there
String className = sTrace[0].getClassName();

Nicht sehr elegant aber erfüllt seinen Zweck. 😀
 
Anstatt aus der Exception sollte man sich den Stack-Trave m.E. besser über
Java:
Thread.currentThread().getStackTrace()
holen.

Ganz ohne den Stack-Trace kommt man aus, wenn man eine anonymous inner class verwendet:
Java:
String ownClsName = new Object(){}.getClass().getEnclosingClass().getName();

Ob das aber "billiger" ist als der Weg über den Stack-Trace, müsste man ggfs. (wenn die Stelle wirklich als performance-kritisch erkannt worden ist) analysieren; schließlich muss auch hier ein Objekt instanziiert und später wieder collected werden.
 
Code:
String s = Test3.class.getName();
würde Dir zumindest das erzeugen eines Objektes ersparen ;-)
Aber was wirklich besseres fällt mir grad nicht ein...

Hi hi - da bin ich reingerannt - im Zuge von Refactoring werden einige Klassen auseinandergerissen und der Originalname bleibt der gemeinsamen Vaterklasse - Test3 gibt es aber immer noch.
Abgesehen davon: Wenn ich den Klassennamen verwenden muss um an den Klassennamen zu kommen .... na ja muss wohl nicht weitertippen 🙂

Ganz elegant wäre halt schon "this".className() .... (logisch, dass es "this" in diesem Kontext nicht gibt.)

Werde wohl den Stacktrace verwenden - geloggt wird hier eigentlich nur in Fehlerfällen und während der Entwicklung - ansonsten ist das per boolean unterdrückt.
 
Zuletzt bearbeitet:
wäre soetwas eine Lösungsmöglichkeit:
Java:
public class App 
{
	public static void main(String[] args)
	{
		Log.info("Hallo welt");
		Demo.doIt();
		Demo demo=new Demo();
		demo.doItInit();
		Log.print();		
	}
}

class Demo
{
	public static void doIt()
	{
		Log.info("test");
	}
	
	public void doItInit()
	{
		Log.info("do ist init");
	}
}

class Log
{
	private StringBuilder log=new StringBuilder();

	private static Log logger=new Log();
	
	public static void info(String text)
	{					
		StackTraceElement caller=Thread.currentThread().getStackTrace()[2];
		
		if(caller!=null) {
			logger.log.append(
				"info|" + caller.getClassName() +  "|" + text + "\n"
			);
		}
	}
	
	public static void print()
	{
		System.out.println(logger.log.toString());
	}
}

Ausgabe:
Code:
info|inf.test.App|Hallo welt
info|inf.test.Demo|test
info|inf.test.Demo|do ist init
?
 
Zuletzt bearbeitet von einem Moderator:
An so etwas ähnlichem bin ich gerade dran.

Das ist mehr als Dokumentation für die "Nachwelt" gedacht ;-)

Interessant ist die Tatsache, dass die Exception nur einen Eintrag im StackTraceElement[] liefert (Der zweite der unten gezeigten), der Thread hingegen zwei. Ich werde wohl nach ".java:" suchen

Java:
StackTraceElement[] steArr = Thread.currentThread().getStackTrace();
for (StackTraceElement ste : steArr) {
	System.out.println("----------------------------------------------");
	System.out.println("ste         = " + ste);
	System.out.println("ClassName   = " + ste.getClassName());
	System.out.println("FileName    = " + ste.getFileName());
	System.out.println("LineNumber  = " + ste.getLineNumber());
	System.out.println("MethodeName = " + ste.getMethodName());
}
Code:
----------------------------------------------
ste         = java.lang.Thread.getStackTrace(Unknown Source)
ClassName   = java.lang.Thread
FileName    = null
LineNumber  = -1
MethodeName = getStackTrace
----------------------------------------------
ste         = com.javaforum.test.ShowClassname.main(ShowClassname.java:20)
ClassName   = com.javaforum.test.ShowClassname
FileName    = ShowClassname.java
LineNumber  = 20
MethodeName = main
 
Interessant ist die Tatsache, dass die Exception nur einen Eintrag im StackTraceElement[] liefert (Der zweite der unten gezeigten), der Thread hingegen zwei. Ich werde wohl nach ".java:" suchen
Damit würdest du dich darauf verlassen, dass der Bytecode auch solche Informationen enthält - was man beim Compiler mit -g:none allerdings unterdrücken kann. Daher wäre der Code darauf angewiesen, mit bestimmten Compileroptionen übersetzt zu werden.
Aber eigentlich musst du auch nichts suchen: der von Thread.getStackTrace() gelieferte Stack-Trace enthält eben immer am Anfang Thread.getStackTrace. Insofern kannst du davon ausgehen, dass die relevante Information eben bei Index 1 steht.
 
Zuletzt bearbeitet:
fast richtig, sie stehen bei [c]2[/c]. Denn bei index [c]0[/c] steht sowas wie:
[c]java.lang.Thread.getStackTrace(Unknown Source)[/c]
somit steht bei [c]1[/c] die Loggerklasse und bei [c]2[/c] die relevanten Informationen.
In deinem Beispiel, aber nicht in dem des TOs:

Code:
----------------------------------------------
ste         = java.lang.Thread.getStackTrace(Unknown Source)
ClassName   = java.lang.Thread
FileName    = null
LineNumber  = -1
MethodeName = getStackTrace
----------------------------------------------
ste         = com.javaforum.test.ShowClassname.main(ShowClassname.java:20)
ClassName   = com.javaforum.test.ShowClassname
FileName    = ShowClassname.java
LineNumber  = 20
MethodeName = main
 
Achso ja, ich bin davon ausgegangen, dass der TO es in einer Form verwenden will, wie in meiner Methode. Nach dem Beispiel hattest du dann natürlich recht.
 
Das Thema ist wohl soeben gestorben :-(

Erst mal Dampf ablassen:

Es ist zum Kotzen. Verd... warum haben die Javaentwickler Vererbung nicht auch im statischen Umfeld korrekt implementiert ???:L

Ich wollte das alles in der Vaterklasse implementieren und dann auf der Subklasse aufrufen

Das Schei.... Java merkt das nicht und liefert mir den Namen der Vaterklasse.

EDIT: Stimmt nicht alles! Siehe weiter unten.
 
Zuletzt bearbeitet:
Verstehe ich jz nicht so ganz. Meinst sowas in der Art:
Java:
class SLogger
{
	private StringBuilder logs=new StringBuilder();
	
	public void printMe()
	{
		System.out.println(logs.toString());
	}
	
	public void info()
	{
		logs.append(this.getClass() + "\n");
	}
}

class MyLogger extends SLogger
{
	
}
?
Java:
SLogger logger=new MyLogger();
logger.info();
Antwort:
Code:
class inf.test.MyLogger

ansonsten erklärs mal genauer, da findet sich doch bestimmt ein weg.
 
Zuletzt bearbeitet von einem Moderator:
Mea culpa - mein Frustausbruch war wohl verfrüht

Java:
public class ShowClassname {
	public static String getClassName() {
		StackTraceElement[] steArr = Thread.currentThread().getStackTrace();
		return steArr[steArr.length-1].getClassName();
	}
}

Java:
public class ShowClassnameSubclass extends ShowClassname {

	public static void main(String[] args) {
		System.out.println(getClassName());
	}
}

und da kommt ganz schön brav:
Code:
com.javaforum.test.ShowClassnameSubclass
 

Zurück
Oben