-3

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

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 {}

为什么会打印“你被一只松鼠淹死了”?

在我的推理中,“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!!!");
    }
}

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

谢谢!

4

4 回答 4

8

在我的推理中,“catch”是一种方法

这是第一个错误。catch不是一种方法,并试图将其视为会给您带来麻烦。

它是一种具有自己规则的语言结构。您应该阅读语言规范第 14.20 节异常教程以获取更多信息。

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

因此,如果您有:

try {
  doSomething();
} catch (FileNotFoundException e) {
  ...
} catch (IOException e) {
  ...
}

然后如果doSomething()抛出 aFileNotFoundException它将执行第一个catch块(并且执行那个) - 而如果它抛出任何其他类型的IOException,它将执行第二个catch块。任何其他异常都会向上传播。

于 2012-08-09T07:34:47.783 回答
1

好吧,catch它不是一种方法,而是 Java 语言的一部分。

但要回答你的问题,p是一个例子Squirtle

Pokemon p = new Squirtle();

并且由于有一个catch子句可以捕获 a Squirtle,所以它就是这样做的。

catch (Squirtle s)

如果这条线不存在,更一般的

catch (Pokemon p)

将处理抛出的Squirtle.

于 2012-08-09T07:35:40.357 回答
1

虽然Pokemon p被声明为口袋妖怪,但它被实例化为带有new Squirtle(). 因为它在内部是一个 Squirtle,getClass()当调用它时,会返回 Squirtle.class,所以 try-catch 会在 Pokemon 捕获被检查之前捕获 Squirtle 捕获。

这称为多态性

关于您的推理,catch它不是一种方法,而是一个带有try块的语句,用于声明在抛出某些异常的情况下要做什么。

于 2012-08-09T07:36:35.503 回答
1

您将 的类型reference与 的类型混淆了object

Catch 更像是一个switch对象instanceof

考虑一个更简单的例子

String s = "hello";
Object o = s;

在这种情况下,引用类型oObject,但对象类型String对于两者都是 a so因为它们是同一个对象。

于 2012-08-09T07:37:15.277 回答