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 extends E> 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;i
我们来看System.arraycopy源码:
public static native void arraycopy(Object src, int srcPos,
Object dest, int destPos,
int length);
可以看到调用了本地方法,该方法的实现不是由java完成,一般来说是C/C++完成的,底层实现。
再来看看Arrays.copyof源码:
public static byte[] copyOf(byte[] original, int newLength) {
byte[] copy = new byte[newLength];
System.arraycopy(original, 0, copy, 0,
Math.min(original.length, newLength));
return copy;
}
我们可以看到,这个方法的本质其实也是调用本地方法,其多花的时间就是用到了Mth.min方法上。
for循环,之所以那么耗时间,是因为每次循环都要进行数组最大值的判断和进行下一次循环,下标值的加法运算。
关于clone,上网找了好久,没找到关于源码的,所以这个下次找到了及时更新。
10.下面那一项不是加载驱动程序的方法?()
A.通过DriverManger.getConnection方法加载
B.调用方法Class.forName
C.通过添加系统的jdbc.drivers属性
D.通过registerDriver方法注册
答案:A
解析:
11.以下代码对其执行后,NumberList里的元素依次为:
List 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中,
StringBuilder
和StringBuffer
的区别,下面说法错误的是?
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的效率最高,因为在编译过程中,这个方式是直接为一个字符串常量的。