# Klassenname in main-Methode ausgeben?



## MrDanger (3. Feb 2005)

Wie bekommt man das hin ohne eine Instanz zu bilden?


----------



## Wildcard (3. Feb 2005)

```
System.out.println(MyClass.class);
```


----------



## Illuvatar (4. Feb 2005)

Hm das setzt aber voraus dass der Klassenname zur Compilezeit bekannt ist und ich fürchte, dass das das Problem ist...

Ich habe keine Ahnung


----------



## bygones (4. Feb 2005)

genau das ist die Frage... daher hoffe ich, dass das Problem noch genauer beschrieben wird!


----------



## fehlerfinder (18. Mrz 2008)

Illuvatar hat gesagt.:
			
		

> Hm das setzt aber voraus dass der Klassenname zur Compilezeit bekannt ist und ich fürchte, dass das das Problem ist...


Genau so war bzw. ist das: Nachdem inzwischen einige Jahre ins Land gegangen sind, möchte ich diesen Thread nochmal nach vorne holen.

Hintergrund:
Mein Programm soll abhängig vom Klassennamen (leicht) unterschiedliche Dinge tun. Als "ClassNormal" soll es regelmäßig laufen und als "ClassSpezial" möchte ich es manuell aufrufen. Um jetzt möglichst wenig im Programmcode ändern zu müssen, möchte ich die "speziellen" Dinge in einem if-Block abhängig vom Klassennamen verarbeiten.

Kennt da jemand eine Möglichkeit?


----------



## SlaterB (18. Mrz 2008)

>  ohne eine Instanz zu bilden

eine Instanz kann man nur bilden, wenn man die Klasse hat

also 
Class c = ..;
->
c.getName();


oder gleich

System.out.println(c);

---------

wenn die Klasse nicht bekannt ist, kein Objekt davon oder sonst irgendwas,
nun dann kann man aus dem Nichts auch nixherzaubern


----------



## Der Müde Joe (18. Mrz 2008)

Strategy Pattern vielleicht?


----------



## fehlerfinder (18. Mrz 2008)

SlaterB hat gesagt.:
			
		

> wenn die Klasse nicht bekannt ist, kein Objekt davon oder sonst irgendwas,
> nun dann kann man aus dem Nichts auch nixherzaubern


Schönen Dank schonmal für die fixe Antwort.

Aber warum ist die Klasse nicht bekannt? Ich rufe die main-Methode doch innerhalb eines class-files auf. Damit habe ich doch eine Klasse, wenn auch natürlich kein Objekt.

Ist es denn so, dass mir die Klasse an sich gar nichts bietet? Beim Übersetzen wird doch auch ein Abgleich zwischen Dateinamen und Klassennamen gemacht (und gemeckert, wenn die nicht übereinstimmen ;-) ). Kann natürlich sein, dass das reines "Text-Parsen" ist. Aber mir widerstrebt ein wenig, dies anzunehmen.


----------



## Beni (18. Mrz 2008)

Anstelle von Reflection könnte man sich den Stacktrace angucken. Mit diesem Stücklein Code solltest du ihn abfragen können:

```
Thread.currentThread().getStackTrace()
```
... das resultierende SackTraceElement kannst du dann mit "getClassName" nach der Klasse fragen.


----------



## Verjigorm (18. Mrz 2008)

Beni hat gesagt.:
			
		

> ...das resultierende SackTraceElement



SackTraceElement??? 
 :shock:    :autsch:  :applaus:


----------



## fehlerfinder (18. Mrz 2008)

Verjigorm hat gesagt.:
			
		

> Beni hat gesagt.:
> 
> 
> 
> ...



Das ist doch mal ein schöner Verschreiber. Auf jeden Fall macht das genau das, was ich will. Werde mich jetzt nur mal noch ein bisschen mit dem StackTrace beschäftigen müssen, damit ich weiß, ob das StackTraceElement mit dem höchsten Index immer(!) den Klassennamen beinhaltet.


----------



## fehlerfinder (18. Mrz 2008)

Der Müde Joe hat gesagt.:
			
		

> Strategy Pattern vielleicht?


Mmh, ich hab das jetzt auf die Schnelle natürlich noch nicht durchgelesen, daher mal eine Vorab-Frage: enthält das Papier eine Möglichkeit, tatsächlich an den Namen zu kommen, oder geht es mehr darum, mich von meinem Vorhaben abzubringen, das Programm wie gewünscht einzusetzen ;-) ?


----------



## tfa (18. Mrz 2008)

fehlerfinder hat gesagt.:
			
		

> Hintergrund:
> Mein Programm soll abhängig vom Klassennamen (leicht) unterschiedliche Dinge tun. Als "ClassNormal" soll es regelmäßig laufen und als "ClassSpezial" möchte ich es manuell aufrufen. Um jetzt möglichst wenig im Programmcode ändern zu müssen, möchte ich die "speziellen" Dinge in einem if-Block abhängig vom Klassennamen verarbeiten.
> 
> Kennt da jemand eine Möglichkeit?


Polymorphie?


----------



## Der Müde Joe (18. Mrz 2008)

>> oder geht es mehr darum, mich von meinem Vorhaben abzubringen, das Programm wie gewünscht einzusetzen 

genau.

In kurz:

Die Verwendung von Strategien bietet sich an, wenn

    * viele verwandte Klassen sich nur in ihrem Verhalten unterscheiden.
    * unterschiedliche (austauschbare) Varianten eines Algorithmus benötigt werden.
    * Daten innerhalb eines Algorithmus vor Klienten verborgen werden sollen.
    * verschiedene Verhaltensweisen innerhalb einer Klasse fest integriert sind (meist über Mehrfachverzweigungen) aber

von Wiki
http://de.wikipedia.org/wiki/Strategie_(Entwurfsmuster)


----------



## SlaterB (18. Mrz 2008)

fehlerfinder hat gesagt.:
			
		

> SlaterB hat gesagt.:
> 
> 
> 
> ...


da du keine Frage gestellt hast bezog ich mich auf die vorherigen Posts,

wenn die Klasse bekannt ist
dann wie gesagt
System.out.println(c); oder was auch immer


----------



## fehlerfinder (18. Mrz 2008)

SlaterB hat gesagt.:
			
		

> fehlerfinder hat gesagt.:
> 
> 
> 
> ...


Ok - so ist das, wenn einem selbst völlig klar ist, was gemeint ist...

Also - 2. Versuch:
In dem Augenblick, in dem ich eine Klassendatei habe - z.B. KlassenName.java - müsste ich doch eigentlich auch den zuhörigen Klassen-Namen ("KlassenName") ermitteln können. Eine Klasse existiert doch in dem Augenblick, in dem ich das übersetzte Programm mit "java KlassenName" aufrufe. Dann habe ich noch keine Objekte, kann also auch nicht darüber auf den Namen zugreifen, aber ich habe die Klasse.

Die Möglichkeit, über getStackTrace() an die Info zu kommen zeigt, dass es geht, erscheint mir aber noch nicht so richtig gelungen bzw. so ein wenig "hintenrum".

Vielleicht gibt es da noch eine schönere Möglichkeit...

Frage: Gibt es noch eine schönere Möglichkeit? ;-)


----------



## SlaterB (18. Mrz 2008)

also den StackTrace kann man meines Wissens nach nicht nachbilden,
das ist eine native Operation, die werweißwas im Hintergrund mit Informationen der ausführenden JVM macht

System.out.println(ich bin gerade in ..);
gibts nicht,
auch Logging-Frameworks müssen dafür den StackTrace abfragen (soweit ich weiß)


----------



## fehlerfinder (18. Mrz 2008)

SlaterB hat gesagt.:
			
		

> also den StackTrace kann man meines Wissens nach nicht nachbilden


nee - soweit wollte ich auch nicht gehen...



> System.out.println(ich bin gerade in ..);


Genau DAS wäre(!) das Statement meiner Wahl. Na gut, dann eben nicht :schmoll

Ich werde mich jetzt mal über das o.g. Strategy pattern hermachen. Vielleicht erhellt mich das ja noch ein wenig.

Ansonsten: Danke für alle Antworten!


----------



## ms (18. Mrz 2008)

Ich frage mich die ganze Zeit, was an 
	
	
	
	





```
System.out.println(MyClass.class)
```
 so verkehrt ist bzw. dass es deinen Anforderungen nicht reicht. Derjenige, der den Code vor Augen hat weiss ja um welche Klasse es sich handelt.
Ist doch völlig sinnlos dafür eine eigene Funktion von der JVM bzw. Api zu verlangen.

Oder findest du auf die Frage wer du selbst bist auch manchmal keine Antwort ohne in den Spiegel, ein Foto oder den Reisepass zu sehen?

ms


----------



## fehlerfinder (18. Mrz 2008)

ms hat gesagt.:
			
		

> was an
> 
> 
> 
> ...


Es reicht nicht, weil ich faul bin (puh, endlich ist es raus...). Ich möchte eben nur (im Sinne von "ausschließlich") den Klassennamen ändern, also aus

```
public class KlasseNormal
```
soll

```
public class KlasseSpezial
```
werden. Schlimm genug, dass ich dafür schon den Dateinamen ändern muss ;-)

Wenn ich jetzt auf dein "MyClass.class" zurückgreife, muss ich an irgendeiner Stelle im Programm ja nochmal den Klassennamen ändern - und das wollte ich eigentlich vermeiden.



> Derjenige, der den Code vor Augen hat weiss ja um welche Klasse es sich handelt.


...aber  der ist halt faul...



> Ist doch völlig sinnlos dafür eine eigene Funktion von der JVM bzw. Api zu verlangen.


...und Faule haben da u.U. ganz andere Prioritäten...



> Oder findest du auf die Frage wer du selbst bist auch manchmal keine Antwort ohne in den Spiegel, ein Foto oder den Reisepass zu sehen?


Das hängt dann davon ab, ob ich mich im NormalZustand.java befinde, oder im IchHabGeradeEineLangeNachtHinterMirZustand.java  :bahnhof:


----------



## ms (18. Mrz 2008)

Für sowas gibt es doch die Refactoring-Funktion zB. in Eclipse. Da werden bei einer Änderung des Klassennamens gleich alle Referenzen, Imports usw. mitgeändert.

ms


----------



## Beni (18. Mrz 2008)

Wieso übergibst du beim Programmstart nicht einfach einen String der sagt, was das Programm tun soll?

"java MeinProgramm normal" würde der main-Methode einen String-Array mit dem Inhalt "normal" übergeben...


----------



## Guest (19. Mrz 2008)

fehlerfinder hat gesagt.:
			
		

> SlaterB hat gesagt.:
> 
> 
> 
> ...


----------



## Guest (19. Mrz 2008)

fehlerfinder hat gesagt.:
			
		

> Die Möglichkeit, über getStackTrace() an die Info zu kommen zeigt, dass es geht, erscheint mir aber noch nicht so richtig gelungen bzw. so ein wenig "hintenrum".



hmmm, ich glaube die Lösung über den Stacktrace ist nicht hintenrum. Wenn eine Methode static ist heißt das ja, dass sie keiner Instanz zugeordnet ist.
Also fällt das auf jedenfall als Zugriffsmöglichkeit raus. (Wie auch schon ein Vorposter geschrieben hat.)
Eine Klasse selbst ist zur Ausführungszeit eigentlich nur eine "abstrakte" Struktur die Variablen und Methoden zusammen fasst. Ähmmm, wo wollte ich drauf raus .... Ja also eine statische Methode hat keinen wirklichen Bezug zur Klasse, sie steht da zwar drin aber das ist wohl eher als eine technische Notwendigkeit, damit du die Methode aufrufen (adressieren) kannst. In Java muss ja alles immer in einer Klasse sein. (schau dir dazu mal C/C++ im Vergleich an). Die Methode "nutzt" Quasi nur den Namensraum der Klasse.
Also bleibt in dieser Situation nur noch der Ausführungsstack, dieser enthält die Adressen in denen sich der Thread gerade befindet. Das ist genau genommen auch die Umgebung in der sich diese Methode befindet.

Wenn du so faul bist solltest du dich mit diesem Umstand zufrieden geben und nimmer weiter drüber nachdenken. Falls du das als kleine Denksportaufgabe siehst (das Problem hat mich im ersten Momment auch verschickt  :bahnhof: ) kannst du dich ja mal näher mit den Eigenschaften von Instanzen/Klassen/Heap/Stack beschäftigen. Dann wird mein wirres Zeugs hier vielleicht einwenig klarer.


----------



## ms (19. Mrz 2008)

Anonymous hat gesagt.:
			
		

> Eine Klasse selbst ist zur Ausführungszeit eigentlich nur eine "abstrakte" Struktur die Variablen und Methoden zusammen fasst. Ähmmm, wo wollte ich drauf raus .... Ja also eine statische Methode hat keinen wirklichen Bezug zur Klasse, sie steht da zwar drin aber das ist wohl eher als eine technische Notwendigkeit, damit du die Methode aufrufen (adressieren) kannst. In Java muss ja alles immer in einer Klasse sein. (schau dir dazu mal C/C++ im Vergleich an). Die Methode "nutzt" Quasi nur den Namensraum der Klasse.


Eine Klasse ist zur Ausführungszeit mehr als nur eine abstrakte Struktur. Sie hält sehrwohl Informationen über sich selbst, deren Methoden und Felder (auch statische).
Sonst würde wohl Reflection nicht funktionieren.

ms


----------



## fehlerfinder (19. Mrz 2008)

Beni hat gesagt.:
			
		

> "java MeinProgramm normal"


Ja, sowas hatte ich mir als "Ersatzmöglichkeit" auch schonmal überlegt. Dann würden allerdings beide Klassen gleich heißen und ich wollte unter allen Umständen ausschließen, dass die "Spezial"-Variante versehentlich über den "Normal"-Klassennamen aufgerufen wird (ich bin nicht nur faul (bin ich eigentlich gar nicht, sonst würde ich mich ja nicht so damit geschäftigen...), sondern auch manchmal ein wenig zerstreut. Und deswegen soll es die "Spezial"-Funktion nur in der Klasse mit dem "Spezial"-Namen geben.


----------



## fehlerfinder (19. Mrz 2008)

ms hat gesagt.:
			
		

> Refactoring-Funktion zB. in Eclipse


Meine "Entwicklungsumgebung" heißt vi (für alle Windows-Ausschließlich-Nutzer: ein Texteditor). Das geht mir immer noch am schnellsten von der Hand (hab eh nichts mit GUIs zu tun). Aber du hast natürlich Recht. Wenn ich einen String auf "KlasseNormal" oder "KlasseSpezial" setze, kann ich mit equals genau meinen speziellen Code-Block abfragen. Wäre auch noch eine Lösung, mit der ich per "suchen & ersetzen" arbeiten könnte.


----------



## fehlerfinder (19. Mrz 2008)

Anonymous hat gesagt.:
			
		

> Falls du das als kleine Denksportaufgabe siehst[...]Eigenschaften von Instanzen/Klassen/Heap/Stack beschäftigen. Dann wird mein wirres Zeugs hier vielleicht einwenig klarer.


"Denksportaufgabe" trifft's schon ganz gut. Ich denke mir halt, es müsste doch eigentlich möglich sein. Und von "wirr" kann ja auch keine Rede sein. Das kommt schon alles klar rüber.

Allerdings - wie ms weiter unten bemerkt - ist halt die Frage, ob es sich bei einer Klasse wirklich nur um eine "abstrakte Struktur" handelt. Das will nicht so recht zu dem Eindruck passen, den ich von Java als "Gesamtkunstwerk" habe. Da bleibt wohl nur ein Blick auf die Eigenschaften...


----------



## maki (19. Mrz 2008)

Halte deine angestrebte Lösung für unsauber, da eignet sich das strategy/state Muster besser zu.


----------



## Guest (29. Mrz 2008)

Wie wärs mit folgender Idee:
Du implementierst einen neuen ClassLoader  und dieser injected beim Laden der fraglichen Klasse das passende Class object. Der Code dazu würde im groben so aussehen:



```
public class InjectingClassLoader extends ClassLoader 
{


protected Class loadClass(String name,  boolean resolve)
{
      Class clazz = super.loadClass(name, resolve);
      
      // bestimme hier welche Klasse injected wird. 
      // Elegantere Alternative wäre das markieren der Klasse oder des Felds mittels einer Annotation
      // deren Existenz hier überprüft werden könnte.
      if ( clazz.getName().equals("Test") )
      {
          // inject via reflection clazz auf statisches Feld Test.currentClass
          clazz.getField("currentClass").set(null,clazz);
      }
      return clazz;
}

}


public class Test {

    public static Class currentClass;


    public static void willBeCalled()
    {
      System.out.println(currentClass.getName());
    }
}


public class Launcher {

      public static void main(String[] args)
      {
            ClassLoader loader = new InjectingClassLoader();
            Test test = (Test)loader.loadClass("Test", true).newInstance();
             test.willBeCalled();
      }

}
```


----------

