zoukankan      html  css  js  c++  java
  • Java笔试面试题整理第八波


    转载至:http://blog.csdn.net/shakespeare001/article/details/51388516
    作者:山代王(开心阳)
    本系列整理Java相关的笔试面试知识点,其他几篇文章如下:

    1、运算符相关

    What results from the following code fragment?
    1. inti = 5;  
    2. intj = 10;  
    3. System.out.println(i + ~j);  
    inti = 5;
    intj = 10;
    System.out.println(i + ~j);
    A、Compilation error because”~”doesn’t operate on integers    B、-5    C、-6    D、15

    正确答案:C
    解法一:公式 -n=~n+1可推出~n=-n-1,所以~10=-11再加5结果为-6
    解法二:计算机中以补码存储。
    正数的原码/反码/补码相同,所以
    10存储为00000000 00000000 00000000 00001010  
    ~10的原码为11111111 11111111 11111111 11110101(10取反)
    ~10的反码为10000000 00000000 00000000 00001010(最高位符号位,不变,其余位取反)
    ~10的补码为10000000 00000000 00000000 00001011(负数的补码=反码+1)
    所以~10 = -11

    &&和&,||和|的区别:
        &&是逻辑与(短路与),当第一个判断条件不满足要求时(返回false),第二个判断条件就不会执行;只有当两个判断条件都返回true时,整个逻辑运算才返回true。
        &按位与,不论什么情况下,两边的判断条件都会执行,当两边都返回true时,按位与才返回true。

        ||逻辑或,当第一个判断条件返回true时,逻辑或直接返回true,第二个判断条件就不会执行了;
        |按位或,不论什么情况下,两边的判断条件都会执行,当有一个条件返回true时,按位或就返回true。

    注意:
        逻辑与、逻辑或两边的运算符必须是boolean类型的,而按位与、按位或可以是boolean类型,两边也可以是int类型的。
        当按位与、按位或两边是int类型时,将是通过二进制进行按位运算,规则就是:
        (1)按位与&:都为1时,返回1,其他情况返回0;
        (2)按位或|:有一个为1时,返回1,都为0时才返回0;
    如下例子:3&2=2,3|2=3
    3–>0011
    2–>0010
    &–>0010=2
    |–>0011=3

    2、泛型相关

    泛型在编译时期进行严格的类型检查,消除了绝大多数的类型转换。泛型在集合中使用广泛,在JDK1.5之后集合框架就全部加入了泛型支持。在没有使用泛型之前,我们可以往List集合中添加任何类型的元素数据,因为此时List集合默认的元素类型为Object,而在我们使用的时候需要进行强制类型转换,这个时候如果我们往List中加入了不同类型的元素,很容易导致类型转换异常。如下例子:        
    1. List list = new ArrayList();  
    2.         list.add(18);  
    3.         list.add(”lly”);  
    4.         for(Object obj : list){  
    5.             int i = (int) obj;//此处运行后,将会报错  
    6.         }  
    List list = new ArrayList();
            list.add(18);
            list.add("lly");
            for(Object obj : list){
                int i = (int) obj;//此处运行后,将会报错
            }
        上面在将“lly”转成int时,会报ClassCastException,但是在编译时却不会出错。(在我们JDK1.5之后有了泛型之后,但是没有去使用泛型来定义集合,跟上面的一样效果。),同时,这也验证了我们前面总结异常类型时所说的,ClassCastException是属于运行时异常,也即非检查性异常。
    在我们使用泛型之后,可以避免不必要的转型,以及避免可能出现的ClassCastException,如下:        
    1. List<Integer> list = new ArrayList<Integer>();  
    2.         list.add(18);  
    3.         list.add(”lly”);    //此时,编译时就不能通过,报错!!!  
    List<Integer> list = new ArrayList<Integer>();
            list.add(18);
            list.add("lly");    //此时,编译时就不能通过,报错!!!
    型允许我们在创建集合时就可以指定元素类型,当加入其他数据类型时,编译不能通过。泛型只作用于编译阶段,在编译阶段严格检查类型是否匹配,类型检查通过后,JVM会将泛型的相关信息擦出掉(即泛型擦除),也就是说,成功编译过后的class文件中是不包含任何泛型信息的,泛型信息不会进入到运行时阶段
    如果像我们上面说的这样,那对于传进来的不同数据类型的对象也只会生成一个类型,而不是多种数据类型对象。下面我们可以验证一下:
    1. class Person<T> {  
    2.     private T charac;//人物特征  
    3.     public Person(T ch){  
    4.         this.charac = ch;  
    5.     }  
    6.     public T getCharac() {  
    7.         return charac;  
    8.     }  
    9.     public void setCharac(T charac) {  
    10.         this.charac = charac;  
    11.     }  
    12. }  
    class Person<T> {
        private T charac;//人物特征
        public Person(T ch){
            this.charac = ch;
        }
        public T getCharac() {
            return charac;
        }
        public void setCharac(T charac) {
            this.charac = charac;
        }
    }
    测试:        
    1. Person<String> p1 = new Person<String>(“lly”);  
    2.         Person<Integer> p2 = new Person<Integer>(18);  
    3.         System.out.println(”p1—>”+p1.getClass());  
    4.         System.out.println(”p2—>”+p2.getClass());  
    Person<String> p1 = new Person<String>("lly");
            Person<Integer> p2 = new Person<Integer>(18);
            System.out.println("p1--->"+p1.getClass());
            System.out.println("p2--->"+p2.getClass());
    打印如下:
    p1—>class com.scu.lly.Person
    p2—>class com.scu.lly.Person
    可以看到,虽然我们传入了两种数据类型,但是在编译时并没有生成这两种类型,而都是Person类型,这正是因为我们上面所说的,泛型在编译通过后,确保了类型正确,此后就擦除了相关泛型信息,把所有元素都作为Person数据类型。也就是说,泛型类型在逻辑上我们可以看成是多个不同的数据类型,但是在本质上它只是同一种数据类型

    类型通配符:
    按我们上面的说法,泛型在编译成功后,泛型信息就被擦除,变成了同一个类型。那如何去区分原本具有父子类关系的泛型类型?如下例子:
    我们在上面Person类的基础上,进行测试:
    1. public class CommonTest {  
    2.     public static void main(String[] args) {  
    3.         Person<Number> p1 = new Person<Number>(12);  
    4.         Person<Integer> p2 = new Person<Integer>(18);  
    5.   
    6.         getCharac(p1);  
    7.   
    8.         getCharac(p2);//报错!!!编译不能通过,提示参数类型不符合  
    9.     }  
    10.   
    11.     public static void getCharac(Person<Number> person){  
    12.         System.out.println(person.getCharac());  
    13.     }  
    14. }  
    public class CommonTest {
        public static void main(String[] args) {
            Person<Number> p1 = new Person<Number>(12);
            Person<Integer> p2 = new Person<Integer>(18);
    
            getCharac(p1);
    
            getCharac(p2);//报错!!!编译不能通过,提示参数类型不符合
        }
    
        public static void getCharac(Person<Number> person){
            System.out.println(person.getCharac());
        }
    }
        按照我们的想法,因为Integer 是继承自Number的,根据Java多态的特性,我们调用getCharac(p2);应该是没有问题的,但是正是因为泛型擦除的特点,导致了泛型在编译通过后被擦除了泛型类型,在运行时,JVM根本不知道有Number和Integer这两个类型存在,内存中只会有Person对象存在。这也正是上面不能编译通过的原因。
        为了解决这个问题,也就是说在使用泛型的时候为了能够体现出父子关系(或者说兼容多态特性),提出了类型通配符的概念。类型通配符用 ? 来代替参数类型,代表任何类型的父类比如Person<?>就是Person<Number>和Person<Integer>的父类了,而Person<Number>和Person<Integer>是体现不出父类关系的,现在就可以继续使用多态特性了,如下:
        public static void getCharac(Person<?> person){
            System.out.println(person.getCharac());
        }
    将上面的参数类型改成通配符的形式以后,我们调用getCharac(p2);就不会出错了。

    类型通配符上界和下界:
    继续我们上面的例子,我们的本意是getCharac方法中只能传入数字类型的参数过来,也就是说希望传入的类型参数是Number类型或它的子类,类型通配符上界提供了这种约束。
    类型通配符上界:可以这样定义:Person<? extends Number>,表示我们的参数类型最大是Number类型或者它的子类。继续修改我们的例子:
        public static void getCharac(Person<? extends Number> person){
            System.out.println(person.getCharac());
        }
    测试:
            Person<Number> p1 = new Person<Number>(12);
            Person<Integer> p2 = new Person<Integer>(18);
            Person<String> p3 = new Person<String>(“lly”);
            
            getCharac(p1);
            getCharac(p2);
            getCharac(p3);//报错!!!编译不能通过,提示参数类型不符合
    因为String并不是Number的子类,因此上面也就不能编译通过了

    类型通配符下界:可以这样定义:Person<? super Number>,表示我们的参数类型最小是Number类型,或者是它的超类类型

    下面我们来看一个题目:
    Which three statements are true?
    class A {}
    class B extends A {}
    class C extends A {}
    class D extends B {}
    Which four statements are true ?
    A、The type List<A>is assignable to List.
    B、The type List<B>is assignable to List<A>.
    C、The type List<Object>is assignable to List<?>.
    D、The type List<D>is assignable to List<? extends B>.
    E、The type List<?extends A>is assignable to List<A>.
    F、The type List<Object>is assignable to any List reference.
    G、The type List<?extends B>is assignable to List<?extends A>.

    is assignable to(意为:赋给,转化为)
    正确答案:ACDG
    对于A任何使用了泛型的数据类型,都可以赋给没有使用泛型的数据类型,此时数据类型相当于是Object,如上面我们的一个例子:
        public static void getCharac(Person person){
            System.out.println(person.getCharac());
        }
        测试:
            Person<Number> p1 = new Person<Number>(12);
            Person<Integer> p2 = new Person<Integer>(18);
            Person<String> p3 = new Person<String>(“lly”);
            
            getCharac(p1);
            getCharac(p2);
            getCharac(p3);

    这个时候都能通过。


    由于使用泛型之后,父子关系必须要有通配符来解决。因此CDG正确。B错。

    对于E,说反了,因为上面的is assignable to赋予关系,体现的是多态关系(父子关系);
    对于F,和B一样的错误,虽然Object是任何类型的父类(需要跟A区别开来,A是用没用泛型的比较,这里是都用了泛型之后的比较),但是用了泛型后,父子关系要有通配符来体现。同样List<String>也不能转化为List<Object>。

    3、变量初始化问题

    对于成员变量:
    对于非final修饰的类的成员变量(包括static和非static),如果开发者没有给其赋初值,在编译时,JVM自动会给非final修饰的成员变量赋初值,我们在类的成员方法中就可以直接使用、运算了。
    对于final修饰成员变量,必须在(1)定义的时候初始化,(2)或者在构造方法中初始化(如果类中有多个构造方法,每个构造方法中都需要进行一次初始化),否则编译不通过。这是因为final类型的变量不能修改,必须在初始定义的时候或者new出对象时构造器里进行初始化,其他时候不能变更。

    对于非成员变量,即方法中的临时变量:
    方法中的临时变量,只需要在使用前保证了初始化就可以。不一定要在定义的时候就初始化,但必须要在开始使用这个变量前初始化。

    如下例子:
    1. public class VarTest {  
    2.     final int i ;  
    3.     public VarTest(){    //在构造方法中初始化了  
    4.         i = 3;  
    5.     }  
    6.     public VarTest(int n){ //有多个构造方法,必须在每个构造方法中进行初始化  
    7.         i = n;  
    8.     }  
    9.     public void doSomething() {  
    10.         int j;  
    11.         j = 1;//对于临时变量,如果这里不进行初始化,下面使用++j时编译不能通过  
    12.         System.out.println(++j + i);  
    13.     }  
    14.   
    15.     public static void main(String[] args) {  
    16.         VarTest test = new VarTest();  
    17.         test.doSomething();  
    18.     }  
    19. }  
    public class VarTest {
        final int i ;
        public VarTest(){    //在构造方法中初始化了
            i = 3;
        }
        public VarTest(int n){ //有多个构造方法,必须在每个构造方法中进行初始化
            i = n;
        }
        public void doSomething() {
            int j;
            j = 1;//对于临时变量,如果这里不进行初始化,下面使用++j时编译不能通过
            System.out.println(++j + i);
        }
    
        public static void main(String[] args) {
            VarTest test = new VarTest();
            test.doSomething();
        }
    }

    4、suspend()和resume()方法

    Java.Thread的方法resume()负责重新开始被以下哪个方法中断的线程的执行()?
    A、stop    B、sleep    C、wait    D、suspend

    正确答案:D
    suspend() 和 resume() 方法:两个方法配套使用,suspend()使得线程进入阻塞状态,并且不会自动恢复,必须其对应的 resume() 被调用,才能使得线程重新进入可执行状态

    5、几个需要注意的小知识点

    (1)What is the result of compiling and executing the following fragment of code:
    1. Boolean flag = false;  
    2. if(flag = true){  
    3.     System.out.println(“true”);  
    4. }else{  
    5.     System.out.println(“false”);  
    6. }  
    Boolean flag = false;
    if(flag = true){
        System.out.println(“true”);
    }else{
        System.out.println(“false”);
    }
    A、The code fails to compile at the “if” statement.    B、An exception is thrown at run-time at the “if” statement.
    C、The text“true” is displayed.    D、The text“false”is displayed.    E、Nothing is displayed.

    正确答案:C
    这里主要是要注意,if条件判断中,flag = true先是一个赋值语句,赋值完成后,flag成为逻辑判断条件,会自动拆箱。

    (2)What will happen when you attempt to compile and run the following code?
    1. public class test{  
    2. static{  
    3.    intx=5;  
    4. }  
    5. static int x,y;  
    6. public static void main(String args[]){  
    7.    x–;  
    8.    myMethod( );  
    9.    System.out.println(x+y+ ++x);  
    10. }  
    11. public static void myMethod( ){  
    12.   y=x++ + ++x;  
    13.  }  
    14. }  
    public class test{
    static{
       intx=5;
    }
    static int x,y;
    public static void main(String args[]){
       x--;
       myMethod( );
       System.out.println(x+y+ ++x);
    }
    public static void myMethod( ){
      y=x++ + ++x;
     }
    }
    A、compiletime error    B、prints:1    C、prints:2    D、prints:3    E、prints:7   F、prints:8

    正确答案:D
    注意静态代码块中的语句声明,重新定义了一个局部变量int x = 5,执行完静态代码块后,局部变量就被销毁。此时全局变量x 还是默认值0,执行到打印语句时,x-1,y= 0,对于打印语句System.out.println(x+y+ ++x);中的x+y+ ++x由于+是左结合的,因此x+y+ ++x,即1+0+(++x).

    (3)以下代码将打印出
    1. public static void main (String[] args) {   
    2.     String classFile = ”com. jd. ”. replaceA11(“.”“/”) + “MyClass.class”;  
    3.     System.out.println(classFile);  
    4. }  
    public static void main (String[] args) { 
        String classFile = "com. jd. ". replaceA11(".", "/") + "MyClass.class";
        System.out.println(classFile);
    }
    A、com. jd    B、com/jd/MyClass.class    C、///////MyClass.class    D、com.jd.MyClass

    正确答案:C
    replaceAll方法的第一个参数是一个正则表达式,而“.”在正则表达式中表示任何字符,所以会把前面字符串的所有字符都替换成”/”。如果想替换的只是”.”,那么久要写成”\.”。和replace类似,split()中的参数也是正则表达式,“.”也是关键词,如果想要使用也是要转义。即写成str.split(“\.”)进行转义处理。

    (4)下面将打印出什么结果? 
    1. int b = 127;  
    2.             System.out.println(b);  
    3.             b = b++;  
    4.             System.out.println(b);  
    int b = 127;
                System.out.println(b);
                b = b++;
                System.out.println(b);
    A、127    B、128

    正确答案:A
    要特别注意:b = b++;和b = ++b;这种两种方式,实现b自增,在Java中是没有效果的。对于b = b++;b被赋予b++的结果,之后b并不会再来自增,因此打印127;对于b = ++b;b被赋予++b的结果,之后b也并不会再来自增,因此打印128。

    6、自动拆箱、装箱问题

    (1)下列 java 程序输出结果为______。
    1. inti=0;  
    2. Integer j = newInteger(0);  
    3. System.out.println(i==j);  
    4. System.out.println(j.equals(i));  
    inti=0;
    Integer j = newInteger(0);
    System.out.println(i==j);
    System.out.println(j.equals(i));
    A、true,false    B、true,true    C、false,true    D、false,false    E、对于不同的环境结果不同    F、程序无法执行


    正确答案:B
    对于==来说:
    如果运算符两边有一方是基本类型,一方是包装类型,在进行==逻辑判断时,包装类型会自动进行拆箱操作,因此i==j返回true;
    如果都是包装类型,那么==就是按照正常判断逻辑来,==比较的是对象的地址,但是下面这种情况除外:
        在-128至127这个区间,如果创建Integer对象的时候(1)Integer i = 1; (2) Integer i = Integer.valueOf(1); 如果是这两种情况创建出来的对象,那么其实只会创建一个对象,这些对象已经缓存在一个叫做IntegerCache里面了,所以==比较是相等的。如果不在-128至127这个区间,不管是通过什么方式创建出来的对象,==永远是false,也就是说他们的地址永远不会相等。
    举例测试如下:
             Integer i1 = 8; 
             Integer i2 = 8; 
             Integer i3 = 300; //超过了127这个范围
             Integer i4 = 300; 
             Integer i5 = Integer.valueOf(8);
             Integer i6 = new Integer(8);
    //         System.out.println(i1 == i2);//true, 在-128至127这个区间,Integer i = 1;和Integer i = Integer.valueOf(1); 这两种方式创建的对象相同
    //         System.out.println(i3 == i4);//false ,超过这个区间,创建出的是不同对象
    //         System.out.println(i1 == i5);//true , 在-128至127这个区间,Integer i = 1;和Integer i = Integer.valueOf(1); 这两种方式创建的对象相同
             System.out.println(i1 == i6);//false ,在指定区间,只有上面两种方式创建出的对象才相同,通过new出来的是不相同的

    对于equals来说:
    equals不同的对象由不同的实现,对于Integer来说,equals比较的是值。因此,j.equals(i);返回的是true。

    (2)代码片段: 
    1. byte b1=1,b2=2,b3,b6;   
    2. final byteb4=4,b5=6;   
    3. b6=b4+b5;   
    4. b3=(b1+b2);   
    5. System.out.println(b3+b6);  
    byte b1=1,b2=2,b3,b6; 
    final byteb4=4,b5=6; 
    b6=b4+b5; 
    b3=(b1+b2); 
    System.out.println(b3+b6);
    关于上面代码片段叙述正确的是()
    A、输出结果:13    B、语句:b6=b4+b5编译出错    C、语句:b3=b1+b2编译出错    D、运行期抛出异常


    正确答案:C
    被final修饰的变量是常量,这里的b6=b4+b5可以看成是b6=10;在编译时就已经变为b6=10了
    而b1和b2是byte类型,java中进行计算时候将他们提升为int类型,再进行计算,b1+b2计算后已经是int类型,赋值给b3,b3是byte类型,类型不匹配,编译不会通过,需要进行强制转换
    Java中的byte,short,char进行计算时都会提升为int类型。

    7、finally语句的执行是在return前还是return后

    在try的括号里面有return一个值,那在哪里执行finally里的代码?

    A、不执行finally代码    B、return前执行    C、return后执行

    正确答案:C

    finally语句是在try(或catch)的return语句执行之后,return返回之前执行。过程如下:在try中如果有return语句,他会首先检测是否有fianlly,如果有的话,就保存try中return要返回的值,然后执行finally中的方法,如果fianlly没有返回值,则finally方法执行完毕之后,返回执行try中的return方法,他会取出之前保存的return值,进行返回。
    如下例子:
    1. public static void main(String[] args) {  
    2.         intk = f_test();  
    3.         System.out.println(k);  
    4.     }  
    5.        
    6.     public static int f_test(){  
    7.         inta = 0;  
    8.         try{  
    9.             a = 1;  
    10.             returna;  
    11.         }  
    12.         finally{  
    13.             System.out.println(”It is in final chunk.”);  
    14.             a = 2;  
    15.             returna;  
    16.         }  
    17.     }  
    public static void main(String[] args) {
            intk = f_test();
            System.out.println(k);
        }
    
        public static int f_test(){
            inta = 0;
            try{
                a = 1;
                returna;
            }
            finally{
                System.out.println("It is in final chunk.");
                a = 2;
                returna;
            }
        }
    输出: 
    It is in final chunk.
    2

    如果将 return a; 注释掉,尽管在finally中给a重新赋了值,但是结果将是如下输出
    It is in final chunk.
    1        
    说明,finally是在try中执行完return后再执行的。只有当finally中也有return的时候,方法将直接返回,不再执行热河代码。

    8、Java1.7和Java1.8的新特性

    一、对于JDK7
    1、支持将整数类型用二进制来表示,用0b开头   
    1. // 所有整数 int, short,long,byte都可以用二进制表示  
    2.    // An 8-bit ‘byte’ value:  
    3.    byte aByte = (byte) 0b00100001;  
    4.   
    5.    // A 16-bit ‘short’ value:  
    6.    short aShort = (short) 0b1010000101000101;  
    7.   
    8.    // Some 32-bit ‘int’ values:  
    9.    intanInt1 = 0b10100001010001011010000101000101;  
    10.    intanInt2 = 0b101;  
    11.    intanInt3 = 0B101; // The B can be upper or lower case.  
    12.   
    13.    // A 64-bit ‘long’ value. Note the “L” suffix:  
    14.    long aLong = 0b1010000101000101101000010100010110100001010001011010000101000101L;  
    15.   
    16.    // 二进制在数组等的使用  
    17.    final int[] phases = { 0b00110001, 0b01100010, 0b11000100, 0b10001001,  
    18.    0b00010011, 0b00100110, 0b01001100, 0b10011000 };  
     // 所有整数 int, short,long,byte都可以用二进制表示
        // An 8-bit 'byte' value:
        byte aByte = (byte) 0b00100001;
    
        // A 16-bit 'short' value:
        short aShort = (short) 0b1010000101000101;
    
        // Some 32-bit 'int' values:
        intanInt1 = 0b10100001010001011010000101000101;
        intanInt2 = 0b101;
        intanInt3 = 0B101; // The B can be upper or lower case.
    
        // A 64-bit 'long' value. Note the "L" suffix:
        long aLong = 0b1010000101000101101000010100010110100001010001011010000101000101L;
    
        // 二进制在数组等的使用
        final int[] phases = { 0b00110001, 0b01100010, 0b11000100, 0b10001001,
        0b00010011, 0b00100110, 0b01001100, 0b10011000 };

    2、switch语句支持String参数 
    1. String str = “a”;  
    2.          switch (str) {  
    3.             case “a”:  
    4.                 System.out.println(”a—”);  
    5.                 break;  
    6.             case “b”:  
    7.             System.out.println(”b—”);  
    8.             break;  
    9.          }  
    String str = "a";
             switch (str) {
                case "a":
                    System.out.println("a---");
                    break;
                case "b":
                System.out.println("b---");
                break;
             }
    注意:在把字符串传进Switch case之前,别忘了检查字符串是否为Null。

    3、数字类型的下划线表示 更友好的表示方式,不过要注意下划线添加的一些标准,可以参考下面的示例   
    1. long creditCardNumber = 1234_5678_9012_3456L;  
    2.    long socialSecurityNumber = 999_99_9999L;  
    3.    float pi = 3.14_15F;  
    4.    long hexBytes = 0xFF_EC_DE_5E;  
    5.    long hexWords = 0xCAFE_BABE;  
    6.    long maxLong = 0x7fff_ffff_ffff_ffffL;  
    7.    byte nybbles = 0b0010_0101;  
    8.    long bytes = 0b11010010_01101001_10010100_10010010;   
    9.    //float pi1 = 3_.1415F;      // Invalid; cannot put underscores adjacent to a decimal point  
    10.    //float pi2 = 3._1415F;      // Invalid; cannot put underscores adjacent to a decimal point  
    11.    //long socialSecurityNumber1= 999_99_9999_L;         // Invalid; cannot put underscores prior to an L suffix   
    12.    //int x1 = _52;              // This is an identifier, not a numeric literal  
    13.    int x2 = 5_2;              // OK (decimal literal)  
    14.    //int x3 = 52_;              // Invalid; cannot put underscores at the end of a literal  
    15.    int x4 = 5_______2;        // OK (decimal literal)   
    16.    //int x5 = 0_x52;            // Invalid; cannot put underscores in the 0x radix prefix  
    17.    //int x6 = 0x_52;            // Invalid; cannot put underscores at the beginning of a number  
    18.    int x7 = 0x5_2;            // OK (hexadecimal literal)  
    19.    //int x8 = 0x52_;            // Invalid; cannot put underscores at the end of a number   
    20.    int x9 = 0_52;             // OK (octal literal)  
    21.    int x10 = 05_2;            // OK (octal literal)  
    22.    //int x11 = 052_;            // Invalid; cannot put underscores at the end of a number   
     long creditCardNumber = 1234_5678_9012_3456L;
        long socialSecurityNumber = 999_99_9999L;
        float pi = 3.14_15F;
        long hexBytes = 0xFF_EC_DE_5E;
        long hexWords = 0xCAFE_BABE;
        long maxLong = 0x7fff_ffff_ffff_ffffL;
        byte nybbles = 0b0010_0101;
        long bytes = 0b11010010_01101001_10010100_10010010; 
        //float pi1 = 3_.1415F;      // Invalid; cannot put underscores adjacent to a decimal point
        //float pi2 = 3._1415F;      // Invalid; cannot put underscores adjacent to a decimal point
        //long socialSecurityNumber1= 999_99_9999_L;         // Invalid; cannot put underscores prior to an L suffix 
        //int x1 = _52;              // This is an identifier, not a numeric literal
        int x2 = 5_2;              // OK (decimal literal)
        //int x3 = 52_;              // Invalid; cannot put underscores at the end of a literal
        int x4 = 5_______2;        // OK (decimal literal) 
        //int x5 = 0_x52;            // Invalid; cannot put underscores in the 0x radix prefix
        //int x6 = 0x_52;            // Invalid; cannot put underscores at the beginning of a number
        int x7 = 0x5_2;            // OK (hexadecimal literal)
        //int x8 = 0x52_;            // Invalid; cannot put underscores at the end of a number 
        int x9 = 0_52;             // OK (octal literal)
        int x10 = 05_2;            // OK (octal literal)
        //int x11 = 052_;            // Invalid; cannot put underscores at the end of a number 

    4、泛型实例的创建可以通过类型推断来简化 可以去掉后面new部分的泛型类型,只用<>就可以了
    一般使用泛型是如下情况:
    List<String> strList = new ArrayList<String>(); 

    在JDK7及以后,可以简化成如下:
    List<String> strList = new ArrayList<>(); 

    5、对资源的自动回收管理
    平常我们在使用一些资源时,一般会在finally中进行资源的释放,如下形式:
    1. BufferedReader br = new BufferedReader(new FileReader(path));    
    2. try {    
    3.    return br.readLine();    
    4. finally {    
    5.    br.close();    
    6. }   
    BufferedReader br = new BufferedReader(new FileReader(path));  
    try {  
       return br.readLine();  
    } finally {  
       br.close();  
    } 
    而1.7之后我们可以使用这种形式:
    1. try (BufferedReader br = new BufferedReader(new FileReader(path)) {    
    2.    return br.readLine();    
    3. }   
    try (BufferedReader br = new BufferedReader(new FileReader(path)) {  
       return br.readLine();  
    } 
    直接在try中进行声明,跟finally里面的关闭资源类似; 按照声明逆序关闭资源。这些资源都需要实现java.lang.AutoCloseable接口的资源。

    二、对于JDK1.8:
    1、接口中可以定义默认非抽象的方法

    Java 8允许我们给接口添加一个非抽象的方法实现,只需要使用 default关键字即可,这个特征又叫做扩展方法,示例如下:

     代码如下:
    1. interface Formula {  
    2.     double calculate(int a);  
    3.     default double sqrt(int a) {  
    4.         return Math.sqrt(a);  
    5.     }  
    6. }  
    interface Formula {
        double calculate(int a);
        default double sqrt(int a) {
            return Math.sqrt(a);
        }
    }
    Formula接口在拥有calculate方法之外同时还定义了sqrt方法,实现了Formula接口的子类只需要实现一个calculate方法,默认方法sqrt将在子类上可以直接使用
    代码如下:
    1. Formula formula = new Formula() {  
    2.     @Override  
    3.     public double calculate(int a) {  
    4.         return sqrt(a * 100);  
    5.     }  
    6. };  
    7. formula.calculate(100);     // 100.0  
    8. formula.sqrt(16);           // 4.0  
    Formula formula = new Formula() {
        @Override
        public double calculate(int a) {
            return sqrt(a * 100);
        }
    };
    formula.calculate(100);     // 100.0
    formula.sqrt(16);           // 4.0

    2、Lambda 表达式

    首先看看在老版本的Java中是如何排列字符串的:

    代码如下:
    1. List<String> names = Arrays.asList(“peter”“anna”“mike”“xenia”);  
    2. Collections.sort(names, new Comparator<String>() {  
    3.     @Override  
    4.     public int compare(String a, String b) {  
    5.         return b.compareTo(a);  
    6.     }  
    7. });  
    List<String> names = Arrays.asList("peter", "anna", "mike", "xenia");
    Collections.sort(names, new Comparator<String>() {
        @Override
        public int compare(String a, String b) {
            return b.compareTo(a);
        }
    });
    只需要给静态方法 Collections.sort 传入一个List对象以及一个比较器来按指定顺序排列。通常做法都是创建一个匿名的比较器对象然后将其传递给sort方法。

    在Java 8 中你就没必要使用这种传统的匿名对象的方式了,Java 8提供了更简洁的语法,lambda表达式:

    复制代码 代码如下:
    Collections.sort(names, (String a, String b) -> {
        return b.compareTo(a);
    });
    看到了吧,代码变得更段且更具有可读性,但是实际上还可以写得更短:
    复制代码 代码如下:
    Collections.sort(names, (String a, String b) -> b.compareTo(a));
    对于函数体只有一行代码的,你可以去掉大括号{}以及return关键字,但是你还可以写得更短点:
    复制代码 代码如下:
    Collections.sort(names, (a, b) -> b.compareTo(a));
    Java编译器可以自动推导出参数类型,所以你可以不用再写一次类型。

    3、Date API

    Java 8 在包java.time下包含了一组全新的时间日期API。新的日期API和开源的Joda-Time库差不多,但又不完全一样,下面的例子展示了这组新API里最重要的一些部分:
    Clock 时钟

    Clock类提供了访问当前日期和时间的方法,Clock是时区敏感的,可以用来取代 System.currentTimeMillis() 来获取当前的微秒数。某一个特定的时间点也可以使用Instant类来表示,Instant类也可以用来创建老的java.util.Date对象。

    代码如下:
    1. Clock clock = Clock.systemDefaultZone();  
    2. long millis = clock.millis();  
    3. Instant instant = clock.instant();  
    4. Date legacyDate = Date.from(instant);   // legacy java.util.Date  
    Clock clock = Clock.systemDefaultZone();
    long millis = clock.millis();
    Instant instant = clock.instant();
    Date legacyDate = Date.from(instant);   // legacy java.util.Date

    4、支持多重注解

    9、异常抛出问题

    以下关于JAVA语言异常处理描述正确的有?
    A、throw关键字可以在方法上声明该方法要抛出的异常。    B、throws用于抛出异常对象。    
    C、try是用于检测被包住的语句块是否出现异常,如果有异常,则抛出异常,并执行catch语句。
    D、finally语句块是不管有没有出现异常都要执行的内容。    E、在try块中不可以抛出异常



    正确答案:CD
    throw用于抛出异常。
    throws关键字可以在方法上声明该方法要抛出的异常,然后在方法内部通过throw抛出异常对象

    未完待续~~

    参考文章:




  • 相关阅读:
    iPad用户使用Mac和Windows应用软件-记Parallels Access使用体验
    用ipad维护Linux服务器
    Class Model of Quick Time Plugin
    vm_write
    [转]Getting a Packet Trace
    [原]调试没有符号的 iOS 应用
    [转]编译 JavaScriptCore For iOS
    [转]ARM64 Function Calling Conventions
    [转]如何选择职业道路
    [转]Native Java Bytecode Debugging without Source Code
  • 原文地址:https://www.cnblogs.com/Arry10/p/7731765.html
Copyright © 2011-2022 走看看