牛客选择题错题集

2019-04-26

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

 

A.true,false,truehtml

B.false,true,falsejava

C.true,true,false算法

D.false,false,true设计模式

正确答案: D   你的答案: A (错误)数组

解答:缓存

当咱们在为Integer赋值的时候,java编译器会将其翻译成调用valueOf()方法。好比Integer i=127翻译为Integer i=Integer.valueOf(127)
而后咱们来看看valueOf()函数的源码:
1 public static Integer valueOf(int i)
2     {
3         //high为127
4         if(i >= -128 && i <= IntegerCache.high)
5             return IntegerCache.cache[i + 128];
6         else
7             return new Integer(i);
8     }
能够看出,对于-128到127之间的数,Java会对其进行缓存。而超出这个范围则新建一个对象。
因此如今回到这道问题
i1和i2为128,超出范围,因此都须要新建对象,对象比较为false;
i5和i6为100,在范围以内,在执行Integer i5=100时,就会直接缓存到内存中,但执行执行Integer i6=100时,就直接从缓存里取,而不须要新建对象,因此为true。
IntegerCache的源码
/**
     * Cache to support the object identity semantics of autoboxing for values between
     * -128 and 127 (inclusive) as required by JLS.
     *
     * The cache is initialized on first usage.  The size of the cache
     * may be controlled by the {@code -XX:AutoBoxCacheMax=<size>} option.
     * During VM initialization, java.lang.Integer.IntegerCache.high property
     * may be set and saved in the private system properties in the
     * sun.misc.VM class.
     */
 
    private static class IntegerCache {
        static final int low = -128;
        static final int high;
        static final Integer cache[];
 
// 省略
}

能够看到能够经过设置虚拟机参数:XX:AutoBoxCacheMax=<size>或 -Djava.lang.Integer.IntegerCache.high=<high>安全

来设置缓存范围的最大值(包含)ide

这归结于java对于Integer与int的自动装箱与拆箱的设计,是一种模式:享元模式(flyweight)函数

为了加大对简单数字的重利用,java定义:在自动装箱时对于值从–128到127之间的值,它们被装箱为Integer对象后,会存在内存中被重用,始终只存在一个对象。post

而若是超过了从–128到127之间的值,被装箱后的Integer对象并不会被重用,即至关于每次装箱时都新建一个 Integer对象;以上的现象是因为使用了自动装箱所引发的,若是你没有使用自动装箱,而是跟通常类同样,用new来进行实例化,就会每次new就都一个新的对象。

享元模式

享元模式(Flyweight Pattern)主要用于减小建立对象的数量,以减小内存占用和提升性能。这种类型的设计模式属于结构型模式,它提供了减小对象数量从而改善应用所需的对象结构的方式。

享元模式,换句话说就是共享对象,在某些对象须要重复建立,且最终只须要获得单一结果的状况下使用。由于此种模式是利用先前建立的已有对象,经过某种规则去判断当前所需对象是否能够利用原有对象作相应修改后获得想要的效果,如以上教程的实例,建立了20个不一样效果的圆,但相同颜色的圆只须要建立一次即可,相同颜色的只须要引用原有对象,改变其坐标值即可。此种模式下,同一颜色的圆虽然位置不一样,但其地址都是同一个,因此说此模式适用于结果注重单一结果的状况。

举一个简单例子,一个游戏中有不一样的英雄角色,同一类型的角色也有不一样属性的英雄,如刺客类型的英雄有不少个,按此种模式设计,利用英雄所属类型去引用原有同一类型的英雄实例,而后对其相应属性进行修改,即可获得最终想获得的最新英雄;好比说你建立了第一个刺客型英雄,而后须要设计第二个刺客型英雄,你利用第一个英雄改变属性获得第二个刺客英雄,最新的刺客英雄是诞生了,但第一个刺客英雄的属性也随之变得与第二个相同,这种状况显然是不能够的。

扩展:下面代码的输出为何?

public class Demo{
    public static void main(String[] args){
        String s1 = "100"; 
        String s2 = "100";
        System. out. print((s1==s2)+",");

        String s3 = new String("100"); 
        System. out. print((s2==s3)+",");

        String s4 = new String("100");
        System. out. print((s3==s4)+",");
        }
}      
输出:
true,false,false,

VM为了提高性能和减小内存开销,避免字符串的重复建立,维护了一块特殊的内存空间——字符串实例池

String赋值的两种方式。

一、String str = "test";

以这种方式赋值时,JVM会先从字符串实例池中查询是否存在"test"这个对象,

若是存在,直接把实例池中"test"的地址返回给str。若是不存在,则会在实例池中建立"test"对象,并把该对象的地址返回给str。

二、String str = new String("test");

以这种方式赋值时,JVM会先从字符串实例池中查询是否存在"test"这个对象,

若不存在则会在实例池中建立"test"对象,同时在堆中建立"test"这个对象,而后将堆中的这个对象的地址返回赋给引用str。

若实例池存在则直接在堆中建立"test"这个对象,而后将堆中的这个对象的地址返回赋给引用str。

上面代码中的s3和s4分别指向堆中不一样的地址,因此返回false

 2.下列代码执行结果为()

public static void main(String args[])throws InterruptedException{
            Thread t=new Thread(new Runnable() {
                public void run() {
                    try {
                        Thread.sleep(2000);
                    } catch (InterruptedException e) {
                        throw new RuntimeException(e);
                    }
                    System.out.print("2");
                }
            });
            t.start();
             
            t.join();
            System.out.print("1");
        }
A. 21
B. 12
C. 可能为12,也可能为21
D. 以上答案都不对

正确答案: A   你的答案: 空 (错误)

thread.Join把指定的线程加入到当前线程,能够将两个交替执行的线程合并为顺序执行的线程。好比在线程B中调用了线程A的Join()方法,直到线程A执行完毕后,才会继续执行线程B。

t.join();      //使调用线程 t 在此以前执行完毕。 
t.join(1000);  //等待 t 线程,等待时间是1000毫秒

本题在主线程中调用了子线程的join函数,所以主线程必须等待子线程执行完毕才结束所以输出结果只能是21。

3. jdk1.8中,下面有关java 抽象类和接口的区别,说法错误的是?

A. 抽象类能够有构造方法,接口中不能有构造方法

B. 抽象类中能够包含非抽象的普通方法,接口中的方法必须是抽象的,不能有非抽象的普通方法

C. 一个类能够实现多个接口,但只能继承一个抽象类

D. 接口中能够有普通成员变量,抽象类中没有普通成员变量

咱们知道,抽象类是不能被实例化的。但抽象类是否能够有构造函数?答案是能够有。抽象类的构造函数用来初始化抽象类的一些字段,而这一切都在抽象类的派生类实例化以前发生。不只如此,抽象类的构造函数还有一种巧妙应用:就是在其内部实现子类必须执行的代码。

2019-04-27

static 修饰符
静态变量:

static 关键字用来声明独立于对象的静态变量,不管一个类实例化多少对象,它的静态变量只有一份拷贝。 静态变量也被称为类变量。局部变量不能被声明为 static 变量。

静态方法:

static 关键字用来声明独立于对象的静态方法。静态方法不能使用类的非静态变量。静态方法从参数列表获得数据,而后计算这些数据。

对类变量和方法的访问能够直接使用 classname.variablename 和 classname.methodname 的方式访问。

1. 下列程序执行后结果为( )

 1 class A {
 2     public int func1(int a, int b) {
 3         return a - b;
 4     }
 5 }
 6 class B extends A {
 7     public int func1(int a, int b) {
 8         return a + b;
 9     }
10 }
11 public class ChildClass {
12     public static void main(String[] args) {
13     A a = new B();
14     B b = new B();
15     System.out.println("Result=" + a.func1(100, 50));
16     System.out.println("Result=" + b.func1(100, 50));
17     }
18 }

正确答案: A   你的答案: C (错误)

A. Result=150Result=150

B. Result=100Result=100

C. Result=100Result=150

D. Result=150Result=100

此题考查的是多态。
  对于多态,能够总结它为:       

     1、使用父类类型的引用指向子类的对象;

    2、该引用只能调用父类中定义的方法和变量;

    3、若是子类中重写了父类中的一个方法,那么在调用这个方法的时候,将会调用子类中的这个方法;(动态链接、动态调用)

    4、变量不能被重写(覆盖),”重写“的概念只针对方法,若是在子类中”重写“了父类中的变量,那么在编译时会报错。

多态的3个必要条件:

        1.继承   2.重写   3.父类引用指向子类对象。
向上转型: Person p = new Man() ; //向上转型不须要强制类型转化
向下转型: Man man = (Man)new Person() ; //必须强制类型转化

2. BufferedReader的父类是如下哪一个?

正确答案: D   你的答案: D (正确)

A. FilterReader

B. InputStreamReader

C. PipedReader

D. Reader

 

3. 下面代码将输出什么内容:()

1 public class SystemUtil{
2     public static boolean isAdmin(String userId){
3         return userId.toLowerCase()=="admin";
4     }
5     public static void main(String[] args){
6         System.out.println(isAdmin("Admin"));
7     }
8 }

正确答案: B   你的答案: B (正确)

A. true

B. false

C. 1

D. 编译错误

在Java中,String 、Math、还有Integer、Double。。。。等这些封装类重写了Object中的equals()方法,让它再也不比较其对象在内存中的地址,而是比较对象中实际包含的整数的值,即比较的是内容。

=="equals方法:

==操做符专门用来比较两个变量的值是否相等,也就是用于比较变量所对应的内存中所存储的数值是否相同,要比较两个基本类型的数据或两个引用变量是否相等,只能用==操做符;

若是一个变量指向的数据是对象类型的,那么,这时候涉及了两块内存,对象自己占用一块内存(堆内存),变量也占用一块内存,例如Objet obj = newObject();变量obj是一个内存,new Object()是另外一个内存,此时,变量obj所对应的内存中存储的数值就是对象占用的那块内存的首地址。对于指向对象类型的变量,若是要比较两个变量是否指向同一个对象,即要看这两个变量所对应的内存中的数值是否相等,这时候就须要用==操做符进行比较。

equals方法是用于比较两个独立对象的内容是否相同,它比较的两个对象是独立的。

若是一个类没有本身定义equals方法,那么它将继承Object类的equals方法,Object类的equals方法的实现代码以下:

boolean equals(Object o){

return this==o;

}

 

这说明,若是一个类没有本身定义equals方法,它默认的equals方法(从Object类继承的)就是使用==操做符,也是在比较两个变量指向的对象是不是同一对象,这时候使用equals和使用==会获得一样的结果,若是比较的是两个独立的对象则总返回false。若是你编写的类但愿可以比较该类建立的两个实例对象的内容是否相同,那么你必须覆盖equals方法,由你本身写代码来决定在什么状况便可认为两个对象的内容是相同的。

 

4. 代码片断: 

byte b1=1,b2=2,b3,b6; 
final byte b4=4,b5=6; 
b6=b4+b5; 
b3=(b1+b2); 
System.out.println(b3+b6);
关于上面代码片断叙述正确的是()

正确答案: C   你的答案: A (错误)

A. 输出结果:13

B.语句:b6=b4+b5编译出错

C.语句:b3=b1+b2编译出错

D. 运行期抛出异常

被final修饰的变量是常量,这里的b6=b4+b5能够当作是b6=10;在编译时就已经变为b6=10了
而b1和b2是byte类型,java中进行计算时候将他们提高为int类型,再进行计算,b1+b2计算后已是int类型,赋值给b3,b3是byte类型,类型不匹配,编译不会经过,须要进行强制转换。
Java中的byte,short,char进行计算时都会提高为int类型

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

package NowCoder;
class Test {
    public static void hello() {
        System.out.println("hello");
    }
}
public class MyApplication {
    public static void main(String[] args) {
        // TODO Auto-generated method stub
        Test test=null;
        test.hello();
    }
}

正确答案: A   你的答案: A (正确)

A.能编译经过,并正确运行

B.由于使用了未初始化的变量,因此不能编译经过

C.以错误的方式访问了静态方法

D.能编译经过,但因变量为null,不能正常运行

由于Test类的hello方法是静态的,因此是属于类的,当实例化该类的时候,静态会被优先加载并且只加载一次,因此不受实例化new Test();影响,只要是使用到了Test类,都会加载静态hello方法!
另外,在其余类的静态方法中也是能够调用公开的静态方法,此题hello方法是使用public修饰的因此在MyApplication中调用hello也是能够的。
总结:即便Test test=null;这里也会加载静态方法,因此test数据中包含Test类的初始化数据。(静态的,构造的,成员属性)
        所以test.hello是会调用到hello方法的。

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

boolean isOdd = false;
 
for(int i=1;i<=2;++i)
{
    if(i%2==1)isOdd = trueelse isOdd = false;
    a+=i*(isOdd?1:-1);
}

 

正确答案: D   你的答案: C (错误)

A. -1

B. -2

C. 0

D. 1

易知:每一个线程对a 均作了两次读写操做,分别是 “ +1 ” 和 “ -2 ”
而题目问了是最终a 的结果,因此 a 的结果取决于各自线程对 a 的前后读写的顺序
结论:a的可能取值为-一、0、-2
如图:

 2019-05-11

 

1. 如下程序的输出结果是

public class Print{
    static boolean out(char c){
        System.out.println(c);
        return true;
    }
    public static void main(String[] argv){
        int i = 0;
        for(out('A');out('B') && (i<2);out('C')){
            i++;
            out('D');
        }
    }
}

正确答案: A   你的答案: A (正确)

A. ABDCBDCB

B. BCDABCD

C. 编译错误

D. 运行错误

其实这题考察的是for(int i=0;i<10;i++){}循环的执行顺序:
1.int i=0;初始化这一步只执行一次;
2.i<10;进行条件判断;条件达成返回true 不然false不往下执行,跳出for循环圈
3.i++ ;  是最后执行的,当循环体内的代码执行完它才进行赋值。

 

2. 若是int x=20, y=5,则语句System.out.println(x+y +""+(x+y)+y);  的输出结果是()

正确答案: D   你的答案: A (错误)

A. 2530

B. 55

C. 2052055

D. 25255

1)不论有什么运算,小括号的优先级都是最高的,先计算小括号中的运算,获得x+y +""+25+y
2)任何字符与字符串相加都是字符串,可是是有顺序的,字符串前面的按原来的格式相加,字符串后面的都按字符串相加,获得25+“”+25+5。
x+y+""+(x+y)+y,
先算括号: x+y+""+25+y, 
再按字符串分开看,符串前面的按原来的格式相加,字符串后面的都按字符串相加, x+y+ ""+25+y
获得  25+""+255
整个再连成字符串 25255
3)上面的结果按字符串相加获得25255

3. 下列哪一个说法是正确的()

正确答案: D   你的答案: A (错误)

A. ConcurrentHashMap使用synchronized关键字保证线程安全

B. HashMap实现了Collction接口

C. Array.asList方法返回java.util.ArrayList对象

D. SimpleDateFormat是线程不安全的

A. JDK1.8 的 ConcurrentHashMap 采用CAS+Synchronized保证线程安全。 JDK1.7 及之前采用segment的分段锁机制实现线程安全,其中segment继承自ReentrantLock,所以采用Lock锁来保证线程安全。
B. 
C. Arrays.asList()  返回  java.util.Arrays.ArrayList 对象,这里的 ArrayList 是 Arrays 私有的内部类
D. 

4. 类Parent和Child定义以下, 将如下哪一种方法插入行5是不合法的(    )

1 class  Parent{
2    public  float  aFun(float a, float b) { }
3 }
4 class  Child  extends  Parent{
5 }

正确答案: A   你的答案: C (错误)

A. float aFun(float a, float b){ }

B. public int aFun(int a, int b) { }

C. public float aFun(float p, float q){ }

D. private int aFun(int a, int b){ }

A.方法重写(覆盖)。子类方法不能缩小父类方法的访问权限,错误。
B.方法重载。参数列表不一样,知足重载条件,正确。
C.方法重写(覆盖)。方法声明和父类相同,知足重写条件,正确。
D.方法重载。参数列表不一样,知足重载条件,正确
 
 方法重写(Override)应遵循“两小一大一相同”原则:
  1. “两小”:子类异常小于等于父类,子类返回值小于等于父类;
  2. “一大”:子类方法的访问修饰符大于等于父类;
  3. “一相同”:方法签名相同。

5. list是一个ArrayList的对象,哪一个选项的代码填到//todo delete处,能够在Iterator遍历的过程当中正确并安全的删除一个list中保存的对象?()

Iterator it = list.iterator();
int index = 0;
while (it.hasNext())
{
    Object obj = it.next();
    if (needDelete(obj))  //needDelete返回boolean,决定是否要删除
    {
        //todo delete
    }
    index ++;
}

正确答案: A   你的答案: B (错误)

A. it.remove();

B. list.remove(obj);

C. list.remove(index);

D. list.remove(obj,index);

Iterator  支持从源集合中安全地删除对象,只需在 Iterator 上调用 remove() 便可。这样作的好处是能够避免 ConcurrentModifiedException ,当打开 Iterator 迭代集合时,同时又在对集合进行修改。有些集合不容许在迭代时删除或添加元素,可是调用 Iterator 的remove() 方法是个安全的作法。 

6. 面有关 JAVA 异常类的描述,说法正确的有()

正确答案: A B C   你的答案: A B C (正确)

A. 异常的继承结构:基类为 Throwable,Error 和 Exception 实现 Throwable,RuntimeException 和 IOException 等继承 Exception

B. 非 RuntimeException 通常是外部错误(不考虑Error的状况下),其必须在当前类被 try{}catch 语句块所捕获

C. Error 类体系描述了 Java 运行系统中的内部错误以及资源耗尽的情形,Error 不须要捕捉

D. RuntimeException 体系包括错误的类型转换、数组越界访问和试图访问空指针等等,必须 被 try{}catch 语句块所捕获

ABC

都是Throwable的子类: 
1.Exception(异常) :是程序自己能够处理的异常。 
2.Error(错误): 是程序没法处理的错误。这些错误表示故障发生于虚拟机自身、或者发生在虚拟机试图执行应用时,通常不须要程序处理。

3.检查异常(编译器要求必须处置的异常) :  除了Error,RuntimeException及其子类之外,其余的Exception类及其子类都属于可查异常。这种异常的特色是Java编译器会检查它,也就是说,当程序中可能出现这类异常,要么用try-catch语句捕获它,要么用throws子句声明抛出它,不然编译不会经过。

4.非检查异常(编译器不要求处置的异常): 包括运行时异常(RuntimeException与其子类)和错误(Error)。

14:41:14

1. 下列关于Java语言中String和char的说法,正确的是()

正确答案: C   你的答案: C (正确)

  A. String是Java定义的一种基本数据类型。

  B. String是以“\0”结尾的char类型的数组char[]。

  C. 使用equals()方法比较两个String是否内容同样(即字符串中的各个字符都同样)。

  D. Char类型在Java语言里面存储的是ASCII码。

A 基本数据类型包括byte,short,int,long,float,double,char,boolean,因此A错。
B,C语言当中是这样,java不是, String内部是用char[]数组实现的,不过结尾不用\0
C 对,字符串内容比较用equals方法。
D char存储的unicode码,不只能够存储ascII码,汉字也能够。

2. 在java中,不管在何处调用,使用静态属性必须以类名作前缀。

正确答案: B   你的答案: A (错误)

  A. 正确

  B. 错误

1若是是本类使用,能够直接就用静态变量名。2若是是其余类使用,可使用类名来调用,也能够建立一个实例对象来调用。3若是静态变量所在的类是静态类(即静态内部类,外部类没有静态的),那么无论在本类里或者在其余外部类,均可以直接使用静态变量名

 

3. 下列外部类定义中,不正确的是:( )

正确答案: C   你的答案: D (错误)

A. class x { .... }

B. class x extends y { .... }

C. static class x implements y1,y2 { .... }

D. public class x extends Applet { .... }

只有静态内部类,没有静态外部类。static不能用来修饰外部类
4. Math.round(11.5) 等于多少 (). Math.round(-11.5) 等于多少 (  ).

正确答案: C   你的答案: D (错误)

A. 11 ,-11

B. 11 ,-12

C. 12 ,-11

D. 12 ,-12

Math类中提供了三个与取整有关的方法:ceil,floor,round 。 ceil 向上取整,Math.ceil(11.3)的结果为12,Math.ceil(-11.6)的结果为-11;

                          floor向下取整,Math.floor(11.6)的结果是11,Math.floor(-11.4)的结果-12;

round方法,表示“四舍五入”,算法为Math.floor(x+0.5),  即将原来的数字加上0.5后再向下取整,因此,Math.round(11.5)的结果是12,Math.round(-11.5)的结果为-11.

5. 以下代码,执行test()函数后,屏幕打印结果为()

public class Test2
{
    public void add(Byte b)
    {
        b = b++;
    }
    public void test()
    {
        Byte a = 127;
        Byte b = 127;
        add(++a);
        System.out.print(a + " ");
        add(b);
        System.out.print(b + "");
    }
}

正确答案: D   你的答案: B (错误)

A. 127 127

B. 128 127

C. 129 128

D. 以上都不对

public void add(Byte b){ b=b++; } 这里涉及java的自动装包/自动拆包(AutoBoxing/UnBoxing) Byte的首字母为大写,是类,看似是引用传递,可是 在add函数内实现++操做,会自动拆包成byte值传递类型,因此add函数仍是不能实现自增功能。也就是说add函数只是个摆设,没有任何做用。 Byte类型值大小为-128~127之间。 add(++a);这里++a会越界,a的值变为-128 add(b); 前面说了,add不起任何做用,b仍是127
6. 下面代码的输出是什么?
public class Base
{
    private String baseName = "base";
    public Base()
    {
        callName();
    }
 
    public void callName()
    {
        System. out. println(baseName);
    }
 
    static class Sub extends Base
    {
        private String baseName = "sub";
        public void callName()
        {
            System. out. println (baseName) ;
        }
    }
    public static void main(String[] args)
    {
        Base b = new Sub();
    }
}

正确答案: A   你的答案: B (错误)

A. null

B. sub

C. base

 new Sub();在创造派生类的过程当中首先建立基类对象,而后才能建立派生类。
建立基类即默认调用Base()方法,在方法中调用callName()方法,因为派生类中存在此方法,则被调用的callName()方法是派生类中的方法,此时派生类还未构造,因此变量baseName的值为null

7. 对 Map 的用法,正确的有:

正确答案: C D   你的答案: B D (错误)

A. new java.util.Map().put("key" , "value") ;

B. new java.util.SortedMap().put("key" , "value") ;

C. new java.util.HashMap().put( null , null ) ;

D. new java.util.TreeMap().put( 0 , null ) ;

选C、D。考察的是Map接口实现类的建立对象以及对象类型包含的方法。
A选项Map属于接口类型,不能够new的方式建立对象。因此A错误。
B选项SortedMap属于接口类型,不能够new的方式建立对象。因此B错误。
C选项HashMap基于哈希表实现Map接口的类,并容许null的值和null键。
D选项TreeMap经过红黑树实现Map接口的类,key不能够为null,会报NullPointerException异常,value能够为null。
public static void main(String[] args) {
        TreeMap<String, Integer> treeMap = new TreeMap<>();
        treeMap.put("0",null);
        System.out.println(treeMap.get("0"));//结果为:null
    }
相关文章
相关标签/搜索