31、简述Java的异常处理机制。

Java对异常进行了分类,不同类型的异常分别使用了不同的Java类表示,所有异常的父类为java.lang.Throwable,Throwable类下面派生了两个子类:Error和Exception,Error表示应用程序本身无法克服和恢复的一种严重问题;Exception表示程序还能够克服和恢复的问题,其中Exception又分为系统异常和普通异常,系统异常是软件本省缺陷所导致的问题,也就是软件开发人员考虑不周所导致的问题,软件使用者无法克服和恢复这种问题,但在这种问题下还可以让软件系统继续运行或者让软件死掉,例如,数组下标越界异常(ArrayIndexOutOfBoundException),空指针异常(NullPointerException)、类转换异常(ClassCastException);普通异常是软件运行环境的变化或者异常所导致的问题,是用户可以克服的问题,比如网络断线、磁盘空间不足等,发生这样的异常时,程序不应该死掉。


Java为系统异常和普通异常提供了不同的解决方案,编译器要求普通异常必须使用try...catch处理或者throws声明继续抛给上层调用方法处理,所以普通异常也称为checked异常,而系统异常可以处理也可以不处理,编译器不强制使用try...catch处理或者throws声明,所以系统异常也称为unchecked异常。


32、说出下面程序的输出结果

public class StringEqualTest {

    public static void main(String[] args) {

        String s1 = "Programming";

        String s2 = new String("Programming");

        String s3 = "Program";

        String s4 = "ming";

        String s5 = "Program"+ "ming";

        String s6 = s3 + s4;

        System.out.println(s1 == s2);

        System.out.println(s1 == s5);

        System.out.println(s1 == s6);

        System.out.println(s1 == s6.intern());

        System.out.println(s2 == s2.intern());

    }

}

依次输出:false、true、false、true、false。s1和s2分别是两个不同对象的引用,这个两个对象里面的内容相同,但却不是一个对象,所以地址不同,第一个为false,无需过多解释;利用+直接连接两个字符串常量,虚拟机会直接把这两个字符串连接起来看成一个字符串,所以s1 == s5返回true;利用+连接两个引用,虚拟机看成StringBuilder,会创建一个StringBuilder对象,然后调用append方法进行追加操作,最后调用toString方法转换成String,所以s1 == s6返回false; String对象的intern()方法会得到字符串对象在常量池中对应的版本的引用(前提是常量池中已有一个字符串与String对象的equals结果为true),所以s1 == s6.intern()返回true;同理,s2.intern()是和s6.intern()相同的,所以最后一个的执行结果是false,因为s1 == s2返回的就是false。


33、Java的基本数据类型及各自所占字节数。

byte             1               boolean             1


short            2               char                  2


int                4               float                  4


long             8               double              8


比较记忆会更快噢。注意:String不是基本数据类型,String是引用类型,String的底层是使用char数组实现的。


34、short s1 = 1; s1 = s1 + 1; 有错吗?short s1 = 1; s1 += 1;有错吗?

前者不正确,后者正确。对于short s1 = 1; s1 = s1 + 1;由于1是int类型,因此s1+1运算的结果也是int类型,需要强制类型转换后才可以赋值给short型。而short s1 = 1; s1 += 1;可以正确编译,因为s1 += 1;相当于s1 = (short)(s1 + 1),里面已经包含了强制类型转换。


35、int和Integer有什么区别?

Java是一个近乎纯洁的面向对象编程语言,但是为了编程的方便还是引入了基本数据类,为了可以将这些基本数据类型当成对象来操作,Java为每一个基本数据类型都又引入了对应的包装类型,int的包装类型就是Integer。从Java5开始又引入了自动装箱/拆箱机制,使得二者可以相互转换。


原始类型:boolean,char,byte,short,int,long,float,double


包装类型:Boolean,Character,Byte,Short,Integer,Long,Float,Double


自动装箱/拆箱机制:


Integer a = new Integer(3);

Integer b = 3;                //自动装箱为Integer类型

int c = 3;                                        

System.out.println(a == b);   //输出false,两个引用没有指向同一个对象

System.out.println(a == c);   //true,自动拆箱成int类型进行比较

36、下面Integer类型的数值比较的结果为?

Integer f1 = 100,f2 = 100,f3 = 150,f4 = 150;

System.out.println(f1 == f2);

System.out.println(f3 == f4);

输出:true,false。首先需要注意的是,f1,f2,f3,f4都是包装类型,所以使用==运算符比较的不是值,而是引用。当我们给一个Integer对象赋一个int值的时候,会调用Integer类的静态方法valueOf,查看valueOf源码我们可以知道,对于整型字面量的值在-128到127之间那么不会new新的Integer对象,而是直接引用常量池中的Integer对象,所以上面第一行输出true,第二行由于150大于了128,故输出false。


public static Integer valueOf(int i) {

        if (i >= IntegerCache.low && i <= IntegerCache.high)

            return IntegerCache.cache[i + (-IntegerCache.low)];

        return new Integer(i);

}

private static class IntegerCache {

        static final int low = -128;

        static final int high;

        static final Integer cache[];

 

        static {

            // high value may be configured by property

            int h = 127;

            String integerCacheHighPropValue =

                sun.misc.VM.getSavedProperty("java.lang.Integer.IntegerCache.high");

            if (integerCacheHighPropValue != null) {

                try {

                    int i = parseInt(integerCacheHighPropValue);

                    i = Math.max(i, 127);

                    // Maximum array size is Integer.MAX_VALUE

                    h = Math.min(i, Integer.MAX_VALUE - (-low) -1);

                } catch( NumberFormatException nfe) {

                    // If the property cannot be parsed into an int, ignore it.

                }

            }

            high = h;

 

            cache = new Integer[(high - low) + 1];

            int j = low;

            for(int k = 0; k < cache.length; k++)

                cache[k] = new Integer(j++);

 

            // range [-128, 127] must be interned (JLS7 5.1.7)

            assert IntegerCache.high >= 127;

        }

 

        private IntegerCache() {}

    }

(越是简单的面试题,里面的玄机就越多,需要面试者相当深厚的基础功)


37、说出String类的常用方法及功能。

int length():返回当前字符串的长度

int indexOf(int ch/String str):用于查找当前字符串中字符或子串,返回字符或子串在当前字符串中从左边起首次出现的位置,若没有出现则返回-1。

int indexOf(int ch/String str, int fromIndex):与上一种类似,区别在于该方法从fromIndex位置向后查找。

int lastIndexOf(int ch/String str):类似,区别在于该方法从字符串的末尾位置向前查找

int lastIndexOf(int ch/String str, int fromIndex):类似,区别于该方法从fromIndex位置向前查找。

String toLowerCase():返回将当前字符串中所有字符转换成小写后的新串

String toUpperCase():返回将当前字符串中所有字符转换成大写后的新串

String replace(char oldChar, char newChar):用字符newChar替换当前字符串中所有的oldChar字符,并返回一个新的字符串。

String replaceFirst(String regex, String replacement):该方法用字符replacement的内容替换当前字符串中遇到的第一个和字符串regex相匹配的子串,应将新的字符串返回。

String replaceAll(String regex, String replacement):该方法用字符replacement的内容替换当前字符串中遇到的所有和字符串regex相匹配的子串,应将新的字符串返回。

String trim():截去字符串两端的空格,但对于中间的空格不处理。

char charAt(int index):获取字符串中指定位置的字符。

String[] split(String regex):将regex作为分隔符进行字符串分解,分解后的字字符串在字符串数组中返回。

38、请说一下数据类型之间的转换

字符串转为基本数据类型:调用基本数据类型对应的包装类中的方法parseXXX(String)或者valueOf(String)既可以返回相应的基本数据类型。

基本数据类型转字符串:一种方法是将基本数据类型与空字符串("")连接(+)即可获得对应的字符串,另一种方法是调用String类中的valueOf()方法返回相应字符串。

39、Java中有几种类型的流?

按照流的方向:输入流(inputStream)和输出流(outputStream);


按照实现的功能分:节点流(可以从或向一个特定的地方(节点)读写数据,例如FileReader)、处理流(是对一个已存在的流的连接和封装,通过所封装的流的功能调用实现数据的读写,例如BufferdReader,处理流的构造方法总是要带一个其他流对象做参数。一个流经过其他流的多次封装,成为流的链接)


按照处理的数据的单位可以分为字节流和字符流。字节流继承于InputStream和OutputStream,字符流继承于InputStreamReader和outputStreamReader。


40、再谈谈String、StringBuffer、StringBuilder之间的区别?

String:字符串常量,再修改时本身不会改变,如修改等于重新生成一个新的字符串对象,String定以后不可改变,故是线程安全的。

StringBuffer:在修改时会改变对象自身,每次修改操作都是对StringBuffer对象本身进行修改,不是生成新的对象,适用于需要经常改变字符串的情形下,由于实现synchronized同步锁(故效率稍慢),是线程安全的,也适用于多线程环境下。

StringBuilder:功能和StringBuffer基本一样,只是没有实现同步锁,不是线程安全的,适用于单线程环境下,执行效率较高。