具有继承性的静态和动态类型 - Java中的细微之处?

Rya*_* Yu -3 java inheritance

所以我有这个相关的代码......

public class PokemonTrainer {
    private Pokemon p = new Squirtle();
    private String name;

    public PokemonTrainer(String name) {
        this.name = name;
    }

    public static void main(String[] args) {
        PokemonTrainer pt = new PokemonTrainer("Ash");
        try {pt.fightGary();}

        catch (Charmander c) {
            System.out.println("You were roasted by a Charmander.");
        }

        catch (Squirtle s) {
            System.out.println("You were drowned by a Squirtle.");
        }

        catch (Bulbasaur b) {
            System.out.println("You were strangled by a Bulbasaur.");
        }

        catch (Pokemon p) {
            System.out.println("You survived!");
        }
    }

    public void fightGary() throws Pokemon {
        throw p;
    }

public class Pokemon extends Exception {}
public class Bulbasaur extends Pokemon {}
public class Squirtle extends Pokemon {}
public class Charmander extends Pokemon {}
Run Code Online (Sandbox Code Playgroud)

为什么打印"你被一个Squirtle淹死了"?

在我的推理中,"catch"是一种方法,当一个对象被传递给一个方法时,该方法根据对象的STATIC TYPE - 即"Pokemon"进行评估,在这种情况下 - 这在下面说明简短的例子:

public class PokemonTrainer {
    private Pokemon p = new Squirtle();
    private String name;

    public PokemonTrainer(String name) {
        this.name = name;
    }

    public static void main(String[] args) {
        PokemonTrainer pt = new PokemonTrainer("Ash");
        pt.fightGary(pt.p); // ------------ Prints "Pokemon!!!"
    }

    public void fightGary(Pokemon p) {
        System.out.println("Pokemon!!!");
    }

    public void fightGary(Squirtle s) {
        System.out.println("Squirtle!!!");
    }
}
Run Code Online (Sandbox Code Playgroud)

那么这两个例子有什么不同呢?为什么第一个例子打印出它的作用?

谢谢!

Jon*_*eet 8

在我的推理中,"捕获"是一种方法

这是第一个错误.catch不是一种方法,并试图把它想象成它会导致你的问题.

它是一种具有自己规则的语言结构.您应该阅读语言规范部分14.20例外教程以获取更多信息.

简而言之,当您有一系列catch块时,将执行与抛出异常的执行时间类型匹配的第一个块.(编译器将阻止您在更具体的异常之前捕获更一般的异常.)

所以如果你有:

try {
  doSomething();
} catch (FileNotFoundException e) {
  ...
} catch (IOException e) {
  ...
}
Run Code Online (Sandbox Code Playgroud)

然后,如果doSomething()抛出FileNotFoundException它将执行第一个catch块(并且只有那个) - 而如果它抛出任何其他类型IOException,它将执行第二个catch块.任何其他异常都将在堆栈中传播.