Eu sei como criar uma referência a um método que tem um String
parâmetro e retorna um int
, é:
Function<String, Integer>
No entanto, isso não funciona se a função gerar uma exceção, digamos que seja definida como:
Integer myMethod(String s) throws IOException
Como eu definiria essa referência?
Respostas:
Você precisará seguir um destes procedimentos.
Se for o seu código, defina sua própria interface funcional que declara a exceção verificada:
e use-o:
Caso contrário, envolva
Integer myMethod(String s)
um método que não declare uma exceção verificada:e depois:
ou:
fonte
Consumer
ouFunction
se usar métodos padrão - veja minha resposta abaixo.(String t) -> myWrappedMethod(t)
, a referência do métodothis::myWrappedMethod
também pode ser usada.Você pode realmente estender
Consumer
(eFunction
etc.) com uma nova interface que lida com exceções - usando os métodos padrão do Java 8 !Considere esta interface (estende
Consumer
):Então, por exemplo, se você tiver uma lista:
Se você quiser consumi-lo (por exemplo, com
forEach
) com algum código que gera exceções, tradicionalmente você configuraria um bloco try / catch:Mas com essa nova interface, você pode instancia-la com uma expressão lambda e o compilador não irá reclamar:
Ou até mesmo faça o elenco para ser mais sucinto !:
Atualização : Parece que há uma parte muito agradável da biblioteca de utilitários do Durian chamada Erros, que pode ser usada para resolver esse problema com muito mais flexibilidade. Por exemplo, na minha implementação acima, defini explicitamente a política de tratamento de erros (
System.out...
outhrow RuntimeException
), enquanto os erros do Durian permitem aplicar uma política em tempo real por meio de um amplo conjunto de métodos utilitários. Obrigado por compartilhar , @NedTwigg !.Uso da amostra:
fonte
Acho que a
Errors
aula de Durian combina muitos dos profissionais das várias sugestões acima.Para incluir o Durian em seu projeto, você pode:
com.diffplug.durian:durian:3.3.0
Throwing.java
eErrors.java
fonte
Isso não é específico do Java 8. Você está tentando compilar algo equivalente a:
fonte
Isenção de responsabilidade: ainda não usei o Java 8, apenas li sobre ele.
Function<String, Integer>
não jogaIOException
, então você não pode colocar nenhum código nelethrows IOException
. Se você está chamando um método que espera aFunction<String, Integer>
, então o lambda que você passa para esse método não pode lançarIOException
, ponto final. Você pode escrever um lambda como este (acho que essa é a sintaxe lambda, não tenho certeza):Ou, se o método para o qual você está passando o lambda é aquele que você mesmo escreveu, você pode definir uma nova interface funcional e usá-la como o tipo de parâmetro em vez de
Function<String, Integer>
:fonte
@FunctionalInterface
anotação não é necessária para que seja utilizável para lambdas. É recomendado para verificação de sanidade embora.Se você não se importa em usar uma lib de terceiros ( Vavr ), você pode escrever
Ele também possui a chamada try monad, que lida com erros:
Por favor, leia mais aqui .
Disclaimer: Eu sou o criador do Vavr.
fonte
Você pode usar invólucro unthrow
ou
fonte
No entanto, você pode criar seu próprio FunctionalInterface que é exibido como abaixo.
implemente-o usando Lambdas ou referências, como mostrado abaixo.
fonte
Você pode.
Estendendo @marcg 's
UtilException
e adicionando genéricos sempre<E extends Exception>
que necessário: dessa forma, o compilador forçará novamente a adicionar cláusulas throw e tudo mais como se você pudesse lançar exceções verificadas nativamente nos fluxos do java 8.fonte
Eu tive esse problema com Class.forName e Class.newInstance dentro de um lambda, então acabei de fazer:
Dentro do lambda, em vez de chamar Class.forName ("myClass"). NewInstance () Acabei de chamar uncheckedNewInstanceForName ("myClass")
fonte
Outra solução usando um wrapper Function seria retornar uma instância de um wrapper do seu resultado, por exemplo, Sucesso, se tudo corresse bem, ou uma instância de, por exemplo, Failure.
Algum código para esclarecer as coisas:
Um caso de uso simples:
fonte
Esse problema também está me incomodando; é por isso que eu criei este projeto .
Com ele você pode fazer:
Há uma totla de 39 interfaces definidas pelo JDK que possuem esse
Throwing
equivalente; aqueles são todos@FunctionalInterface
s utilizados em correntes (a baseStream
, mas tambémIntStream
,LongStream
eDoubleStream
).E como cada um deles estende sua contraparte não lançada, você também pode usá-los diretamente em lambdas:
O comportamento padrão é que, quando seu lambda lançando lança uma exceção verificada, a
ThrownByLambdaException
é lançada com a exceção verificada como causa. Portanto, você pode capturar isso e obter a causa.Outros recursos também estão disponíveis.
fonte
@FunctionalInterface public interface SupplierWithCE<T, X extends Exception> { T get() throws X; }
- dessa maneira, o usuário não precisa capturarThrowable
, mas a exceção específica verificada.ThrownByLambdaException
, você terá a exceção original como causa (ou você pode usarrethrow(...).as(MyRuntimeException.class)
)Throwing.runnable()
e outros, sempre com recursos de encadeamentoJá existem muitas ótimas respostas postadas aqui. Apenas tentando resolver o problema com uma perspectiva diferente. É apenas meus 2 centavos, por favor me corrija se eu estiver errado em algum lugar.
A cláusula Throws no FunctionalInterface não é uma boa ideia
Acho que isso provavelmente não é uma boa ideia para aplicar lances IOException por causa dos seguintes motivos
Isso me parece um anti-padrão para o Stream / Lambda. A idéia é que o chamador decida qual código fornecer e como lidar com a exceção. Em muitos cenários, a IOException pode não ser aplicável ao cliente. Por exemplo, se o cliente estiver obtendo valor do cache / memória em vez de executar a E / S real.
Além disso, as exceções de manipulação nos fluxos se tornam realmente hediondas. Por exemplo, aqui está o meu código, se eu usar sua API
Feio, não é? Além disso, como mencionei no meu primeiro ponto, que o método doSomeOperation pode ou não estar lançando IOException (dependendo da implementação do cliente / responsável pela chamada), mas devido à cláusula throws no seu método FunctionalInterface, sempre preciso escrever o tentar pegar.
O que faço se realmente souber que esta API lança IOException
Então provavelmente estamos confundindo FunctionalInterface com interfaces típicas. Se você souber que essa API lançará IOException, provavelmente também conhecerá algum comportamento padrão / abstrato também. Eu acho que você deve definir uma interface e implantar sua biblioteca (com implementação padrão / abstrata) da seguinte maneira
Mas, o problema try-catch ainda existe para o cliente. Se eu usar sua API no fluxo, ainda preciso lidar com IOException no hediondo bloco try-catch.
Forneça uma API padrão compatível com o fluxo da seguinte maneira
O método padrão usa o objeto consumidor como argumento, que será responsável por lidar com a exceção. Agora, do ponto de vista do cliente, o código ficará assim
Nice né? Obviamente, o logger ou outra lógica de manipulação pode ser usada em vez de Exception :: printStackTrace.
Você também pode expor um método semelhante a https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/CompletableFuture.html#exceptionally-java.util.function.Function- . Significando que você pode expor outro método, que conterá a exceção da chamada de método anterior. A desvantagem é que agora você está tornando suas APIs com estado, o que significa que você precisa lidar com a segurança de threads e que acabará se tornando um problema de desempenho. Apenas uma opção a considerar.
fonte
Stream
exceção gerada foi lançada. Portanto, gosto da ideia de ter um manipulador de exceções e filtrar os resultados que não são válidos. Observe que o MyAmazingAPI é efetivamente umFunctionalInterface
(portanto, você pode adicionar a anotação @FunctionalInterface). Além disso, você pode ter um valor padrão em vez de usarOptional.empty()
.O idioma sneaky throw permite ignorar a
CheckedException
expressão Lambda. O agrupamento de umCheckedException
em aRuntimeException
não é bom para o tratamento estrito de erros.Pode ser usado como uma
Consumer
função usada em uma coleção Java.Aqui está uma versão simples e aprimorada da resposta do jib .
Isso apenas envolve o lambda em uma repetição . Torna o
CheckedException
relançamento qualquerException
que foi lançado em sua lambda.Encontre um código completo e testes de unidade aqui .
fonte
Você pode usar ET para isso. ET é uma pequena biblioteca Java 8 para conversão / conversão de exceção.
Com o ET, fica assim:
ExceptionTranslator
instâncias são thread-safe e podem ser compartilhadas por vários componentes. Você pode configurar regras de conversão de exceção mais específicas (por exemploFooCheckedException -> BarRuntimeException
), se desejar. Se nenhuma outra regra estiver disponível, as exceções marcadas serão automaticamente convertidas emRuntimeException
.(Aviso: sou o autor do ET)
fonte
O que estou fazendo é permitir que o usuário dê o valor que ele realmente deseja em caso de exceção. Então, eu tenho algo parecido com isto
E isso pode ser chamado como:
fonte
Se você não se importa em usar uma biblioteca de terceiros, com cyclops-react , uma biblioteca na qual eu contribuo, você pode usar a API FluentFunctions para escrever
ofChecked utiliza um jOOλ CheckedFunction e retorna a referência suavizada de volta para um JDK padrão (não verificado) java.util.function.Function.
Como alternativa, você pode continuar trabalhando com a função capturada através da API FluentFunctions!
Por exemplo, para executar seu método, tente novamente 5 vezes e registre o status que você pode escrever
fonte
Por padrão, o Java 8 Function não permite gerar exceções e, como sugerido em várias respostas, existem várias maneiras de alcançá-lo, uma maneira é:
Defina como:
E adicione
throws
outry/catch
a mesma exceção no método de chamada.fonte
Crie um tipo de retorno personalizado que irá propagar a exceção verificada. Essa é uma alternativa à criação de uma nova interface que espelha a interface funcional existente com a leve modificação de uma "exceção de lançamento" no método da interface funcional.
Definição
CheckedValueSupplier
CheckedValue
Uso
O que está acontecendo?
Uma única interface funcional que gera uma exceção verificada é criada (
CheckedValueSupplier
). Essa será a única interface funcional que permite exceções verificadas. Todas as outras interfaces funcionais aproveitarãoCheckedValueSupplier
para envolver qualquer código que lança uma exceção verificada.A
CheckedValue
classe manterá o resultado da execução de qualquer lógica que lança uma exceção verificada. Isso evita a propagação de uma exceção verificada até o ponto em que o código tenta acessar o valor que uma instânciaCheckedValue
contém.Os problemas com essa abordagem.
CheckedValue#get()
seja chamada.Consumer et al
Algumas interfaces funcionais (
Consumer
por exemplo) devem ser tratadas de maneira diferente, pois não fornecem um valor de retorno.Função em vez de Consumidor
Uma abordagem é usar uma função em vez de um consumidor, que se aplica ao manipular fluxos.
Escalar
Como alternativa, você sempre pode escalar para a
RuntimeException
. Há outras respostas que cobrem a escalação de uma exceção verificada de dentro de aConsumer
.Não consuma.
Evite todas as interfaces funcionais e use um loop for de boa forma.
fonte
Eu uso uma função de utilitário sobrecarregada chamada
unchecked()
que lida com vários casos de uso.Alguns exemplos de usos
UTILIDADES DE APOIO
fonte
Várias das soluções oferecidas usam um argumento genérico de E para passar o tipo de exceção que é lançada.
Dê um passo adiante e, em vez de passar o tipo de exceção, passe um Consumidor do tipo de exceção, como em ...
Você pode criar várias variações reutilizáveis, as
Consumer<Exception>
quais cobririam as necessidades comuns de tratamento de exceções do seu aplicativo.fonte
Vou fazer algo genérico:
uso:
fonte
Use
Jool Library
ou dizerjOOλ library
a partirJOOQ
. Ele não apenas fornece interfaces manipuladas de exceção não verificadas, mas também fornece à classe Seq muitos métodos úteis.Além disso, ele contém interfaces funcionais com até 16 parâmetros. Além disso, fornece a classe Tuple, usada em diferentes cenários.
Jool Git Link
Especificamente na pesquisa de biblioteca para
org.jooq.lambda.fi.util.function
pacote. Ele contém todas as interfaces do Java-8 com o Checked anexado. Veja abaixo para referência: -fonte
Eu sou o autor de uma pequena biblioteca com alguma mágica genérica para lançar qualquer exceção Java em qualquer lugar, sem a necessidade de capturá-las nem envolvê-las
RuntimeException
.Uso:
unchecked(() -> methodThrowingCheckedException())
fonte: https://github.com/qoomon/unchecked-exceptions-java
fonte
fonte
<code>/<code>
:)