牛客网刷题错题集(2021/9/1)
时间:9月1日,记一次牛客网刷题错题集。
下列语句哪一个是不正确的()
正确答案: D 你的答案: C (错误)
Log4j支持按分钟为间隔生成新的日志文件
Log4j是一个打印日志用的组件
Log4j支持按年为间隔生成新的日志文件
Log4j的日志打印级别可以在运行时重新设置
答案解析:
日志的级别之间的大小关系如右所示:ALL < TRACE < DEBUG < INFO < WARN < ERROR < FATAL < OFF Log4j建议只使用四个级别,优先级从高到低分别是 ERROR > WARN > INFO > DEBUG。 log4j在运行期间是不可以重新设置的
如果一个接口Glass有个方法setColor(),有个类BlueGlass实现接口Glass,则在类BlueGlass中正确的是? ( )
正确答案: C 你的答案: D (错误)
protected void setColor() { …}
void setColor() { …}
public void setColor() { …}
以上语句都可以用在类BlueGlass中
答案解析:
JAVA 子类重写继承的方法时,不可以降低方法的访问权限,子类继承父类的访问修饰符要比父类的更大,也就是更加开放,假如我父类是protected修饰的,其子类只能是protected或者public,绝对不能是friendly(默认的访问范围)或者private,当然使用private就不是继承了。还要注意的是,继承当中子类抛出的异常必须是父类抛出的异常的子异常,或者子类抛出的异常要比父类抛出的异常要少。
下面哪个Set类是排序的?
正确答案: B 你的答案: A (错误)
LinkedHashSet
TreeSet
HashSet
AbstractSet
答案解析:
LinkedHashSet
继承于HashSet、又基于 LinkedHashMap 来实现
TreeSet
使用二叉树的原理对新 add()的对象按照指定的顺序排序(升序、降序),每增加一个对象都会进行排序,将对象插入的二叉树指定的位置。
HashSet
存储元素的顺序并不是按照存入时的顺序(和 List 显然不同) 而是按照哈希值来存的所以取数据也是按照哈希值取得
检查程序,是否存在问题,如果存在指出问题所在,如果不存在,说明输出结果。
public class Example {
String str = new String("good");
char[] ch = {
'a','b','c'};
public static void main(String[] args) {
Example ex = new Example();
ex.change(ex.str, ex.ch);
System.out.print(ex.str +"and");
System.out.print(ex.ch);
}
public void change(String str, char ch[]){
str= "test ok";
ch[0]= 'g';
}
}
正确答案: D 你的答案: B (错误)
test okandabc
test okandgbc
goodandabc
goodandgbc
答案解析:
java 中String是 immutable的,也就是不可变,一旦初始化,其引用指向的内容是不可变的。
也就是说,String str = “aa”;str=“bb”;第二句不是改变“aa”所存储地址的内容,而是另外开辟了一个空间用来存储“bb”;同时由str指向
原来的“aa”,现在已经不可达,GC时会自动回收。
因此String作为参数传进来时候,str= "test ok"; 实际给副本引用str指向了新分配的地址,该地址存储“test ok”。
因此,原先的str仍然指向“good”
执行语句“int a= ’ 2 ’ ”后,a的值是( )
正确答案: B 你的答案: A (错误)
2
50
49
0
答案解析:
常用ASCII码值:空格为32;数字0为48;“A”为65;“a”值为97。
下面这条语句一共创建了多少个对象:String s=“welcome”+“to”+360;
正确答案: A 你的答案: B (错误)
1
2
3
4
答案解析:
是否大家有没有刷到这类面试题:在执行String s = "Hello";s = s + " world!";这两行代码后,原始的String对象中的内容到底变了没有?
答案的解析:
没有。因为String被设计成不可变(immutable)类,所以它的所有对象都是不可变对象。在这段代码中,s原先指向一个String对象,内容是 "Hello",然后我们对s进行了+操作,那么s所指向的那个对象是否发生了改变呢?答案是没有。这时,s不指向原来那个对象了,而指向了另一个 String对象,内容为"Hello world!",原来那个对象还存在于内存之中,只是s这个引用变量不再指向它了。
通过上面的说明,我们很容易导出另一个结论,如果经常对字符串进行各种各样的修改,或者说,不可预见的修改,那么使用String来代表字符串的话会引起很大的内存开销。因为 String对象建立之后不能再改变,所以对于每一个不同的字符串,都需要一个String对象来表示。这时,应该考虑使用StringBuffer类,它允许修改,而不是每个不同的字符串都要生成一个新的对象。并且,这两种类的对象转换十分容易。
同时,我们还可以知道,如果要使用内容相同的字符串,不必每次都new一个String。例如我们要在构造器中对一个名叫s的String引用变量进行初始化,把它设置为初始值,应当这样做:
public class Demo {
private String s;
...
public Demo {
s = "Initial Value";
}
...
}
而非
s = new String("Initial Value");
后者每次都会调用构造器,生成新对象,性能低下且内存开销大,并且没有意义,因为String对象不可改变,所以对于内容相同的字符串,只要一个String对象来表示就可以了。也就说,多次调用上面的构造器创建多个对象,他们的String类型属性s都指向同一个对象。
上面的结论还基于这样一个事实:对于字符串常量,如果内容相同,Java认为它们代表同一个String对象。而用关键字new调用构造器,总是会创建一个新的对象,无论内容是否相同。
至于为什么要把String类设计成不可变类,是它的用途决定的。其实不只String,很多Java标准类库中的类都是不可变的。在开发一个系统的时候,我们有时候也需要设计不可变类,来传递一组相关的值,这也是面向对象思想的体现。不可变类有一些优点,比如因为它的对象是只读的,所以多线程并发访问也不会有任何问题。当然也有一些缺点,比如每个不同的状态都要一个对象来代表,可能会造成性能上的问题。所以Java标准类库还提供了一个可变版本,即 StringBuffer。
说说我的看法:字面量的创建是发生在编译期,类似于上述面试题,答案只创建一个对象。
下列哪些情况下会导致线程中断或停止运行( )
正确答案: A B 你的答案: A B D (错误)
InterruptedException异常被捕获
线程调用了wait方法
当前线程创建了一个新的线程
高优先级线程进入就绪状态
答案解析:
A选项正确,Java中一般通过interrupt方法中断线程
B选项正确,线程使用了wait方***强行打断当前操作,进入阻塞(暂停)状态,然后需要notify方法或notifyAll方法才能进入就绪状态
C选项错误,新创建的线程不会抢占时间片,只有等当前线程把时间片用完,其他线程才有资格拿到时间片去执行。
D选项错误,调度算法未必是剥夺式的,而准备就绪但是还没有获得CPU,它的权限更高只能说明它获得CPU被执行的几率更大而已
本人线程知识薄弱,呜呜呜.......
以下关于final关键字说法错误的是
正确答案: A C 你的答案: A B (错误)
final是java中的修饰符,可以修饰类、接口、抽象类、方法和属性
final修饰的类肯定不能被继承
final修饰的方法不能被重载
final修饰的变量不允许被再次赋值
答案解析:
final修饰类、方法、属性!不能修饰抽象类,因为抽象类一般都是需要被继承的,final修饰后就不能继承了。
final修饰的方法不能被重写而不是重载!
final修饰属性,此属性就是一个常量,不能被再次赋值!
执行如下程序代码
char chr = 127;
int sum = 200;
chr += 1;
sum += chr;
后,sum的值是 ; ( )
备注:同时考虑c/c++和Java的情况的话
正确答案: A C 你的答案: C D (错误)
72
99
328
327
答案解析:
java中只有byte, boolean是一个字节, char是两个字节, 所以对于java来说127不会发生溢出, 输出328
但是对于c/c++语言来说, char是一个字节, 会发生溢出, 对127加一发生溢出, 0111 1111 --> 1000 0000, 1000 0000为补码-128, 所以结果为200-128=72
下面有关java threadlocal说法正确的有?
正确答案: A B C D 你的答案: A C D (错误)
ThreadLocal存放的值是线程封闭,线程间互斥的,主要用于线程内共享一些数据,避免通过参数来传递
从线程的角度看,每个线程都保持一个对其线程局部变量副本的隐式引用,只要线程是活动的并且 ThreadLocal 实例是可访问的;在线程消失之后,其线程局部实例的所有副本都会被垃圾回收
在Thread类中有一个Map,用于存储每一个线程的变量的副本
对于多线程资源共享的问题,同步机制采用了“以时间换空间”的方式,而ThreadLocal采用了“以空间换时间”的方式
答案解析:
ThreadLocal类用于创建一个线程本地变量
在Thread中有一个成员变量ThreadLocals,该变量的类型是ThreadLocalMap,也就是一个Map,它的键是threadLocal,值为就是变量的副本。通过ThreadLocal的get()方法可以获取该线程变量的本地副本,在get方法之前要先set,否则就要重写initialValue()方法。
ThreadLocal的使用场景:
数据库连接:在多线程中,如果使用懒汉式的单例模式创建Connection对象,由于该对象是共享的,那么必须要使用同步方法保证线程安全,这样当一个线程在连接数据库时,那么另外一个线程只能等待。这样就造成性能降低。如果改为哪里要连接数据库就来进行连接,那么就会频繁的对数据库进行连接,性能还是不高。这时使用ThreadLocal就可以既可以保证线程安全又可以让性能不会太低。但是ThreadLocal的缺点时占用了较多的空间。
总结
学而时习之,不亦说乎!!!