Empresas
Empregos
  • Sobre nós
  • Soluções
    • Publicação de vagas
      Publique sua vaga e receba candidatos qualificados em 48h.
    • Avaliações de candidatos
      Mais de 500 testes técnicos e psicológicos, mais anti-fraude.
    • Headhunting
      Busca executiva personalizada do início ao fim.
    • Folha de Pagamento + EOR
      Dispersão de folha e EOR em mais de 15 países da LATAM.
  • Preços
  • Empregos

0

156
Visualizações
Type Inference resolution procedure involving throws clause in Java

Consider the following article in JLS §18.1.3 - Bounds

Here when we try to identify the set of bounds on the inference variables - we have one of the following situations:

...

  • throws α: The inference variable α appears in a throws clause.

...

A bound of the form throws α is purely informational: it directs resolution to optimize the instantiation of α so that, if possible, it is not a checked exception type.

I think this statement is incorrect:

  • this is because ideally the throws clause is mentioned to take care of checked exceptions which can happen during the course of execution of the code.
  • Then why still the JLS preventing α to be a Checked Exception?
  • Ideally the inference variable α must be bounded to be an exception of Checked type rather than being an Unchecked variant.

Is my understanding correct here or am I missing something?

over 4 years ago · Santiago Trujillo
2 Respostas
Responde à pergunta

0

I think your interpretation/understanding of this statement is slightly misguided:

A bound of the form throws α is purely informational: it directs resolution to optimize the instantiation of α so that, if possible, it is not a checked exception type.

That line is referring to the resolution, which, as I understand it, is not about where throws α is, but about where α is inferred, conceivably the invocation of the method.

Consider this class:

static class MyClass {

    public static void main(String[] args) {
        MyClass.<RuntimeException>something(0); // same as MyClass.something(1);

        try {
            MyClass.<IOException>something(2);
        } catch (IOException ex) {
            // checked exception
        }
    }

    /**
     * Will throw IOException if argument is 2, a RuntimeException otherwise
     */
    static <T extends Exception> void something(int a) throws T {
        if (a == 2) {
            throw (T) new IOException(); //of course it's a bad cast
        } else {
            throw (T) new Exception();
        }
    }
}

After analyzing the two something method, focus on the invocation in the main method:

The call MyClass.<IOException>something(0) expects an IOException. The caller knows it (assume fully documented contract rather than tightly coupled code), and handles the exception.
This already tells you that the variable can be a checked exception, contrary to what you think.

On the contrary, the call MyClass.<RuntimeException>something(0) expects a runtime exception on similar grounds.

How α (T in the above example) is inferred allows the compiler to skip forcing the caller to catch/handle the exception (if it's to look at the bound, which it'd otherwise have to)

Now about the "optimization": The type variable being bounded as extends Exception can reasonably be expected to resolve to a checked exception. But, if the caller knows that it shall be a runtime exception, it can "inform" the compiler that it's going to be a runtime exception. This is what I did by specifying RuntimeException in the type witness (RuntimeException is also the resolved type when no type argument is given explicitly).

We can spend days to interpret "optimization", but at least I as a caller did not have to try/catch the invocation, and I still didn't upset the compiler (first invocation).

over 4 years ago · Santiago Trujillo Relatório

0

Consider this example:

public class Main {

    public static void main(String[] args) {
        foo(() -> System.out.println("Foo"));
    }

    public static <T extends Exception> void foo(ThrowingRunnable<T> runnable) throws T {
        runnable.run();
    }
}

interface ThrowingRunnable<T extends Exception> {
    void run() throws T;
}

During the inference of the type parameter T when calling foo, there will be a "throws" bound on the type variable T, and T is inferred to be RuntimeException. If not for this bound, T would have been inferred as Exception because of the T extends Exception bound. This would have meant that I needed to do:

try {
    foo(() -> System.out.println("Foo"));
catch (Exception e) {
    // This won't be reached!
}

I had to handle the exception, even though all I'm doing in the lambda is printing things! That doesn't seem very nice, does it?

The purpose of this bound is so that if there's no reason for the method to throw a checked exception, it doesn't throw a checked exception, so that you don't have to write so many try...catches all over the place. foo would only throw a checked exception if you do things like:

foo(() -> new FileOutputStream("foo"));

If the effect of the bound were instead to force T to be a checked exception, it wouldn't be very useful at all.

over 4 years ago · Santiago Trujillo Relatório
Responde à pergunta
Encontrar trabalhos remotos

Descubra a nova forma de encontrar um emprego!

melhores empregos
Principais categorias de trabalho
Empresas
Postar vaga Preços Comercial
Jurídico
Termos e Condições Política de privacidade
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomende algumas ofertas para mim
Preciso de ajuda