刷题-Java篇(。。。)

1.在运行时,由java解释器自动引入,而不用import语句引入的包是()。
A.java.lang
B.java.System
C.java.io
D.java.until

答案:A
解释:java.lang是java语言的核心包,包内定义了一些基本的类型,包括Integer、String之类的,无需手动导入,解释器自动导入。(System属于java.lang.System,java.io、java.until需要手动导入)



2.在Java中,对于不再使用的内存资源,如调用完成的方法,“垃圾回收器”会自动将其释放。()
A.正确
B.错误

答案:B
解释:



3.以下程序的输出结果为()

class  Base{
      public Base(String  s){
              System.out.println("B");
      }
 }

public class Derived extends Base{
      public Derived(String s){
              System.out.println("D");
      }
      public static void main(String[] args){
              new Derived("C");
      }
}

A. BD
B. DB
C. C
D. 编译错误

答案:D
解释:由java初始化顺序,我们可知,初始化子类必须要先初始化父类,即子类构造器会隐式调用父类无参的构造器。如果父类没有无参构造器,那么子类必须要在构造器的第一行显示调用父类的有参构造器,将"super(s);"添上即可



4.以下哪些JVM的垃圾回收方式采用的是复制算法回收()
A.新生代串行收集器
B.老年代串行收集器
C.并行收集器
D.新生代并行回收收集器
E.老年代并行回收收集器
F.cms收集器

答案:AD
解释:



5.ArryList list=new ArryList(20);
中的list扩充几次()。
A.0
B.1
C.2
D.3

答案:A
解释:关于ArryList的构造器总共有三个:
ArryList():构造一个初始容量为10的空列表
ArryList(Collection c):构造一个包含指定collection元素的列表,这些元素是按照该collection的迭代器返回他们的顺序排列的。
ArryList(int inittalCapacity):构造一个具有指定初始化容量的空列表。



6.What is display when the following is executed:

double d1=-0.5;
System.out.println("Ceil d1="+Math.ceil(d1));
System.out.println("floor d1="+Math.floor(d1));

A. Ceil d1=-0.0 floor d1=-1.0
B. Ceil d1=0.0 floor d1=-1.0
C. Ceil d1=-0.0 floor d1=-0.0
D. Ceil d1=0.0 floor d1=0.0
F. Ceil d1=0 floor =-1

答案:A
解释:首先我们先来了解Math.ceil()、Math.floor()方法
ceil()故名思意,天花板数,向上取整。例如-2.1->-2.0,2.1->3.0
floor()地板数,即向下取整。例如-2.1->-3.0,2.1->2.0
同时还有一个方法,Math.round(),表示“四舍五入”,即等价于将目标数+0.5然后使用Math.floor()方法。例如-2.6->-3,2.6->3
ceil()、floor()处理完后得到的数符号是不变的
而round()处理后返回的数的类型是根据参数的不同而不同,即有round(double d)、round(float f)两个方法,前者返回的long型的数,后者是返回int型的数



7.枚举(enum)属于原始数据类型(primitive type)。
A.正确
B.错误

答案:B
解释:首先我们先了解原始类型的概念:原始类型一共有8种:byte、short、int、long、double、char、boolean、float
而枚举类型是java5新增的特性,是一种新的类型,允许用常量来表示特定的数据片段,即拥有成员变量和方法,是一个特殊的类。即除了原始类型,其他类型都是引用类型。


8.以下代码执行的结果显示是多少()?

public class Demo{
    public static void main(String[] args){
               int  count=0;
               int  num=0;
               for(int i=0;i<=100;i++){
                    num=num+i;
                    count=count++;
               }
               System.out.println(num*count);
    }
}

A.505000
B.0
C.运行错误
D.5050

答案:B
解释:可能是受了C语言的影响,一下次就选A了,结果一看,错了,顿时怀疑人生!!!于是到处查资料,看到了如下说法:
在JVM中,对于count=count++的处理,先是将count的值(不是引用)存储在一个临时变量区,然后对count进行+1的操作,最后返回临时变量区的值。即等价于:
temp(临时变量)=count;
count++;
count=temp
而在C/C++中:
temp=count;
count=temp;
count++;



9.(不定选项)jdk1.8中,下面有关java抽象类和接口的区别,说法错误的是?()
A.抽象类可以有自己的构造方法,接口不能有构造方法。
B.抽象类中可以包含非抽象的普通方法,接口中的方法必须是抽象的,不能有非抽象的普通方法,
C.一个类可以实现多个接口,但只能继承一个抽象类。
D.接口中可以有普通成员变量,抽象类中没有普通成员变量。

答案:BD
解释:啊啊啊,做错啦!!!果然要不断的学习啊,从jdk1.8开始,对于接口,不再只是只能有抽象方法了,还增加的静态方法(即static修饰的方法)和default方法;从jdk1.9开始,又增加了私有方法如下:

//目前java9版本
public interface A {
    abstract void a();  //以前的只能有这个形式的方法

    static void b(){}   //增加的静态方法,不能被实现类使用
    default void c(){}  //增加的default方法。可以被实现类直接使用或重写
    private void method(){}//私有方法
    
    void d();           //不过默认下还是abstract修饰
    int  a=10;          //默认是用static final修饰
}

爱Java,爱编程!!!继续学习吧!!!



10.java语言的下面集中数组复制方法中,那个效率最高?()
A. for循环逐一赋值
B.System.arrarycopy
C.Arrays.copyOf
D.使用clone方法

答案:B
解析:数组中这4个复制的方法中,效率的依次比较如下:
System.arraycopy>使用clone方法>Arrays.copyOf>for
为了验证,我们可以如下测试:


/**
 * 复制数组的4种方法比较
 */
public class ArrayCopyDemo {
    private static final byte[] buffer = new byte[1024*10];
    static {
        for (int i = 0; i < buffer.length; i++) {
            buffer[i] = (byte) (i & 0xFF);
        }
    }
    private static long startTime;
    public static void main(String[] args){
        startTime = System.nanoTime();
        methodFor();
        showTime("methodFor     ");

        startTime = System.nanoTime();
        methodClone();
        showTime("methodClone     ");

        startTime = System.nanoTime();
        methodArrayscopyOf();
        showTime("methodArrayscopyOf     ");

        startTime = System.nanoTime();
        methodSystemcopyOf();
        showTime("methodSystemarraycopy     ");

    }

    //通过for循环复制
    public static void methodFor(){
        byte[]    newbyte = new     byte[buffer.length];
        for(int i=0;iList  NumberList = new ArrayList();
NumberList.add(2);
NumberList.add(4);
NumberList.add(1);
NumberList.add(3);
NumberList.add(5);
for(int i =0 ;i < MumberList.size() ; ++ i){
      int v = NumberList.get(i);
      if(v % 2 == 0)
          NumberList.remove(v);
}

A. 2,4,1,3,5
B. 2,1,3,5
C. 4,1,3,5
D. 会出现越界异常

答案:D
解析:其实这道题就是考我们的细心问题,在ArrayList中remove有两个重载方法,一个是remove(int index),另一个是remove(Object obj),前一个方法是删除集合中index索引位置的元素,后一个方法是删除集合中obj元素。
所以题目中remove方法传入的参数类型v是int型了,所以调用的是remove(int index)方法,所以,循环执行第二次的时候(第一次正好符合要求,删除了索引2的元素,即索引最大值-1),传参4超出了当前集合的索引最大值,造成越界异常!
注:List集合中的remove方法,只要参数传入的是int型就是删除指定索引位置的元素!



12.下面代码执行的结果是多少?()

public class Demo{
  public static void main(String[] args){
      Integer i1 = 128;
      Integer i2 = 128;
      System.out.print((i1 == i2) + ",");
      String i3 = "100";
      String i4 = "1" + new String("00");
      System.out.print((i3 == i4) + ",");
      Integer i5 = 100;
      Integer i6 = 100;
      System.out.println(i5 == i6);
  }
}

A. true,false,true
B. false,true,false
C. truen,true,false
D.false,false,true

答案:D
解析:首先我们要知道,我们为Integer赋值的时候,java编译器会将其翻译成调用valueOf方法,我们看源码:

public static Integer valueOf(int i) {
        //low值是-128,high值是127
        if (i >= IntegerCache.low && i <= IntegerCache.high)
            return IntegerCache.cache[i + (-IntegerCache.low)];
        return new Integer(i);
    }

所以,当我们赋值的时候,若赋的值在-128~127范围中,将会直接从缓存cache中拿过来用,地址值并没有改变,这是JVM的优化。所以若是超过了这个范围,就会new Integer(i)而产生新的地址值。
对于String字符串,"1" + new String("00")这个已经产生了new新的对象,固然不会从字符串常量池中取出了,==判断当然地址值不一样了。



13.*(不定选项)byte b1 = 1 , b2 = 2 , b3 , b6 ,b8;
    final byte b4 = 4 , b5 = 6 , b7;

b3 = (b1 + b2); //语句1
b6 = b4 + b5; //语句2
b8 = (b1 + b4); //语句3
b7 = (b2 + b5); //语句4

上面4个语句中,存在编译错误的语句是()
A. 语句2
B. 语句1
C. 语句3
D. 语句5

答案:BCD
解析:根据表达式数据类型转型的规则:
1.比int类型数据范围小的数据类型在运算的时候后自动转为int型
2.当有某个数据类型范围高于int型的时候其它数据类型会自动转为这个高的数据类型计算(按最高范围的为准)
3.被final修饰的变量不会自动改变类型,如果有2个被final修饰的变量进行操作时,会根据左边变量的类型而转换。
A.b6 = b4 + b5;//根据规则3,是符合的,没有问题。
B.b3 = (b1 + b2);//(b1 + b2)会自动转为int型,然后赋值给byte型的b3,存在数据精度缺失,即编译不通过。
C.b8 = (b1 + b4);//虽然b4被final修饰,b1没有被修饰,但最终的结果还会是int型
D.同上



14.阅读如下代码。请问,对语句行test.hello()描述正确的有().

package NowCoder;
class Test{
  public static void hello(){
      System.out.println("hello");
  }
}
public class MyApplication{
    public static void main(String[] args){
          Test  test = null;
          test.hello();
    }
}

A.能编译通过,且正常运行
B.使用了未初始化的变量,所以不能编译通过
C.以错误的方法访问的静态方法
D.编译能通过,但因为变量为null,不能正常运行

答案:A
解析:
我们应该知道,hello是静态方法,在类加载的时候就已经存在且只加载一次。
Test test = null;会加载Test类,虽然对象为空,但是并不影响继续调用静态方法,加上是public修饰,在其他类中这样调用能够正常编译和运行。(不过,对于静态方法不推荐这样调用,最好是用类名.静态方法名的形式调用)



15.假设a是一个由 线程1 和 线程2 共享的初始值为0的全局变量,则线程1 和 线程2 同时执行下面的代码,最终a的结果不可能是()

boolean isOdd = false;

for(int i =1; i <= 2;++ i){
    if(i % 2 == 1)
        isOdd = true;
    else
        isOdd = false;

    a += i*(isOdd?1:-1);
}

A.-1
B.-2
C.0
D.1

答案:D
解析:
__



16.对于以下代码段

class A{
  public A foo(){
      return this;
  }
}

class B extends A{
    public A foo(){
        return this;
    }
}

class C extends B{
    //....
}

能够在//....下填入,且编译正确,运行不产生错误的选项是()
A. public void foo(){}
B. public int foo(){return 1;}
C. public A foo(B b){return b;}
D. public A foo(){return A;}

答案:C
解析:
按照题目要求,我们仔细看这几个选型,似乎是想考我们重写、重载,那我们回顾下重写、重载的要点:
重写:
1.重写在子类继承父类中存在(即父类要有这个方法且不能是私有方法)。
2.重写方法的修饰符权限要 >= 父类中要重写的方法的修饰符权限。
3.重写需要方法名(完全相同)、返回类型(重写的返回类型要在父类返回类型的范围内,比如父类时Object,子类需要是Object或它的子类)、参数列表一致才叫重写(参数的个数、顺序必须完全相同,类型同返回类型一样,要在范围内)。
重载:
1.重载发生在同一个类中。
2.重载的无关修饰符、和返回值类型,只和方法名和参数列表有关。即方法名要完全相同,参数列表不能相同(参数的类型、顺序、个数不同)。

  咋一看,似乎选项中没有我们想要的,首先排除了方法的重写,应为D选项语法错误,返回的不能是类,要是对象。重载呢,类C中没有方法啊?其实我们忘记了一个关键部分,我们知道方法的重载是在同一个类中,但是类C继承了类B啊,这继承过来的非私有方法不也是类C自己的方法吗?所以,我们往父类B上看,父类B重写了类A的foo()方法,而类A中只有foo()方法,即我们只需要看foo()方法的重载即可,选项中只有C选项符合,A、B编译出错。



17.Java语言中,如果"xyz"没有被创建过,String s = new String("xyz");这行代码创建了几个String object?
A. 1
B. 2
C. 3
D. 4

答案:B
解释:



18.以下代码执行后输出的结果为()

public class Test{
    public static void main(String[] args){
          System.out.println("return value of getValue():"+getValue);
    }

    public static int getValue(){
          try{
              return 0;
          }finally{
              return 1;
          }
    }
}

A. return value of getValue(): 1
B. return value of getValue(): 0
C. return value of getValue(): return value of getValue(): 1
D. return value of getValue(): return value of getValue(): 0

答案:A
解析:
根据JVM规范:

  • 如果只是try语句里有return,即返回try语句块中的变量值。
    具体过程如下:
    如果有返回值,则将返回值先保存到局部变量中;
    然后执行jsr指令跳转到finally语句中执行;
    执行完finally语句后,返回之前保存在局部变量里的值。
  • 如果try、finally语句中均有return,则忽略try的return,而使用finally中的return。
    通过规范,就能得出结果是A了!


19.what results from the following code fragment?

int i = 5;
int j = 10;
System.out.println(i + ~j);

A. Compliation error because "~" doesn't operate on integers.
B.-5
C.-6
D.15

答案:C
解析:
首先我们得知道"~"是按位取反的意思(要注意的是对储存在计算机中的二进制的补码来计算)。
有个公式:-n=~n+1,可以推算出-->~10= -n-1-->
得出:i + ~j = 5+ (-11)的结果为-6
那么-n=~n+1的公式是怎么得出来的呢?
其实很简单,计算机中的数值以补码的形式储存,正数的原码/反码/补码是相同的,负数的补码=反码+1。即10的补码为0000 0000 0000 1010补码,那么~10的补码为1111 1111 1111 0101~10的补码(此时已经为负数了,因为最高位为1), 那么~10的反码为1111 1111 1111 0100~10的反码, 再~10的源码为1000 0000 0000 1011~10的源码 --->得出~10的十进制位-11



20.(JDK.18版本)抽象方法的访问权限修饰符默认都是public。()
A. 正确
B. 错误

答案:B
解析:在jdk1.8版本中,抽象类中的抽象方法和非抽象方法在不加修饰符的情况下默认是default修饰
我们可以实际测试一下

abstract class Demo{
    //不加修饰符的抽象方法
    abstract void method();
    //不加修饰符的普通方法
    void method02(){}
    //加了protected修饰符的抽象方法
    protected void method03();
    //加了protected修饰符的普通方法
    protected void method04(){}
}
//然后我们定义一个类来继承这个抽象类,并来重写这两个方法
/*
  在重写之前,我们首先应该知道,当重写某个方法时,
  重写的方法的权限修饰符不能比原有方法修饰符的权限小
  修饰符权限从大到小的排序:
      public -> protected -> (默认修饰符default) -> private
*/
public class MyDemo extends Demo{
    /*
      所以,我们要做验证抽象方法的默认修饰符是不是
      (默认default) 修饰,我们只需要重写的时候都不写修饰符
      使用(默认default)
    */
    @Override
    void method(){}
    
    @Override
    void method02(){}
    
    /*
      下面2个重写方法编译出错,说明抽象类中的抽象方法和
      普通方法并不是默认protected或public修饰符
      修饰的!!!
     */
    //@Override
    //void method03(){}
    
    //@Override
    //void method04(){}
}


21.What will be printed when you execute the following code?

class C{
    C(){
        System.out.print("C");
    }
}
class A{
    C c = new C();;
    A(){
       this("A");
       System.out.print("A");
    }
    A(String s){
        System.out.print(s);
    }
}
class Test extends A{
    Test(){
        super("B");
        System.out.print("B");
    }

    public static void main(String[] args){
        new B("");
    }
}


22.下列哪个选项是Java调试器?如果编译器返回程序代码的错误,可以用它对程序进行调试。
A. java.exe
B. javadoc.exe
C. jdb.exe
D. javaprof.exe

答案:C
解析:
javac.exe是编译.java文件
java.exe是执行编译好的.class文件
javadoc.exe是生成Java说明文档
jdb.exe是Java调试器
javaprof.exe是剖析工具



23.假设有4条语句:
s1:a=5x;
s2:b=5+y;
s3:c=a+b;
s4:d=c+y;

根据bernstein条件,下面说法正确的是?
A. s1,s4可并发执行
B. s1,s2不可并发执行
C. s2,s3可并发执行
D. s3,s4不可并发执行

答案:D
Bernstein条件:R(P1)∩W(P2)∪R(P2)∩W(P1)∪W(P1)∩W(P2)={}
R()代表读集、W()代表写集
所以,当满足上式条件的时候,就代表2个程序之间无关联,可以进行并发操作。
A选项:s1:a=5x,s4:d=c+y-->c=a+b;可以看到s1的结果影响着s4,所以这两个不能并发执行。
B选项:s1:a=5x,s2:b=5+y;这两个语句没有关联,所以可以并发执行。
C选项:s2:b=5+y,s3:c=a+b-->b=5+y;不能并发执行。
D选项:s3:c=a+b,s4:d=c+y-->c=a+b;不能并发执行,答案正确



23.(单选题)Test.main()函数执行后的输出是()

public class Test{
    public static void main(String[] args){
          System.out.println(new B().getValue());
    }

    static class A{
        protected int value;
        public A(int v){
            setValue(v);
        }
        public void setValue(int value){
            this.value = value;
        }
        public int getValue(){
            try{
                  value ++;
                  return value;
             }catch(Exception e){
                  System.out.println(e.toString());
             }finally{
                  this.setValue(value);
                  System.out.println(value);
             }
            return value;
        }    

    static class B extends A{
          public B(){
           super(5);
           setValue(getValue() - 3);
        }
        public void setValue(int value){
            super.setValue(2*value);
        }
    }
}

A. 11 17 34
B. 22 74 74
C. 6 7 7
D. 22 34 17

答案:D
解析:
new B().getValue();按照步骤:
①先执行构造方法B()

  • super(5)执行->public A(5){setValue(5)}这里是关键setValue(5)执行的不是类A中的setValue方法,而是执行类B中重写的setValue方法,即执行super.setValue(2*5),那么此时value=10

②然后执行setValue(getValue() - 3)

  • 然后这个也是先执行getValue()->10 ++,返回 11(保留),先执行finally中的方法体->this.setValue(2*11);->value = 22 -> System.out.println(22)->控制台打印22
    然后通过返回的11执行setValue(11 - 3)->super.setValue(2*8)->此时value = 16

③最后执行getValue()方法
16 ++;->返回17(保留),先执行finally中的方法体->this.setValue(2*17)->此时value = 34->System.out.println(34)->控制台打印34
最后返回17->执行System.out.println(17);控制台打印17

对于上面什么时候执行setValue方法是要看是哪个类型的对象调用的:
这里是子类对象new B()调用的,当子类调用某个方法的时候,子类继承父类如果重写了继承过来的方法,那么调用的就是重写的方法,否则就是调用的是继承的方法;

所以对于当执行这一句super(5)的时候,我们追溯上去

public A(5){
    /*
    这个方法这个时候是谁来调用的呢?没错,就是B类对象!
    */
    setValue(5);
}


24.(单选题)说明输出结果

package test;
import java.util.Date;
public class SuperTest extends Date{
      private static final long serialVersionUID = 1L;
      private void test(){
            System.out.println(super.getClass().getName());
      }
      public static void main(String[] args){
            new SuperTest().test();
      }
}

A. SuperTest
B. SuperTest.class
C. test.SuperTest
D. test.SuperTest.class

答案:C
解析:
首先我们要知道.getClass().getName()是返回包名+类名
那么super.getClass().getName()返回的就是父类的包名+类名,这并不是绝对的,因为getClass()方法时Object类的方法:
The {@code Class} object that represents the runtime class of this object.(返回正在运行时的类的Class对象)

并且父类Date并没有重写这个方法,所以返回的应是此时正在运行时的类的包名+类名** test.SuperTest**



25.下面语句正确的是()
A. 形式参数可被视为local variable
B. 形式参数可被所有的字段修饰符修饰
C. 形式参数为方法被调用时,是真正被传递的参数
D. 形式参数不可以是对象

答案:A
解析:
A. 形式参数可被视为lcoal variable(局部变量)。形式参数和局部变量一样都不能离开方法,都在方法内才能起作用,不为方法外所见。
B.形式参数只能使用final修饰符,其它的修饰符都会引发编译错误。使用final后的限制,不能都这个参数作任何的修改,那么为什么要使用呢?就是方法内的内部内,方法内部内有规定使用方法的参数或局部变量的话,这个参数不都被修改,当然也可以不用final修饰,只要我们不改变这个参数即可,不过使用的话能够达到提醒效果。
C.形式参数的值在调用时根据调用者更改,实参则使用自身的值更改形参的值(其实我们可以根据JVM所知,实参赋值给形参的就是指向实际内容的地址),所以真正被传递的其实是实参。
D.这个显然错误。



26.What is the result of the following code?

enum AccountType{
    SAVING,FIXED,CURRENT;
    private AccountType(){
        System.out.println("It is a account type");
    }
}

class EnumOne{
    public static void main(String[] args){
        System.out.println(AccountType.FIXED);
    }
}

A. Compiles fine and output is prints "It is a account type" once followed by "FIXED"
B. Complies fine and output is prints "It is a account type" twince followed by "FIXED"
C. Complies fine and output is prints "It is a account type" thrice followed by "FIXED"
D. Complies fine and output is prints "It is a account type" four times followed by "FIXED"
E. Complies fails

答案:C

解析:
感觉跟考英语一样,首先,对于枚举类,它是一个类,它的每一个静态枚举值(默认是static修饰)都是一个对象,所以在第一次初始化的时候(因为题中是第一次调用),有多少个静态成员(实例)就会调用多少次构造方法!
故题中有3个枚举值,故执行3次



27.(不定选项)在Java语言中,下列关于字符集编码(Character set encoding)和国际化(i18n)的问题,那些是正确的?
A. 每个中文字符占用2个字节,每个英文字符占1个字节
B. 假设数据库中的字符是以GBK编码的,那么显示数据库数据的网页也必须是以GBK编码的
C. Java的char类型,通常以UTF-16 Big Endian的方式保存一个字符
D. 实现国际化应用的手段是利用ResourceBundle类

答案:CD

解析:
A:Java中采用的是Unicode编码方式,



28.Java中,StringBuilderStringBuffer的区别,下面说法错误的是?
A. StringBuffer是线程安全的
B. StringBuilder是线程不安全的
C. StringBuffer对String类型进行改变的时候其实都等同于生成了一个新的String对象,然后将指针指向新的String对象
D. 效率比较StringBuilder>StringBuffer>String,但是在String s1 ="This is only a" + "simple"+"test"时,String效率最高。

答案:C
解析:
A:Stringbuffer是线程安全的,其通过synchronized关键字来保证其线程的安全性。
B:StringBuilder是线程不安全的,它没有任何对线程问题做任何处理。
C:StringBuffer亦或StringBuilder在对String类型进行改变的时候,并没有生成新的String对象,而是在原本的对象上做改变的,具体方式可以看源码。
D:一般来说,对字符串的修改,效率的排序如同D选项,但是对于"This is only a" + "simple"+"test"时,String的效率最高,因为在编译过程中,这个方式是直接为一个字符串常量的。

你可能感兴趣的:(刷题-Java篇(。。。))