# instanceof vermeiden



## Johannes L. (27. Mai 2007)

Hallo,

wie kann man am besten instanceof Operatoren vermeiden? Ich rufe Methoden auf, wobei man innerhalb der Methode prüfen muss um welches Objekt es sich handelt um nur richtig zu casten und halt zu schauen welches Objekt null ist.

Also innerhalb der Methode:


```
/**
	 * Get the status-line and the Headers.
	 * 
	 * @param to_client
	 * 	Output text stream.
	 * @param method
	 *  The method used.
	 */
	private void getResponseHeader(PrintWriter to_client, Object method)
	{
		Header[] headers = null;
		
		if(method instanceof GetMethod)
		{
			to_client.print(((GetMethod) method).getStatusLine().toString()+"\r\n");
			to_client.flush();
		
			headers = ((GetMethod) method).getResponseHeaders();
		}
		else if(method instanceof HeadMethod)
		{
			to_client.print(((HeadMethod) method).getStatusLine().toString()+"\r\n");
			to_client.flush();
			
			headers = ((HeadMethod) method).getResponseHeaders();
		}
		else if(method instanceof PostMethod)
		{
			to_client.print(((PostMethod) method).getStatusLine().toString()+"\r\n");
			to_client.flush();
			
			headers = ((PostMethod) method).getResponseHeaders();
		}
		
		for(Header header : headers)
		{
			logger.debug("Header: "+header.toString());
			to_client.print(header.toString());
			to_client.flush();
		}
		
		to_client.print("\r\n");
		to_client.flush();
	}
```

Wobei ich mir da gar nicht so wirklich sicher bin, ob es überhaupt Sinn macht das in eine Methode auszulagern oder eher gleich in jeden Case-Block zu schreiben.

Viele Grüsse,
Johannes


----------



## Roar (27. Mai 2007)

```
private void getResponseHeader(PrintWriter to_client, HttpMethod method)
   {
      Header[] headers = method.getResponseHeaders();
      
        to_client.print(method.getStatusLine().toString()+"\r\n");
         to_client.flush();
      
      for(Header header : headers)
      {
         logger.debug("Header: "+header.toString());
         to_client.print(header.toString());
         to_client.flush();
      }
      
      to_client.print("\r\n");
      to_client.flush();
   }
```
?

edit: außerdem ist die methode sinnlos benannt
edit2: und warum schreibst du das ganze zeug selber in den stream :?:


----------



## SlaterB (27. Mai 2007)

wenn das deine eigenen Klassen sind, dann fasse sie in ein Interface zusammen 
mit Operationen wie getType() oder isTypePostMethod() oder ähnliches,
dann kannst du einfache ints oder boolean vergleichen,
was etwas performanter ist, 

letztlich wirst du aber um das if-else-Konstrukt + Cast nicht vorbeikommen, falls du das ganze nicht generell generischer lösen kannst,

wenn z.B. getResponseHeaders() im Interface angegeben wäre,
müsstes du wohl gar nicht casten/ nach den Typ fragen


----------



## Johannes L. (27. Mai 2007)

Naja, es ist ein Proxyserver und ich muss ja die ganzen Daten, die ich vom httpclient kriege an den Client weiterschicken. Wie kann ich das sonst weiterleiten?


----------



## JPKI (27. Mai 2007)

Eventuell mit getClass().getName()?


----------



## Marco13 (28. Mai 2007)

JEDE Typabfrage ist eine Kapitulation vor der Objektorientierung - und getClass().getName() ist sogar noch ein bißchen schlimmer  :autsch:  Aber Roar hat die Lösung ja schon genannt :roll:


----------



## André Uhres (28. Mai 2007)

Marco13 hat gesagt.:
			
		

> JEDE Typabfrage ist eine Kapitulation vor der Objektorientierung..


Trotzdem sollte man *instanceof * sinnvoll einsetzen. 
Jede equals-Methode, die Object#equals überschreibt, sollte z.B. eine solche Typabfrage haben:

```
public boolean equals(Object o){
  if(!(o instanceof MyType)){
    return false;
  ...
}
```
 :wink:


----------



## Marco13 (28. Mai 2007)

Soweit ich mich erinnere sind sogar in den original Java-Sourcen von Sun einige "equals" Methoden so implementiert

```
public boolean equals(Object otherObject)
{
    try
    {
        ThisClass other = (ThisClass)otherObject;
         ...
    }
    catch (ClassCastException e)
    {
         return false;
    }
}
```
Ich wollte nur andeuten: Man _braucht_ instanceof nicht. Und wenn doch, dann ist es ein Modellierungs"fehler". ("Fehler" in Anführungszeichen, weil JEDER an irgendeinem Punkt kapituliert, und der Aufwand mit instanceof u.U. um Größenordnungen geringer sein kann, als mit einer "richtigen" Modellierung)


----------



## Leroy42 (28. Mai 2007)

Ist das _instanceOf_ in Java zu vergleichen mit
_respondsTo: "methodenname"_ in Smalltalk?


----------



## André Uhres (29. Mai 2007)

Marco13 hat gesagt.:
			
		

> Soweit ich mich erinnere sind sogar in den original Java-Sourcen von Sun einige "equals" Methoden so implementiert
> 
> ```
> public boolean equals(Object otherObject)
> ...


Das würde mich sehr wundern, weil das recht unperformant ist. 
Man braucht 'instanceof' wohl doch dazu :wink:

Der 'instanceof' Operator erlaubt es zu festzustellen, ob ein bestimmtes Casten erlaubt ist, ohne es erst zu versuchen. 
Da die Perfomance viel besser ist als bei einer ClassCastException, ist es allgemein günstig,
eine 'instanceof' Abfrage zu machen, wenn man nicht sicher ist, ob der Typ einer Referenz so ist, wie man will. 
Zuvor sollte man sich allerdings überlegen, ob man vernünftig mit einem ungewollten Typ umgehen kann.
Andernfalls wäre es besser, die Exception werfen zu lassen, um sie auf einer höheren Ebene zu behandeln.


----------



## Marco13 (29. Mai 2007)

Es IST aber so. Nur ... wie oft vergleicht man auch z.B. zwei FontRenderContext-Objekte...? :? Jedenfalls stellt sich für mich dann die Frage, ob "equals" überhaupt mit Objekten unterschiedlicher Klassen aufgerufen werden sollte !? ...


----------

