Har jag förstått skillnaden mellan Throws och Throw med exception handling

Permalänk
Medlem

Har jag förstått skillnaden mellan Throws och Throw med exception handling

Har googlat och googlat, läst i böcker och blogginlägg men jag är ändå inte säker på att jag förstår skillnaden mellan dessa nyckelord. Så här har jag fattat det:

Man använder Try catch då programmet kan hantera exception själv.

Throw då man vill notifiera användare att ett exception inträffat, användaren måste lösa det själv. (detta är nästan som att inte ha exception handling alls). Har även läst att man använder Throw då man vill kasta ett exception direkt. Men jag förstår inte riktigt poängen med detta?

Throws är bara om man vill handla exception i en annan del, t ex en annan metod eller klass. Men man måste fånga det någon gång. Uppfyller nästan samma funktion som try/catch.

Har jag förstått detta rätt eller är jag ute och cyklar?

Permalänk
Medlem
Skrivet av Baxtex:

Har googlat och googlat, läst i böcker och blogginlägg men jag är ändå inte säker på att jag förstår skillnaden mellan dessa nyckelord. Så här har jag fattat det:

Man använder Try catch då programmet kan hantera exception själv.

Throw då man vill notifiera användare att ett exception inträffat, användaren måste lösa det själv. (detta är nästan som att inte ha exception handling alls). Har även läst att man använder Throw då man vill kasta ett exception direkt. Men jag förstår inte riktigt poängen med detta?

Throws är bara om man vill handla exception i en annan del, t ex en annan metod eller klass. Men man måste fånga det någon gång. Uppfyller nästan samma funktion som try/catch.

Har jag förstått detta rätt eller är jag ute och cyklar?

throws signalerar att en metod kan kasta ett exception. throw är raka motsatsen till ett try/catch-block som används för att hantera eventuellt kastade exceptions. "användaren" i ditt exempel är programmeraren som jobbar mot kod som eventuellt slänger exceptions, och som kan välja att hantera det med en try/catch-sats.

I Java är reglerna för detta extra strikta iom konceptet "checked exceptions" vilket innebär att man måste deklarera throws … i metoder från vilka man slänger exceptions. Anroparen av metoden måste gardera sig mot eventuella exceptions genom att antingen fånga dem i en try-catch eller slänga dem vidare med throw. Exceptions som slängs vidare på detta vis måste de återigen deklareras i metodsignaturen.

Korrigerade och förtydligade
Visa signatur

Kom-pa-TI-bilitet

Permalänk
Medlem

Utöver ovan helt korrekta och utmärkta svar:

Råder lite olika filosofier kring det, men för att tillägga enligt min egen filosofi:

Ett exception är när något oförutsett orsakar ett katastrofalt fel som skulle få programmet att crasha. Om det händer, vill man ofta fånga felet, isolera det, skriva ner till felloggen för att sen försöka köra vidare.

Om felet inte är oförutsägbart, skall det inte resultera i ett exception, utan det skall hanteras i vanlig kod, typ if/else - Helst skall man ju se till att situationen aldrig uppstår.

Eftersom det finns lite olika skolor på hur man ska använda throw/catch, "throwar" vissa bibliotek eller metoder ett exception som resultat - Exempelvis "Cannot connect to server". - Personligen tycker ju jag att det är ett fel som är synnerligen förutsägbart och bör hanteras med ens egen error handling och inte kasta ett exception, men det spelar faktiskt egentligen inte så stor roll.

Se bara till att ett try/Catch aldrig används för att hantera logik där en vanlig if/else funkar lika bra då att kasta ett exception är mångfaldigt mycket tyngre att rulla än en vanlig logisk operation.

Permalänk
Medlem
Skrivet av Teknocide:

throws signalerar att en metod kan kasta ett exception. throw är raka motsatsen till ett try/catch-block som används för att hantera eventuellt kastade exceptions. "användaren" i ditt exempel är programmeraren som jobbar mot kod som eventuellt slänger exceptions, och som kan välja att hantera det med en try/catch-sats.

I Java är reglerna för detta extra strikta iom konceptet "checked exceptions" vilket innebär att man måste deklarera throws … i metoder från vilka man slänger exceptions. Anroparen av metoden måste gardera sig mot eventuella exceptions genom att antingen fånga dem i en try-catch eller slänga dem vidare med throw. Exceptions som slängs vidare på detta vis måste de återigen deklareras i metodsignaturen.

Skrivet av Ernesto:

Utöver ovan helt korrekta och utmärkta svar:

Råder lite olika filosofier kring det, men för att tillägga enligt min egen filosofi:

Ett exception är när något oförutsett orsakar ett katastrofalt fel som skulle få programmet att crasha. Om det händer, vill man ofta fånga felet, isolera det, skriva ner till felloggen för att sen försöka köra vidare.

Om felet inte är oförutsägbart, skall det inte resultera i ett exception, utan det skall hanteras i vanlig kod, typ if/else - Helst skall man ju se till att situationen aldrig uppstår.

Eftersom det finns lite olika skolor på hur man ska använda throw/catch, "throwar" vissa bibliotek eller metoder ett exception som resultat - Exempelvis "Cannot connect to server". - Personligen tycker ju jag att det är ett fel som är synnerligen förutsägbart och bör hanteras med ens egen error handling och inte kasta ett exception, men det spelar faktiskt egentligen inte så stor roll.

Se bara till att ett try/Catch aldrig används för att hantera logik där en vanlig if/else funkar lika bra då att kasta ett exception är mångfaldigt mycket tyngre att rulla än en vanlig logisk operation.

Okej, så om jag förstått rätt:

Try/Catch och Throws gör alltså egentligen samma sak, bara att man med throws kan fånga exceptionet i en annan del av koden? Och Throw använder man när explicit vill kasta ett exception. Säg t ex att jag har en array med 5 element(0-4) och vill anropa ett 6 element(som inte finns) då kan jag använda t ex Throw(IndexOutOfBoundsException e). men precis som du säger är det ju något som egentligen hade kunnat hanteras av ett if/else statement.

Tycker det är svårt att veta vilka exceptions som är checked vs !checked, men Eclipse brukar kunna hjälpa till där.

Permalänk
Medlem
Skrivet av Baxtex:

Okej, så om jag förstått rätt:

Try/Catch och Throws gör alltså egentligen samma sak, bara att man med throws kan fånga exceptionet i en annan del av koden? Och Throw använder man när explicit vill kasta ett exception. Säg t ex att jag har en array med 5 element(0-4) och vill anropa ett 6 element(som inte finns) då kan jag använda t ex Throw(IndexOutOfBoundsException e). men precis som du säger är det ju något som egentligen hade kunnat hanteras av ett if/else statement.

Tycker det är svårt att veta vilka exceptions som är checked vs !checked, men Eclipse brukar kunna hjälpa till där.

Jag skulle inte säga att de gör samma sak eftersom de inte ersätter varandra på något vis. Snarare kompletterar de varandra eftersom du inte kan slänga ett exception utan att sätta throws, och inte kan hantera ett slängt exception utan try/catch.

Om du försöker nå element fem i en array som har fyra element så kommer ett IndexOutOfBoundsException att slängas; att slänga ett sådant exception själv är ingenting du vanligtvis gör själv men om du skriver en egen datastruktur och vill ha den funktionaliteten så skulle det passa. Det är inte särskilt vanligt att man försöker fånga ett sånt exception heller, då det vanligtvis slängs när man skrivit fel någonstans i sin kod.

Skriv lite kod och testa själv hur de olika nyckelorden fungerar!

Visa signatur

Kom-pa-TI-bilitet

Permalänk
Medlem
Skrivet av Teknocide:

Jag skulle inte säga att de gör samma sak eftersom de inte ersätter varandra på något vis. Snarare kompletterar de varandra eftersom du inte kan slänga ett exception utan att sätta throws, och inte kan hantera ett slängt exception utan try/catch.

Om du försöker nå element fem i en array som har fyra element så kommer ett IndexOutOfBoundsException att slängas; att slänga ett sådant exception själv är ingenting du vanligtvis gör själv men om du skriver en egen datastruktur och vill ha den funktionaliteten så skulle det passa. Det är inte särskilt vanligt att man försöker fånga ett sånt exception heller, då det vanligtvis slängs när man skrivit fel någonstans i sin kod.

Skriv lite kod och testa själv hur de olika nyckelorden fungerar!

Fast det kan jag väl? Har använt Try/catch block många gånger utan att använda throws. Men på andra håller har jag använt det flera gånger, som här t ex:

public void run() { IconProducer producer; while(!Thread.interrupted()) { try { producer = buffer.get(); populateProducerToConsole(producer); } catch (InterruptedException e) { break; } } } private void populateProducerToConsole(IconProducer producer) throws InterruptedException { Icon icon; for(int times=0; times<producer.times(); times++) { for(int index = 0; index<producer.size(); index++) { icon = producer.nextIcon(); System.out.println(icon.toString() + ", w=" + icon.getIconWidth() + ", h=" + icon.getIconHeight()); Thread.sleep(producer.delay()); } } }

I detta fallet är run överskuggad från den ärvda klassen Thread. Som jag förstår detta ifall metoden populateProducerToConsole slänger ett InterruptedException kommer det fångas i run metoden.

Medans det t ex i denna koden här inte behöver en throws:

public void findRemoteIP(String str) { try { InetAddress remoteAddress = InetAddress.getByName(str); remoteHostIP.setText( "Remote Host: " + remoteAddress.getHostName() + " IP: " + remoteAddress.getHostAddress()); } catch (UnknownHostException e) { JOptionPane.showMessageDialog(null, "Ogiltlig address"); } }

Och ja, precis som du säger är mitt tidigare exempel inte något man vanligvis ska göra, bara det första jag kom på.

Permalänk
Medlem
Skrivet av Baxtex:

Okej, så om jag förstått rätt:

Try/Catch och Throws gör alltså egentligen samma sak, bara att man med throws kan fånga exceptionet i en annan del av koden?

Nej det är inte samma sak. Du lägger till Throws på metoden TestX för att visa att metoden kan kasta ett exception. Det innebär att andra metoder som använder metoden TestX dels får kännedom om att fel kan inträffa men också måste hantera felet på ett eller annat sätt.
Egentligen är det lite märkligt, om du skriver en metod som du vet kan råka kasta fel, då känner du redan till situationen och kan ta hand om det. Men olika synsätt i olika läror... och det finns för och nackdelar med bägge.

Throw innebär att du kastar ett exception.

Notera här en skillnad mot c# som dels inte har Throws, men om du i c# tar emot ett exception ex och väljer att kasta ex vidare så förlorar du stacktrace. Tar du i c# emot ett exception i en catch(exception ex) så kanske du log.Error(ex) men sen skriver du throw; och inte throw ex;
Nämner detta för att jag sett många utvecklare göra den missen.

Visa signatur

Intel Core i7 8700K, MSI GeForce GTX 1080 Ti 11GB Gaming X, Samsung 960 EVO 1TB, MSI Z370 GAMING M5, Corsair 32GB (4x8GB) DDR4 3200MHz CL16 Vengeance, EVGA Supernova G3 850W

INTEL CORE I7 3930K 3.20GHZ 12MB S-2011, FRACTAL DESIGN MIDITOWER DEFINE R3, CORSAIR HX 1050W, ASUS RAMPAGE IV FORMULA, Asus STRIX GTX970, CORSAIR 16GB DDR3 DOMINATOR QUAD 1866MHZ CL9 (4X4GB) Ljud: ASUS Xonar D2X/XDT 7.1 | Elac 5.1 +förstärkare | Cambridge dacmagic plus | Astro gaming A40 | Sennheiser HD 650
You ask me if I have a god complex? Let me tell you something, I am god!

Permalänk
Medlem
Skrivet av Baxtex:

Fast det kan jag väl? Har använt Try/catch block många gånger utan att använda throws. Men på andra håller har jag använt det flera gånger, som här t ex:

public void run() { IconProducer producer; while(!Thread.interrupted()) { try { producer = buffer.get(); populateProducerToConsole(producer); } catch (InterruptedException e) { break; } } } private void populateProducerToConsole(IconProducer producer) throws InterruptedException { Icon icon; for(int times=0; times<producer.times(); times++) { for(int index = 0; index<producer.size(); index++) { icon = producer.nextIcon(); System.out.println(icon.toString() + ", w=" + icon.getIconWidth() + ", h=" + icon.getIconHeight()); Thread.sleep(producer.delay()); } } }

I detta fallet är run överskuggad från den ärvda klassen Thread. Som jag förstår detta ifall metoden populateProducerToConsole slänger ett InterruptedException kommer det fångas i run metoden.

Medans det t ex i denna koden här inte behöver en throws:

public void findRemoteIP(String str) { try { InetAddress remoteAddress = InetAddress.getByName(str); remoteHostIP.setText( "Remote Host: " + remoteAddress.getHostName() + " IP: " + remoteAddress.getHostAddress()); } catch (UnknownHostException e) { JOptionPane.showMessageDialog(null, "Ogiltlig address"); } }

I dina exempel ovan är throws deklarerad på Thread.sleep samt InetAddress.getByName

Det är den som skriver metoden — vilket kan vara du själv — som deklarerar throws. Den som använder en sådan metod kan använda try/catch för att fånga det. Om det är ett checked exception så måste man deklarera try/catch, eller throws på den metod som anropar metoden som slänger exception (precis som du gjort på metoden populateProducerToConsole)

Visa signatur

Kom-pa-TI-bilitet

Permalänk
Medlem
Skrivet av Teknocide:

I dina exempel ovan är throws deklarerad på Thread.sleep samt InetAddress.getByName

Det är den som skriver metoden — vilket kan vara du själv — som deklarerar throws. Den som använder en sådan metod kan använda try/catch för att fånga det. Om det är ett checked exception så måste man deklarera try/catch, eller throws på den metod som anropar metoden som slänger exception (precis som du gjort på metoden populateProducerToConsole)

Aha, men då tror jag att jag förstår det! Den som har skrivit t ex klassen InetAddress har deklarerat throws på t ex getByName metoden. Så nu när jag använder en instans av det måste jag fånga exceptionet, via ett try/catch någonstans i min kod?

Samma sak i det övre exempelt, fast där har jag gjort det själv. Alltså deklarerat att metoden kan kasta ett exception och sedan väljer jag att fånga det i en metod som använder metoden som kan kasta det?

Permalänk
Medlem
Skrivet av Baxtex:

Aha, men då tror jag att jag förstår det! Den som har skrivit t ex klassen InetAddress har deklarerat throws på t ex getByName metoden. Så nu när jag använder en instans av det måste jag fånga exceptionet, via ett try/catch någonstans i min kod?

Samma sak i det övre exempelt, fast där har jag gjort det själv. Alltså deklarerat att metoden kan kasta ett exception och sedan väljer jag att fånga det i en metod som använder metoden som kan kasta det?

Antingen fånga det eller slänga det vidare. Om du väljer att slänga det vidare innebär det att du måste deklarera att den metod som innehåller kodsnutten också kastar detta exception. Det är detta du gjort i din andra kodsnutt, kanske omedvetet.

Visa signatur

Kom-pa-TI-bilitet