Java return Problem

abraxus14

Cadet 4th Year
Registriert
Mai 2007
Beiträge
102
Hallo Mitglieder

ich da wieder ein Problem
und zwar will der Compiler nicht starten, obwohl (aus meiner Sicht alle returnfälle abgedeckt sind. Soll heißen Für jeden Fall gibt es eine returnanweisung.
Ich hab das Programm ein wenig vereinfacht damit die if und else Struktur besser herauskommt. Kann mir jemand erklären, wo der Fehler ist?

PHP:
if (zeichen==' ')
                return n;
            if (zeichen=='+' || zeichen=='-' || zeichen)=='/' || zeichen=='+') {
                n.type=´zeichen;
                return n;}

            if (zeichen=='(')
                if (n.left==null) {
                    n.left=p(t);
                    return n;}
                else {
                    n.right=p(t);
                    return n;}
           
            if (zeichen==')')
                return n;
            
            else 
                if (n.left.data==-1) {
                    n.left.data=Character.digit(zeichen,10);
                    return n.left;}
                else {
                    n.right.data=Character.digit(zeichen,10);
                    return n.left;}
 
Code:
[COLOR=#000000][COLOR=#0000BB]zeichen[/COLOR][COLOR=#007700])==[/COLOR][COLOR=#DD0000]'/'[/COLOR][/COLOR]
und
Code:
n.type=´zeichen;
Ich find den code style übrigens echt anstrengend. :D

P.S.: In der zweiten if prüfst du zweimal auf + und nie auf *.
 
Zuletzt bearbeitet:
Woher soll denn der Compiler wissen, dass du mit deinen IF-Abfragen alle Fälle abdeckst? Was soll die Funktion machen, wenn keine der IF-Abfragen passt?
 
Mal so als Anregung:

Code:
        switch (zeichen)
        {
            case ' ':
                return n;
            case '+':
            case '-':
            case '/':
            case '*':
                n.type = zeichen;
                return n;
            case '(':
                if (n.left == null)
                    n.left = p(t);
                else
                    n.right = p(t);
                return n;
            case ')':
                return n;
            default:
                System.err.println("Unknown char detected!");
        }

Natürlich völlig ohne Gewähr, weil ich ja nicht weiß, was du da eigentlich treibst.
 
die Codefehler sind entstanden, da ich wie gesagt, den code ein wenig vereinfacht habe.
Den einzigen Fehler, den der Compiler anzeigt ist der, das er sagt, dass ein return satement fehlt. die anderen Passagen sind richtig bzw wurden von mir falsch hier eingefügt.
Welche returnanweisung ist hier falsch oder welche muss ich einfügen, damit der Compiler alle möglichen fälle als abgedeckt sieht.
 
1. Der Code ist schon rein syntaktisch nicht kompilierbar, es wäre auch nett gewesen, wenn du ihn wenigstens ein bißchen ordentlicher formatiert hättest. Ich hoffe der vollständige Code ist etwas ordentlicher, das hilft dann auch in diesen Situation sehr.

2. Meiner Ansicht nach endet der Codeschnipsel strukturell grundsätzlich bei einer return-Anweisung. Ich gehe davon aus, dass deine Code"vereinfachung" den Fehler behoben hat. Vllt. kannst du den Originalcode zeigen (aber bitte ordentlich formatiert), dann kann man sich das nochmal anschauen.
 
also hier ist der OrginalCode:

PHP:
public class Parser {
    private int pos;
    public Node n;
    boolean links,rechts;

    
    private Node parse(final String t) {
        for (int i=0;i<Main.text.length();i++) {
            pos=i;
            n = new Node();
             
            if (Main.text.charAt(i)==' ')
                return n;
            if (Main.text.charAt(i)=='+' || Main.text.charAt(i)=='-' || Main.text.charAt(i)=='/' || Main.text.charAt(i)=='+') {
                n.type=Main.text.charAt(i);
                return n;}

            if (Main.text.charAt(i)=='(')
                if (n.leftChild==null) {
                    n.leftChild=parse(t);
                    return n;}
                else {
                    n.rightChild=parse(t);
                    return n;}
           
            if (Main.text.charAt(i)==')')
                return n;
            
            else 
                if (n.leftChild.data==-1) {
                    n.leftChild.data=Character.digit(Main.text.charAt(i),10);
                    return n.leftChild;}
                else {
                    n.rightChild.data=Character.digit(Main.text.charAt(i),10);
                    return n.leftChild;}






        
    }}}
 
Ist halt immer noch syntaktisch falsch, bitte korrigier das mal richtig. Außerdem kannst du dir ja mal überlegen was zurückgegeben wird, wenn die Schleife 0 Durchläufe macht.
 
Tumbleweed schrieb:
Mal so als Anregung:

Code:
        switch (zeichen)
        {
            case ' ':
                return n;
            case '+':
            case '-':
            case '/':
            case '*':
                n.type = zeichen;
                return n;
            case '(':
                if (n.left == null)
                    n.left = p(t);
                else
                    n.right = p(t);
                return n;
            case ')':
                return n;
            default:
                System.err.println("Unknown char detected!");
        }

Natürlich völlig ohne Gewähr, weil ich ja nicht weiß, was du da eigentlich treibst.

Solche Switch Anweisungen sehen zwar immer wieder toll aus, aber sollte man meiden. Eine Switch Anweisung sollte man nur zur Überprüfungen bei regelmäßigen Mustern(z.B. 1,2,3,4,5,6 usw.) verwenden.
Bei unregelmäßigen Mustern ist "else if" das geeignete Mittel.

Außerdem benötigt man für den Vergleich von Strings die equals() bzw. compareTo() Methode.
 
Darf ich fragen was der Grund dafür sein soll? :)

Ab Java 7 erlaubt switch übrigens auch strings.
 
Der Grund ist Performance. Ob jetzt wirklich 1zu1 auf Java übertragbar ist weiß ich nicht genau, aber für C/C++ steht in den Developer Guides von AMD und Intel das man dies so machen sollte. Hat dort etwas damit zu tun wie der Compiler den Code übersetzt, was genau weiß ich aber auch nicht mehr.
Ich persönlich finde die "else if" Variante sogar übersichtlicher(solange der Code natürlich gescheit Formatiert ist^^)
 
Fonce schrieb:
Der Grund ist Performance. Ob jetzt wirklich 1zu1 auf Java übertragbar ist weiß ich nicht genau, aber für C/C++ steht in den Developer Guides von AMD und Intel das man dies so machen sollte. Hat dort etwas damit zu tun wie der Compiler den Code übersetzt, was genau weiß ich aber auch nicht mehr.

Ah, Schmarn! Zeig mir mal ein sinnvolles Programm C oder C++ Programm, in dem if/else im Vergleich zu switch einen relevanten (oder überhaupt spürbaren) Unterschied macht. Das ist wieder mal premature optimization vom Feinsten.
Abhängig von der jeweiligen Situation kann es durchaus sinnvoll sein, einem Konstrukt den Vorzug zu geben, aber Performance dürfte nur in den allerseltensten Fällen dieser Grund sein.

Im übrigen solltest du dich hüten, solche Weisheiten von C/C++ auf Java übertragen zu wollen. Das sind ja wohl eindeutig 2 Paar Stiefel.
 
antred schrieb:
Ah, Schmarn! Zeig mir mal ein sinnvolles Programm C oder C++ Programm, in dem if/else im Vergleich zu switch einen relevanten (oder überhaupt spürbaren) Unterschied macht. Das ist wieder mal premature optimization vom Feinsten.
Abhängig von der jeweiligen Situation kann es durchaus sinnvoll sein, einem Konstrukt den Vorzug zu geben, aber Performance dürfte nur in den allerseltensten Fällen dieser Grund sein.

Im übrigen solltest du dich hüten, solche Weisheiten von C/C++ auf Java übertragen zu wollen. Das sind ja wohl eindeutig 2 Paar Stiefel.

Das wo du dich hüten solltest ist Leute hier im Forum länger mit deiner "premature optimization" und deiner Ausdrucksweise zu langweilen. Das einzige was hier premature ist sind deine unqualifizierten Kommentare. Du bist mir damit nämlich schon öfter negativ aufgefallen.

http://support.amd.com/us/Processor_TechDocs/25112.PDF
Kapitel 2.10
 
Abgesehen von schwacher Polemik wieder nix brauchbares von deiner Seite. Du darfst mich aber jederzeit eines besseren belehren, indem du einfach (wie oben schon erwähnt) folgendes tust:

"Zeig mir mal ein sinnvolles Programm C oder C++ Programm, in dem if/else im Vergleich zu switch einen relevanten (oder überhaupt spürbaren) Unterschied macht."
Ergänzung ()

Man programmiert erst mal den simplesten, natürlichsten Algorithmus. Leicht lesbarer, verständlicher Code sollte da im Vordergrund stehen. Wenn sich dann rausstellt, daß die Performance den Anforderungen nicht genügt, schnappt man sich einen Profiler, findet raus, wo viel Rechenzeit verloren geht und optimiert eben diese Stellen. Man legt sich nicht auf if/else oder switch fest, weil "es schneller ist".
 
Okay, dann ist es aber in diesem konkreten Fall völlig in Ordnung eine switch-Anweisung zu benutzen, da die char-Werte contiguous sind. ;) Naja gut, das Leerzeichen nicht, aber das könnte man auch vorher abfangen.

Find ich aber trotzdem interessant, davon hatte ich bisher noch nichts gehört.
 
Zuletzt bearbeitet:
Im Übrigen muss ich antred zustimmen.

Es ist auch nicht so, dass aus jeder Anwendung das letzte an Leistung rausgekitzelt werden muss - wenn dem so ist, dann sollte man kein Java nehmen...

Es gibt durchaus Fälle, bei denen Wartbarkeit wichtiger als Leistung ist.

Edit:
Und nochmal an die Optimierer:
"Because the case expressions in the following switch statement are not contiguous values, the
compiler will likely translate the code into a comparison chain instead of a jump table:"
Compiler werden auch optimiert vom Hersteller... ich würde echt mal Benchmarks machen, vermutlich wird kein Unterschied bei beiden Variaten in der JRE festgestellt...


Edit2:
Code:
public class Parser { 
     
    public static int parseIf(char c) { 
        if (c==' ') {
            return -1; 
        } else if (c=='+' || c=='-' || c=='/' || c=='*') { 
            return 0;
        } else if (c=='(') { 
            return 1;
        } else if (c==')') { 
            return 2;
        } else {
        	return 3;
        }
    }

    public static int parseSwitch(char c) {
    	switch (c) {
    	case ' ':
    		return -1;
    	case '+':
    	case '-':
    	case '/':
    	case '*':
            return 0;
    	case '(':
            return 1;
    	case ')':
            return 2;
        default:
        	return 3;
    	}
    }
    
    public static void main(final String[] args) {
    	String s = "+-/()((()))/**/*/-/-*-//*//*-/-*/*-/-*/*/*-/-*/++/+/+/+/+/+/+/+//**/+//+/+/*/*32/*+/+/*/+/+//*+/*/+*";
   
    	final long loops = 5000000;

    	// um Seiteneffekte zu vermeiden...
    	for (long i = 0; i < loops; i++) {
    		for (int j = 0; j < s.length(); j++) {
    			parseSwitch(s.charAt(j));
    			parseIf(s.charAt(j));
    		}
    	}

    	// Messen
    	long startI = System.currentTimeMillis();
    	for (long i = 0; i < loops; i++) {
    		for (int j = 0; j < s.length(); j++) {
    			parseIf(s.charAt(j));
    		}
    	}
    	long endI = System.currentTimeMillis();

    	long startS = System.currentTimeMillis();
    	for (long i = 0; i < loops; i++) {
    		for (int j = 0; j < s.length(); j++) {
    			parseSwitch(s.charAt(j));
    		}
    	}
    	long endS = System.currentTimeMillis();
       	
    	System.out.println("If: " + (endI - startI) + " Switch: " + (endS - startS));
    }
}

spuckt bei mir aus:
If: 4346 Switch: 4125

d.h. das sind 4,3 vs 4,1 Sekunden, und das bei 500.000.000 aufrufen an meinem Rechner... wenn der Leistungsunterschied hier nicht mal von essentieller Bedeutung ist...
Ach ja: Das Switch ist hier wohlgemerkt schneller in dem Fall...
 
Zuletzt bearbeitet:
Sehe ich genau so, die "Optimierung" bringt rein garnichts. Ist zwar schön, wenn man es so gut machen will wie es nur geht, aber das wäre am falschen Ende begonnen.
 
Ich denke da rumzufummeln im Namen der Performance ist Zeitverschwendung. In Effective Java wird auch explizit davon abgeraten (mit 3 Zitaten unterlegt).
Rein von der Übersicht her finde ich zumindest in diesem konkreten Beispiel switch deutlich besser. Vor allem wegen fall through wird die Sache recht kompakt.
 
Zurück
Oben