Java invocation exceptionhandling

Pagina: 1
Acties:

Onderwerpen


Acties:
  • 0 Henk 'm!

Verwijderd

Topicstarter
Ik ben vrij nieuw met Java en echt object georienteerd programmeren, al gaat het nu redelijk goed. Ik zit een beetje in de knoop met try/catch en runtime geinvokete objecten en exceptions die daaruit voortkomen.

We zijn bezig met een rekenmachine, aan de hand van een soort van eigen soort String bouwen we een post-fix list op die we omzetten tot een Formule boom, daarin staan waardes, variabelen en operators. Om deze boom op te bouwen invoken we tijdens runtime objecten die Formula extenden. Tijdens dit proces kunnen er meerdere dingen verkeerd gaan, zoals dat er te weinig parameters zijn voor een bepaalde operator. Hiervoor hebben we een aantal exceptions gemaakt. Als er iets mis gaat tijdens het constructen van zo'n object geeft hij altijd een InvokeTargetException in plaats van de echte exception die we doorgeven. Hieruit kun je wel de originele exception weer terug halen met getCause() maar nu zie ik door de bomen het bos niet meer. Hier in pseudocode hoe we het ongeveer willen hebben:

code:
1
2
3
4
5
6
7
try {
    Formula rekenFormula = Formula.parseFormula(tokenList);
} catch ( ParseException e ) {
    ParseFoutje();
} catch ( ExecuteException e ) {
    ExecuteFoutje();
}


Formula maakt tijdens het opbouwen van de boom dus nieuwe (ge-extende) Formulas met soms andere Formulas als parameters (bij een operator). Wat moeten we waar gooien, wat moet wat kunnen gooien en waarom geeft Java niet gewoon onze eigen Exceptions als we die gooien. Ik zie echt door de bomen het bos niet meer en ik kan geen duidelijke voorbeelden online vinden. Heel erg bedankt!

Edit: Ik kan de titel niet meer veranderen naar [JAVA] Invocation Exception handling

Acties:
  • 0 Henk 'm!

  • DaRKie
  • Registratie: December 2001
  • Laatst online: 02-09 19:08
Java gaat nooit een exception van jezelf wrappen tenzij je dit zelf doet (of je moest via reflection werken bv)

Beter zou zijn dat je ook even de code achter parseFormula post want daar zal het probleem zitten.

Acties:
  • 0 Henk 'm!

  • hellfighter87
  • Registratie: Mei 2008
  • Laatst online: 11-09 20:54
Java:
1
2
3
4
5
6
7
try {
    Formula rekenFormula = Formula.parseFormula(tokenList);
} catch ( ParseException e ) {
    ParseFoutje();
} catch ( Exception e ) {
    ExecuteFoutje();
}


Zo zou je alle exceptions moeten kunnen afvangen.
Op het moment vang je alleen ExecuteExceptions af maar ik gok dat er een andere exception gegooid word dan die. al heb ik niet echt ervaring met ExecuteExceptions lol.

Als ExecuteExeption iets van jezelf is dan moet je die wel gooien. dus zoiets als throw ExecuteExeption(); en daarvoor moet je wee reen classe makken die exception overerfd en die ExecuteExeption heet :P.

Verder: kan je iets van een DKD / AKD posten zodat je classen structuur duidelijker word :P?

[ Voor 17% gewijzigd door hellfighter87 op 20-06-2010 08:41 ]


Acties:
  • 0 Henk 'm!

Verwijderd

Topicstarter
DaRKie schreef op zondag 20 juni 2010 @ 08:38:
Java gaat nooit een exception van jezelf wrappen tenzij je dit zelf doet (of je moest via reflection werken bv)

Beter zou zijn dat je ook even de code achter parseFormula post want daar zal het probleem zitten.
We werken inderdaad met reflection, dit doen we om realtime classes in te kunnen laden om zo die boom op te kunnen bouwen die uit minstens 200 soorten classes gaat bestaan (waardes, variabelen en ontzettend veel operators met hun eigen class).

Nu is Formula parseFormula zo, dit klopt in ieder geval niet maar ik weet niet hoe het wel moet:

Java:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
    public static Formula parseFormula(TokenList tokenList) throws InvocationTargetException{
    if(tokenList.isEmpty()){
        throw new InvocationTargetException(new ParseException("dit gaat helemaal fout, ding leeg"));
    } else {
        Token token = tokenList.pop();
        if(token.getTokenType().isOperator()){
            Class operatorClass;
            try {
                operatorClass = Class.forName(token.getTokenType().getOperatorName());
                Constructor operatorConstructor = operatorClass.getConstructor(new Class[] {Class.forName("com.mathapp.formula.token.TokenList")});
                Formula formula = (Formula) operatorConstructor.newInstance(new Object[]{tokenList});
                    
                return formula;
            } catch (ClassNotFoundException e) {
                System.out.println("Class niet gevonden: " + token.getTokenType().getOperatorName());
                throw new Error();
            } catch (SecurityException e) {
                e.printStackTrace();
            } catch (NoSuchMethodException e) {
                e.printStackTrace();
            } catch (IllegalArgumentException e) {
                e.printStackTrace();
            } catch (InstantiationException e) {
                e.printStackTrace();
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            } catch (InvocationTargetException e) {
                if (e.getCause() instanceof ParseException) {
                    System.out.println("ParseException");
                }
                e.printStackTrace();
            }
        }else if(token.getTokenType().isNum() || token.getTokenType().isImaginaryUnit()){
            return new ComplexValue((ComplexValue)token.getValue());
        }else if(token.getTokenType().isVar()){
            //Als VAR
        }
    }
    return null;
}


Waar het bijvoorbeeld mis kan gaan is bij het opbouwen van een AddOperator, deze heeft als parameters twee Formulas die hij bij elkaar optelt:

Java:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
public AddOperator(TokenList tokenList) throws ParseException{
    //hier zijn eigen parameters intialiseren;
    //eg. this.parameters[0] = Formula.parseFormula(tokenList);
    
    parameters = new Formula[2];
    try {
        this.parameters[1] = Formula.parseFormula(tokenList);
        this.parameters[0] = Formula.parseFormula(tokenList);
    } catch (InvocationTargetException e) {
        if (e.getCause() instanceof ParseException) {
            throw (ParseException) e.getCause();
        }
    }
}


ExecuteException en ParseException zijn eigen exceptions. Ik zie niet goed wat ik nou waar moet gooien, dit is eigenlijk voor het eerst dat ik exception handling doe en met die InvokeTargetExceptions wordt het er voor mij niet duidelijker op.

EDIT: DKD / ADK ? Weet niet wat dat is.. en googlen helpt me ook niet :P Zal wel een schematische weergave van de structuur zijn oid?

Acties:
  • 0 Henk 'm!

  • DaRKie
  • Registratie: December 2001
  • Laatst online: 02-09 19:08
Java:
1
throw new InvocationTargetException(new ParseException("dit gaat helemaal fout, ding leeg"));
Als er iets mis gaat tijdens het constructen van zo'n object geeft hij altijd een InvokeTargetException in plaats van de echte exception die we doorgeven. Hieruit kun je wel de originele exception weer terug halen met getCause() maar nu zie ik door de bomen het bos niet meer
Als je zelf al je eigen exception in een InvocationTargetException wrapped, dan is het natuurlijk logisch dat je InvocationTargetException binnenkrijgt :)

Volgens de TS wil je dit bekomen:
Java:
1
2
3
4
5
6
7
try {
    Formula rekenFormula = Formula.parseFormula(tokenList);
} catch ( ParseException e ) {
    ParseFoutje();
} catch ( ExecuteException e ) {
    ExecuteFoutje();
}


Dit betekent dus dat je parseFormula methode er voor moet zorgen dat andere exceptions gecatched worden en dan naar gelang de situatie fix je het probleem of gooi je 1 van je eigen exceptions.

Dus zonder verder je code bestudeerd te hebben, zou je dit kunnen doen:
Java:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
  public static Formula parseFormula(TokenList tokenList) throws ParseException, ExecutionException { 
    if(tokenList.isEmpty()){ 
        throw new ParseException("dit gaat helemaal fout, ding leeg"); 
    } else { 
        Token token = tokenList.pop(); 
        if(token.getTokenType().isOperator()){ 
            Class operatorClass; 
            try { 
                operatorClass = Class.forName(token.getTokenType().getOperatorName()); 
                Constructor operatorConstructor = operatorClass.getConstructor(new Class[] {Class.forName("com.mathapp.formula.token.TokenList")}); 
                Formula formula = (Formula) operatorConstructor.newInstance(new Object[]{tokenList}); 
                     
                return formula; 
            } catch (Throwable t) { 
        // als er IETS fout gaat ...
        throw new ExecuteException(t);
            } 
        }else if(token.getTokenType().isNum() || token.getTokenType().isImaginaryUnit()){ 
            return new ComplexValue((ComplexValue)token.getValue()); 
        }else if(token.getTokenType().isVar()){ 
            //Als VAR 
        } 
    } 

    // ik gooi hier jou ParseException: ik veronderstel als je code hier is de parsing mislukt is?
    throw new ParseException();
}

Acties:
  • 0 Henk 'm!

  • Macros
  • Registratie: Februari 2000
  • Laatst online: 15-05 16:29

Macros

I'm watching...

Je gebruikt reflection. Als het geen opdracht van school was waarbij je reflection moest gebruiken, dan zou ik geen reflection gebruiken.

In plaats van dat je een Constructor maakt en aanroept kan je beter een factory class gebruiken.
Dus dan maak je een Factory class, die aan de hand van de OperatorName een Formula of Operator maakt.

Ik heb ook wel eens zoiets gemaakt, en toen gaf ik de children, (of tokenList bij jou ofzo) niet mee met de constructor, maar later mee. Dan in de (abstracte) super klasse Formule (of interface) kan je dan de children bijhouden en die kan je dan setten op een later moment. Als je dan teveel of te weinig children set, dan kan je een foutmelding opgooien tijdens runtime, dus als je de formule berekend.

Dus dan heb je twee stappen.

1. parse de formule, en maak met een factory klass en wat parsing een tree van objecten.
2. die tree van objecten bereken je door bijvoorbeeld een visitor op die tree te gebruiken (google visitor pattern)

Het voorbeeld dat je gaf dat er iets mis gaat omdat er niet genoeg parameters zijn, komen dan pas naar voren als je in stap 2, de executie bent.

Het parsen van de formule gooit dan alleen ParseExceptions en het executen van de formule gooit dan alleen ExecutionExceptions.

Als je perse de check wil doen voor het execution wil doen, kan je een extra stap tussen 1 en 2 voegen, die de formule valideerd.

Ik hoop dat je me een beetje snapt.

"Beauty is the ultimate defence against complexity." David Gelernter

Pagina: 1