Exceções verificadas e não
Em suma, são necessárias exceções para separar o cenário positivo (quando tudo está indo bem) do negativo (quando ocorre um erro e o cenário positivo é interrompido). Isso é útil porque, muitas vezes, há poucas informações no código para tratar o erro e você precisa transmitir informações sobre o que aconteceu acima.
Por exemplo, existe uma função para ler um número de um arquivo (ou não um número, não importa):
String readStoredData(String id) throws FileNotFoundException, IOException {
File file = new File(storage, id + ".dat");
try (BufferedReader in = new BufferedReader(new FileReader(file))) {
return in.readLine();
}
}
Como você pode ver, não há nenhum código aqui que decida o que fazer em caso de erro. E não está claro o que fazer - encerrar o programa, retornar "", nulo ou outra coisa? Portanto, as exceções são declaradas throws
e serão tratadas em algum lugar do chamador:
int initCounter(String name) throws IOException, NumberFormatException {
try {
return Integer.parseInt(readStoredData(name));
} catch (FileNotFoundException e) {
return 0;
}
}
As exceções em Java são divididas em marcadas e não marcadas. Neste caso, IOException
ele é verificado - você deve declará-lo throws
e então processá-lo em algum lugar, o compilador irá verificar. NumberFormatException
não verificável - seu processamento permanece na consciência do programador e o compilador não controlará você.
Há também um terceiro tipo de exceção - erros fatais ( Error
), mas geralmente não faz sentido lidar com eles, então você não deve se preocupar com eles.
, – , .
:
;
( – ) .
- , . .
Scala?
Scala: ( ), .
Try[T]
– , , . Scala:
def readStoredData(id: String): Try[String] =
Try {
val file = new File(storage, s"$id.dat")
val source = Source.fromFile(file)
try source.getLines().next()
finally source.close()
}
def initCounter(name: String): Try[Int] = {
readStoredData(name)
.map(_.toInt)
.recover {
case _: FileNotFoundException => 0
}
}
, , readStoredData
String
, Try[String]
– . Try Java – , .
:
(
Either[Error, T]
, );
happy-path , (
Try/get
for/map/flatMap
);
Java - , ( Java , ).
( Try[String]
– ). Option[T]
– , Future[T]
– ..
, – . / Java, ( ).
:
FileNotFoundException
,
IOException
–
:
def readStoredData(id: String): Option[Try[String]] = {
val file = new File(storage, s"$id.dat")
if (file.exists()) Some(
Try {
val source = Source.fromFile(file)
try source.getLines().next()
finally source.close()
}
)
else None
}
Option[Try[String]]
, , :
None
–
Some(Success(string))
–
Some(Failure(exception))
– ,
Try
. Java , null. .
A abundância de tipos cria mais ruído visual e geralmente requer um código mais complexo ao trabalhar com vários efeitos ao mesmo tempo. Mas, em troca, ele fornece código autodocumentado e permite que o compilador encontre muitos erros.