Java——谜题

1、谜题36  try和finally语句,代码如下,判断输出

public class Indecisive {
    public static void main(String[] args) {
        System.out.println(decision());
    }
    static boolean decision() {
        try {
            return true;
        } finally {
            return false;
        }
    }
}

最后的输出为false,为什么呢?这是因为try的异常结束(例如return,break,continue,throws)是不会影响finally语句块的执行。

2、谜题37 考察try catch的规则掌握程度

public class Arcane1 {
    public static void main(String[] args) {
        try {
            System.out.println("Hello world");
        } catch(IOException e) {
            System.out.println("I‘ve never seen
               println fail!");
        }
    }
}

这段代码看着会编译通过,但是实际上编译都不能通过。这里就考察到被检查异常的一个基本原则。try里的代码println执行IO,但是它不能抛出IOException异常,而catch里检查的异常就是IOException,所以会出现编译不通过。语言规范中描述道:如果一个catch子句要捕获一个类型为E的被检查异常,而其相对应的try子句不能抛出E的某种子类型的异常,那么这就是一个编译期错误[JLS 11.2.3]。

public class Arcane2 {
    public static void main(String[] args) {
        try {
            // If you have nothing nice to say, say nothing
        } catch(Exception e) {
            System.out.println("This can‘t
                happen");
        }
    }
}

这段代码,如果你看了上面的,你肯定会以为编译不通过,可是他的编译 是通过的。为什么呢?因为Catch里捕捉的是Exception,捕获这个异常在规则里是合法的。尽管是一个合法程序,因为没有触发这个异常,所以catch里仍然不会执行。

interface Type1 {
    void f() throws CloneNotSupportedException;
}

interface Type2 {
    void f() throws InterruptedException;
}

interface Type3 extends Type1, Type2 {
}

public class Arcane3 implements Type3 {
    public void f() {
        System.out.println("Hello world");
    }
    public static void main(String[] args) {
        Type3 t3 = new Arcane3();
        t3.f();
    }
}

每一个接口都限制了方法f可以抛出的被检查异常集合。一个方法可以抛出的被检查异常集合是它所适用的所有类型声明要抛出的被检查异常集合的交集,而不是合集。因此,静态类型为Type3的对象上的f方法根本就不能抛出任何被检查异常。因此,Arcane3可以毫无错误地通过编译,并且打印Hello world。

总之,第一个程序说明了一项基本要求,即对于捕获被检查异常的catch子句,只有在相应的try子句可以抛出这些异常时才被允许。第二个程序说明了这项要求不会应用到的冷僻案例。第三个程序说明了多个继承而来的throws子句的交集,将减少而不是增加方法允许抛出的异常数量。本谜题所说明的行为一般不会引发难以捉摸的bug,但是你第一次看到它们时,可能会有点吃惊。

3、谜题40  不情愿的构造器

构造方法中抛出异常并不常见,下面的代码就是这样,思考下会打印出什么?

public class Reluctant {
    private Reluctant a = new Reluctant();
    public Reluctant() throws Exception {
        throw new Exception("I‘m not coming out");
    }
    public static void main(String[] args) {
        try {
            Reluctant b = new Reluctant();
            System.out.println("Surprise!");
        } catch (Exception ex) {
            System.out.println("I told you so");
        }
    }
}

运行之后,什么也没打印,报错误——StackOverflowError异常(属于Error,不属于Exception,所以catch不能捕捉)。为什么呢?这是因为,当你调用构造器时,实例化变量的初始化操作会先于构造器的程序体运行。在上述代码中,a变量的初始化调用了构造器,而构造器需要调用自身去完成初始化操作,所以就造成了一个递归。

对于一个对象包含与它自己类型相同的实例的情况,并不少见。例如,链接列表节点、树节点和图节点都属于这种情况。你必须非常小心地初始化这样的包含实例,以避免StackOverflowError异常。

总之,实例初始化操作是先于构造器的程序体而运行的。实例初始化操作抛出的任何异常都会传播给构造器。最后,对于我们所设计的类,如果其实例包含同样属于这个类的其他实例,那么对这种无限递归要格外当心。

4、谜题41 域和流

这个想给的结论就是:当你在finally语句块中调用close方法时,要用一个嵌套的try-catch语句来保护它,以防止IOException的传播。更一般地讲,对于任何在finally语句块中可能会抛出的被检查异常都要进行处理,而不是任其传播。

5、操作符

逻辑AND操作符&   条件AND操作符&& 区别:前者必须计算两个操作数之间的与关系     后者当前边的操作数为false时,就直接返回false,不在考虑后边操作数的真假。

逻辑OR操作符|     条件OR操作符||   区别:前者必须计算两个操作数之间的或关系  后者当前边的操作数为true时,就直接返回true,不考虑后边的。

时间: 2024-10-27 04:05:20

Java——谜题的相关文章

Java谜题——库谜题

1.Java中的不可变对象和可变对象 (1)不可变类:当你获得这个类的实例的引用之后,你不可以改变这个实例的内容.比如:String,BigInteger,BigDecimal,还有基本数据类型的封装类,这些都是不可变类.用实例来调用方法时,不会改变里面的变量的值.代码: import java.math.BigInteger; public class BigProblem { public static void main(String[ ] args) { BigInteger fiveT

Java谜题——类谜题(二)

1.域的隐藏 代码如下: class Base { public String className = "Base"; } class Derived extends Base { private String className = "Derived"; } public class PrivateMatter { public static void main(String[ ] args) { System.out.println(new Derived().

Java进阶1(Java 谜题)

1. //判断奇偶数 public static boolean isOdd(int i){ return i % 2 != 0; } 2. //减法精确 public static BigDecimal jian(String s1,String s2){ BigDecimal jian=new BigDecimal(s1). subtract(new BigDecimal(s2)); return jian; } 3. //长整除算法 public static void  chu(){ f

java异常面试常见题目

在Java核心知识的面试中,你总能碰到关于 处理Exception和Error的面试题.Exception处理是Java应用开发中一个非常重要的方面,也是编写强健而稳定的Java程序的关键,这自然使它成为面试题中的常客.关于Java中Error和Exception的面试题目多是关于Exception和Error的概念,如何处理Exception,以及 处理Exception时需要遵守的最佳实践等等.尽管关于多线程.垃圾回收.JVM概念和面向对象设计等方面的问题依然主宰着这类面试,你仍然需要为回答

Java的Exception和Error面试题10问10答

在Java核心知识的面试中,你总能碰到关于 处理Exception和Error的面试题.Exception处理是Java应用开发中一个非常重要的方面,也是编写强健而稳定的Java程序的关键,这自然使它成为面试题中的常客.关于Java中Error和Exception的面试题目多是关于Exception和Error的概念,如何处理Exception,以及 处理Exception时需要遵守的最佳实践等等.尽管关于多线程.垃圾回收.JVM概念和面向对象设计等方面的问题依然主宰着这类面试,你仍然需要为回答

[变]C#谜题(1-10)表达式篇

[变]C#谜题(1-10)表达式篇 最近偶然发现了<Java谜题>,很有意思,于是转到C#上研究一下. 本篇是关于表达式的一些内容. 谜题1:奇数性(负数的取模运算) 下面的方法意图确定它那唯一的参数是否是一个奇数.这个方法能够正确运转吗? 1 public static bool isOdd(int i) 2 { 3 return i % 2 == 1; 4 } 奇数可以被定义为被2 整除余数为1 的整数.表达式 i % 2 计算的是 i 整除 2时所产生的余数,因此看起来这个程序应该能够正

10.Java异常问题

目录介绍 10.0.0.1 见过哪些运行时异常?异常处理机制知道哪些?从异常是否必须需要被处理的角度来看怎么分类? 10.0.0.2 运用Java异常处理机制?异常处理的原理?Java中检查异常和非检查异常的区别? 10.0.0.3 异常处理的过程中,你遵循那些好的实践? throw 和 throws这两个关键字在java中有什么不同? 10.0.0.4 你知道什么是"异常链"吗?自定义实现过哪些异常,怎么写的?可以有一个空的catch块吗? 10.0.0.5 Java异常类有哪些的重

java解惑之字符之谜(谜题22)

谜题22:URL的愚弄 本谜题利用了一个java编程语言中一个鲜为人知的特性.请考虑下面的程序将会做什么? public class BrowerTest{ public static void main(String[] args){ System.out.ptintln("iexplore"); http://www.google.com; System.out.println(":maximize"); } } 这是个有点诡异的问题.当我们初次看到这个程序时,

java解惑之字符之谜(谜题16)

谜题16:行打印程序 行分隔符是为分割文本行的字符或字符串而起的名字,并且在不同平台上它是存在差异的.在windows平台上,它由CR字符(回车)和紧随其后的LR(换行)字符组成.在UNIX平台上,通常引用单独的LF字符作为换行字符.那么,这次的谜题也就由行分隔符引出,来看看下面这个将LF字符传递给println方法的程序会打印什么,它的行为是否依赖于平台? public class LinePrinter{ public static void main(String[] args){ //N