第二周
基础
1
尝试编译以下程序会产生怎么样的结果?()
1 | public class MyClass { |
- A:编译错误将发生在(1),因为构造函数不能指定返回值
- B:编译错误将发生在(2),因为该类没有默认构造函数
- C:编译错误将在(3)处发生,因为该类没有构造函数,该构造函数接受一个int类型的参数
- D:该程序将正确编译和执行
解析:
这道题一定要看仔细了,MyClass方法并不是构造参数,而是返回类型为void的普通方法,普通方法自然需要实例化对象然后去调用它,所以124不对,第三个是正确的,因为没有带参数的构造器,所以自然不能传一个int进去。
2
从内存实现或者反射的角度来看,关于继承的说法正确的是()。
注:此处的继承不代表能调用
- A:子类将继承父类的所有的数据域和方法
- B:子类将继承父类的其可见的数据域和方法
- C:子类只继承父类public方法和数据域
- D:子类只继承父类的方法,而不继承数据域
解析:
子类可以继承父类的全部数据域和方法,但是这里继承代表的是“拥有”,即:只是拥有父类的全部数据域和方法,但不具备对某些私有数据域或私有方法的使用权(调用)。
这道题明确标注:此处的继承不代表能调用。
3
java语言的下面几种数组复制方法中,哪个效率最高?
- A:for 循环逐一复制
- B:System.arraycopy
- C:Array.copyOf
- D:使用clone方法
解析:
复制的效率System.arraycopy>clone>Arrays.copyOf>for循环
这里面在System类源码中给出了arraycopy的方法,是native方法,也就是本地方法,肯定是最快的。而Arrays.copyOf(注意是Arrays类,不是Array实现的,在源码中是调用System.copyOf的,多了一个步骤,肯定就不是最快的。
4
下列代码的输出结果是_
- A:true
- B:false
- C:null
- D:空字符串
解析:
== 优先级高于 三目运算符,先判断 true == true,此时返回为 true,
这时表达式为 boolean b = true?false:true?false:true
此时三目运算符从右向左执行,true?false:true,返回false
这时表达式为 boolean b = true?false:false;
结果为:boolean b = false ;
5
(多选)Which statement declares a variable a which is suitable for referring to an array of 50 string objects?(Java)
- A:char a[][];
- B:String a[];
- C:String[] a;
- D:Object a[50];
- E:String a[50];
- F:Object a[];
解析:
在java 中,声明一个数组时,不能直接限定数组长度,只有在创建实例化对象时,才能对给定数组长度。
如下,1、2、3可以通过编译,4、5不行。而String是Object的子类,所以上述BCF均可定义一个存放50个String类型对象的数组。
String a[]=new String[50];
String b[];
char c[];
String d[50];
char e[50];
6
运行代码,输出的结果是()
1 | public class P { |
- A:P is init
123 - B:S is init
P is init
123 - C:P is init
S is init
123 - D:S is init
123
解析:
被动引用不会出发子类初始化
1.子类引用父类的静态字段,只会触发子类的加载、父类的初始化,不会导致子类初始化
2.通过数组定义来引用类,不会触发此类的初始化
3.常量在编译阶段会进行常量优化,将常量存入调用类的常量池中, 本质上并没有直接引用到定义常量的类,因此不会触发定义常量的类的初始化。
7
下列哪个选项是Java调试器?如果编译器返回程序代码的错误,可以用它对程序进行调试。
- A:java.exe
- B:javadoc.exe
- C:jdb.exe
- D:javaprof.exe
解析:
javac.exe是编译.java文件
java.exe是执行编译好的.class文件
javadoc.exe是生成Java说明文档
jdb.exe是Java调试器
javaprof.exe是剖析工具
class A {}
class B extends A {}
class C extends A {}
class D extends B {}
(多选)Which four statements are true ?
- A:The type Listis assignable to List.
- B:The type Listis assignable to List.
- C:The type List
- D:The type List
is assignable to List<?extends B>. - E:The type List<?extends A>is assignable to List.
- F:The type List
- G:The type List<?extends B>is assignable to List<?extends A>.
解析:
1. 只看尖括号里边的!!明确点和范围两个概念
2. 如果尖括号里的是一个类,那么尖括号里的就是一个点,比如List,List,List
3. 如果尖括号里面带有问号,那么代表一个范围, extends A> 代表小于等于A的范围, super A>代表大于等于A的范围,>代表全部范围
4. 尖括号里的所有点之间互相赋值都是错,除非是俩相同的点
5. 尖括号小范围赋值给大范围,对,大范围赋值给小范围,错。如果某点包含在某个范围里,那么可以赋值,否则,不能赋值
6. List<?>和List 是相等的,都代表最大范围
7. List既是点也是范围,当表示范围时,表示最大范围
A:√ List就是List<?>代表最大的范围,A只是其中的一个点,肯定包含在内。
B:× 点与点之间不能相互赋值
C:√ List<?>表示最大的范围,List
D:√ List<? extends B>代表小于等于B的范围,List
是一个点,在其中。 E:× 点不能赋值给点
F:× List
G:√ 小于等于A的范围包含小于等于B的范围
8
(多选)如下哪些是 java 中有效的关键字()
- A:native
- B:NULL
- C:false
- D:this
解析:
true、false、null都不是关键字
goto、const、是保留的关键字
1
2
3
4
5
6
7
8
9
10
11
12
13 abstract continue for new
switch default if package
synchronized do goto private
this break double implements
protected throw byte else
import public throws case
enum instanceof return transient
catch extends int short
try char final interface
static void class finally
long strictfp volatile const
float native super while
boolean assert
9
What results from the following code fragment?
1 | int i = 5; |
- A:Compilation error because”~”doesn’t operate on integers
- B:-5
- C:-6
- D:15
解析:
公式-n= ~ n+1可推出 ~ n=-n-1,所以~10=-11再加5结果为-6
计算机本身储存的就是补码:
那么10的补码就是10的原码:0000 0000 0000 1010——这是补码,因为现在是计算机在计算
~10的补码就是:1111 1111 1111 0101
~10的反码就是:1111 1111 1111 0100——补码减1
~10的原码就是:1000 0000 0000 1011——反码取反:这个才是正常二进制数,换算为整数为-11
原码才可以对应为正常的整数,补码只有转换为原码才能被正常人类识别。
10
抽象类方法的访问权限默认都是public。( )
- A:正确
- B:错误
解析:
关于抽象类
JDK 1.8以前,抽象类的方法默认访问权限为protected
JDK 1.8时,抽象类的方法默认访问权限变为default
关于接口
JDK 1.8以前,接口中的方法必须是public的
JDK 1.8时,接口中的方法可以是public的,也可以是default的
JDK 1.9时,接口中的方法可以是private的
11
(多选)Java创建对象的说法正确的有()
- A:用new语句创建对象,是最常见的创建对象的方法。
- B:运用反射手段,调用java.lang.Class或者java.lang.reflect.Constructor类的newInstance()实例方法。
- C:调用对象的clone()方法。
- D:运用反序列化手段,调用java.io.ObjectInputStream对象的 readObject()方法。
解析:
Java有5种方式来创建对象:
- 使用 new 关键字(最常用): ObjectName obj = new ObjectName();
- 使用反射的Class类的newInstance()方法: ObjectName obj = ObjectName.class.newInstance();
- 使用反射的Constructor类的newInstance()方法: ObjectName obj = ObjectName.class.getConstructor.newInstance();
- 使用对象克隆clone()方法: ObjectName obj = obj.clone();
- 使用反序列化(ObjectInputStream)的readObject()方法: try (ObjectInputStream ois = new ObjectInputStream(new FileInputStream(FILE_NAME))) { ObjectName obj = ois.readObject(); }
12
(多选)关于Java中的数组,下面的一些描述,哪些描述是准确的:( )
- A:数组是一个对象,不同类型的数组具有不同的类
- B:数组长度是可以动态调整的
- C:数组是一个连续的存储结构
- D:一个固定长度的数组可类似这样定义: int array[100]
- E:两个数组用equals方法比较时,会逐个便利其中的元素,对每个元素进行比较
- F:可以二维数组,且可以有多维数组,都是在Java中合法的
解析:
1
2
3
4
5
6
7
8
9
10
11 public static void main(String[] args) {
int[] i = new int[]{1,2,3};
int[] j = new int[]{1,2,3};
int[] k = i;
int[] array = new int[100];
double[] array_1 = new double[100];
System.out.println(array);
System.out.println(array_1);
System.out.println(i.equals(j));
System.out.println(i.equals(k));
}
1
2
3
4 [I@6d6f6e28
[D@135fbaa4
false
trueA 数组是对象,因为可以调用方法,从上面的输出结果可以看出不同类型的数组具有不同的类
B 数组长度是不能动态调整的
C Java中的数组中的数据是连续存储在一块内存中的,所以可以通过下标(即偏移量)的方式访问
D 固定长度的数组定义如上
E 查看源码可以知道数组的equals方法是object的equals,比较的是内存地址,Arrays.equal()可以比较数组元素。
F java可以有多维数组
13
以下JAVA程序的运行结果是什么( )
1 | public static void main(String[] args) { |
- A:1 1
- B:1.0 1.0
- C:1 1.0
- D:1.0 1
解析:
三元操作符类型的转换规则:
若两个操作数不可转换,则不做转换,返回值为Object类型
若两个操作数是明确类型的表达式(比如变量),则按照正常的二进制数字来转换,int类型转换为long类型,long类型转换为float类型等。
若两个操作数中有一个是数字S,另外一个是表达式,且其类型标示为T,那么,若数字S在T的范围内,则转换为T类型;若S超出了T类型的范围,则T转换为S类型。
若两个操作数都是直接量数字,则返回值类型为范围较大者
14
以下关于Object类的说法正确的是()
- A:Java中所有的类都直接或间接继承自Object,无论是否明确的指明,无论其是否是抽象类。
- B:Java中的接口(interface)也继承了Object类
- C:利用“==”比较两个对象时,Java调用继承自Object的equals方法,判断是否相等。
- D:如果类的定义中没有重新定义toString()方法,则该类创建的对象无法使用toStrig()方法。
解析:
A:Object 是基类 Java中的所有的类都直接或间接的继承;所以A对
B:从一个class派生的必然是另一个class。Object是一个class,如果interface继承自Object,那么interface必然是一个class,所以B错
C:利用equals()方法进行比较时 会调用== 可以看equals()方法的源码,可以这样说, == 比equal更加强大,所以C错
D:toString()方法是Object类中 即使不重写也能使用 所以D错
15
(多选)Java类Demo中存在方法func0、func1、func2、func3和func4,请问该方法中,哪些是不合法的定义?( )
1 | public class Demo{ |
- A:func1
- B:func2
- C:func3
- D:func4
解析:
数据类型的转换,分为自动转换和强制转换。自动转换是程序在执行过程中 “ 悄然 ” 进行的转换,不需要用户提前声明,一般是从位数低的类型向位数高的类型转换;强制类型转换则必须在代码中声明,转换顺序不受限制。
自动数据类型转换
自动转换按从低到高的顺序转换。不同类型数据间的优先关系如下:
低 ———————————————> 高
byte,short,char-> int -> long -> float -> double运算中,不同类型的数据先转化为同一类型,然后进行运算,转换规则如下:
操作数 1 类型 操作数 2 类型 转换后的类型 byte 、 short 、 char int int byte 、 short 、 char 、 int long long byte 、 short 、 char 、 int 、 long float float byte 、 short 、 char 、 int 、 long 、 float double double 强制数据类型转换
强制转换的格式是在需要转型的数据前加上 “( )” ,然后在括号内加入需要转化的数据类型。有的数据经过转型运算后,精度会丢失,而有的会更加精确
16
Consider the following code:
String s=null;
Which code fragments cause an object of type NullPointerException to be thrown?
- A:if((s!=null)&(s.length()>0))
- B:if((s!=null)&&(s.length()>0))
- C:if((s == null)|(s.length()==0))
- D:if((s == null)||(s.length()==0))
解析:
s为null,因此只要调用了s.length()都会抛出空指针异常。因此这个题目就是考察if语句的后半部分会不会执行。
A:单个与操作的符号& 用在整数上是按位与,用在布尔型变量上跟&&功能类似,但是区别是无论前面是否为真,后面必定执行,因此抛出异常
B:与操作,前半部分判断为假,后面不再执行
C:这里跟 & 和&& 的区别类似,后面必定执行,因此抛出异常
D:或语句,前面为真,整个结果必定为真,后面不执行
17
(重要)下面代码的输出是什么?
1 | public class Base |
- A:null
- B:sub
- C:base
解析:
1.首先,需要明白类的加载顺序。
(1) 父类静态代码块(包括静态初始化块,静态属性,但不包括静态方法)
(2) 子类静态代码块(包括静态初始化块,静态属性,但不包括静态方法 )
(3) 父类非静态代码块( 包括非静态初始化块,非静态属性 )
(4) 父类构造函数
(5) 子类非静态代码块 ( 包括非静态初始化块,非静态属性 )
(6) 子类构造函数
其中:类中静态块按照声明顺序执行,并且(1)和(2)不需要调用new类实例的时候就执行了(意思就是在类加载到方法区的时候执行的)
2.其次,需要理解子类覆盖父类方法的问题,也就是方法重写实现多态问题。
Base b = new Sub();它为多态的一种表现形式,声明是Base,实现是Sub类, 理解为 b 编译时表现为Base类特性,运行时表现为Sub类特性(这个非常重要)。
当子类覆盖了父类的方法后,意思是父类的方法已经被重写,题中 父类初始化调用的方法为子类实现的方法,子类实现的方法中调用的baseName为子类中的私有属性。
由1.可知,此时只执行到步骤4.,子类非静态代码块和初始化步骤还没有到,子类中的baseName还没有被初始化。所以此时 baseName为空。 所以为null。
19
设有下面两个赋值语句:
1 | a = Integer.parseInt("1024"); |
下述说法正确的是()
- A:a是整数类型变量,b是整数类对象。
- B:a是整数类对象,b是整数类型变量。
- C:a和b都是整数类对象并且它们的值相等。
- D:a和b都是整数类型变量并且它们的值相等。
解析:
intValue()是把Integer对象类型变成int的基础数据类型;
parseInt()是把String 变成int的基础数据类型;
Valueof()是把String 转化成Integer对象类型;(现在JDK版本支持自动装箱拆箱了。)
本题:parseInt得到的是基础数据类型int,valueof得到的是装箱数据类型Integer,然后再通过intValue转换成int,所以选择D
20
A 是抽象父类或接口, B , C 派生自 A ,或实现 A ,现在 Java 源代码中有如下声明:
1 | 1. A a0 = new A(); |
问以下哪个说法是正确的?( )
- A:第1行不能通过编译
- B:第1、2行能通过编译,但第3行编译出错
- C:第1、2、3行能通过编译,但第2、3行运行时出错
- D:第1行、第2行和第3行的声明都是正确的
解析:
抽象类和接口不能实例化了这个我竟然没注意。。。
21
以下代码执行后输出结果为( )
1 | public class Test |
- A:blockAblockBblockA
- B:blockAblockAblockB
- C:blockBblockBblockA
- D:blockBblockAblockB
解析:
首先区别
是类初始化, 是实例初始化 类装载准备阶段->类初始化clinit阶段
类装载准备阶段:变量赋系统要求的初始值(0或者null等),final变量会在此时赋用户定义的初始值
类初始化
过程: Step1 编译器收集t1的赋值动作,static语句块,main方法语句块
Step2 执行收集好的语句块:
Step2.1 执行t1 = new Test,发现clinit过程已经调用,于是可以开始触发init过程,执行成员变量的初始化(此处没有),以及非静态代码块,输出blockA,最后调用构造函数(此处没有)
Step2.2 按照顺序,执行static语句块,输出blockB
Step2.3 按照顺序,执行main方法语句块,执行t2 = new Test,触发init方法,执行非静态代码块,输出blockA
其实这题很简单,第一你要搞懂,这程序是怎么走的,从上往下。第二你要知道静态块和构造块,静态块是程序走到静态快的位置就自动执行,仅且执行一次,构造块是创建类对象(实例化)操作时就加载一次。最后把题目从上往下执行,遵循第一和第二,就得到答案了。
1 | public class DataObject implements Serializable{ |
22
创建一个如下方式的DataObject:
1 | DataObject object=new Data0bject ( ); |
将此对象序列化为文件,并在另外一个JVM中读取文件,进行反序列化,请问此时读出的Data0bject对象中的word和i的值分别为:
- A:“”, 0
- B:“”, 2
- C:“123”, 2
- D:“123”, 0
解析:
Java在序列化时不会实例化static变量和transient修饰的变量,因为static代表类的成员,transient代表对象的临时数据,被声明这两种类型的数据成员不能被序列化。
23
1 | byte b1=1,b2=2,b3,b6,b8; |
(多选)下列代码片段中,存在编译错误的语句是()
- A:语句2
- B:语句1
- C:语句3
- D:语句4
解析:
Java表达式转型规则由低到高转换:
1、所有的byte,short,char型的值将被提升为int型;
2、如果有一个操作数是long型,计算结果是long型;
3、如果有一个操作数是float型,计算结果是float型;
4、如果有一个操作数是double型,计算结果是double型;
5、被fianl修饰的变量不会自动改变类型,当2个final修饰相操作时,结果会根据左边变量的类型而转化。
语句1错误:b3=(b1+b2);自动转为int,所以正确写法为b3=(byte)(b1+b2);或者将b3定义为int;
语句2正确:b6=b4+b5;b4、b5为final类型,不会自动提升,所以和的类型视左边变量类型而定,即b6可以是任意数值类型;
语句3错误:b8=(b1+b4);虽然b4不会自动提升,但b1仍会自动提升,所以结果需要强转,b8=(byte)(b1+b4);
语句4错误:b7=(b2+b5); 同上。同时注意b7是final修饰,即只可赋值一次,便不可再改变。
24
(多选)Java语言中,下面哪个语句是创建数组的正确语句?( )
- A:float f[][] = new float
[6][6]; - B:float []f[] = new float
[6][6]; - C:float f[][] = new float
[][6]; - D:float [][]f = new float
[6][6]; - E:float [][]f = new float
[6][];
解析:注意B选项就行,还有就是第一个框中必须有值!!
25
(多选)以下类型为Final类型的为()
- A:HashMap
- B:StringBuffer
- C:String
- D:Hashtable
解析:
StringBuilder , StringBuffer ,String 都是 final 的,但是为什么StringBuilder , StringBuffer可以进行修改呢,因为不可变包括的是,引用不可变以及对象不可变,而这三个都是属于引用不可变,(也就是地址不要变,里面的内容随心所欲),而StringBuilder , StringBuffer 中都包含右append方法,可对对象中的内容进行增加。
而String a=”123”+new String(“456”);实际上底层是用了一个StringBuffer 进行append;
26
(多选)Java1.8版本之前的前提,Java特性中,abstract class和interface有什么区别()
- A:抽象类可以有构造方法,接口中不能有构造方法
- B:抽象类中可以有普通成员变量,接口中没有普通成员变量
- C:抽象类中不可以包含静态方法,接口中可以包含静态方法
- D:一个类可以实现多个接口,但只能继承一个抽象类。
解析:
A B D显然都是对的。主要说C选项:
在JDK1.8之前的版本(不包括JDK1.8),接口中不能有静态方法,抽象类中因为有普通方法,故也可以有静态方法。
在JDK1.8后(包括JDK1.8),在抽象类中依旧可以有静态方法,同时在接口中也可以定义静态方法了。
以下代码在JDK1.8之后是没有问题的(可以通过接口名来调用静态方法 :Main.prinf(); ):
1
2
3
4
5 public interface Demo{
public static void print() {
System.out.println("Hello World!");
}
}PS:
在JDK1.7,接口中只包含抽象方法,使用public abstract 修饰。
1 public interface Demo{ public abstract void method();}在JDK1.8,接口中新加了默认方法和静态方法:
默认方法:使用default修饰,在接口的实现类中,可以直接调用该方法,也可以重写该方法。
静态方法:使用static修饰,通过接口直接调用。
1
2
3
4
5
6
7
8
9
10 public interface Demo{
//默认方法
public default void method(){
System.out.println("default method...");
}
//静态方法
public static void print(){
System.out.println("static method...");
}
}在JDK1.9,接口中新加了私有方法,使用private修饰,私有方法供接口内的默认方法和静态方法调用。
1
2
3
4
5 public interface Demo{
private void method() {
System.out.println("Hello World!");
}
}
27
()运算符把其操作数中所有值为0和所有值为1的位分别在结果的相应中设置1和0
- A:&
- B:|
- C:!
- D:~
解析:
是位运算符,意义是 按位非(NOT)”是对其运算数的每一位取反。
按位非也叫做补,一元运算符NOT“
- 仅用于整数值
- 反转位,即0位变为1位,1变成0
- 在所有情况下〜x等于(-x)- 1
例如
1 ~ 0111 (7) = 1000 (8)
28
Java 源程序文件的扩展名为()
- A:.java
- B:.class
- C:.exe
- D:.jar
解析:
java中源文件的后缀为.java,经过javac.exe编译后生成字节码文件,后缀为.class,再经过java.exe编译为可执行文件,后缀为.exe。
29
下列程序的运行结果
1 | public void getCustomerInfo() { |
- A:IOException!
- B:IOException!Exception!
- C:FileNotFoundException!IOException!
- D:FileNotFoundException!IOException!Exception!
解析:
try-catch-finally 规则
1) 必须在 try 之后添加 catch 或 finally 块。try 块后可同时接 catch 和 finally 块,但至少有一个块。
2) 必须遵循块顺序:若代码同时使用 catch 和 finally 块,则必须将 catch 块放在 try 块之后。
3) catch 块与相应的异常类的类型相关。
4) 一个 try 块可能有多个 catch 块。若如此,则执行第一个匹配块。即Java虚拟机会把实际抛出的异常对象依次和各个catch代码块声明的异常类型匹配,如果异常对象为某个异常类型或 其子类的实例,就执行这个catch代码块,不会再执行其他的 catch代码块
5) 可嵌套 try-catch-finally 结构。
6) 在 try-catch-finally 结构中,可重新抛出异常。
由此可以看出,catch只会匹配一个,因为只要匹配了一个,虚拟机就会使整个语句退出
多线程
30
(多选)下面有关java threadlocal说法正确的有?
- A:ThreadLocal存放的值是线程封闭,线程间互斥的,主要用于线程内共享一些数据,避免通过参数来传递
- B:线程的角度看,每个线程都保持一个对其线程局部变量副本的隐式引用,只要线程是活动的并且 ThreadLocal 实例是可访问的;在线程消失之后,其线程局部实例的所有副本都会被垃圾回收
- C:在Thread类中有一个Map,用于存储每一个线程的变量的副本。
- D:对于多线程资源共享的问题,同步机制采用了“以时间换空间”的方式,而ThreadLocal采用了“以空间换时间”的方式
解析:
ThreadLocal类用来提供线程内部的局部变量。这种变量在多线程环境下访问(通过get或set方法访问)时能保证各个线程里的变量相对独立于其他线程内的变量。ThreadLocal实例通常来说都是private static类型的,用于关联线程和线程的上下文。 可以总结为一句话:ThreadLocal的作用是提供线程内的局部变量,这种变量在线程的生命周期内起作用,减少同一个线程内多个函数或者组件之间一些公共变量的传递的复杂度。 ThreadLocal设计的初衷:提供线程内部的局部变量,在本线程内随时随地可取,隔离其他线程。
IO
31
(多选)下面的类哪些可以处理Unicode字符?
- A:InputStreamReader
- B:BufferedReader
- C:Writer
- D:PipedInputStream
解析:
后缀是Stream的都是字节流,其他的都是字符流。
算法
32
下面程序段的时间复杂度是()
1 | i = k = 0; |
- A:O(n)
- B:O(n^1/2)
- C:O(n*i)
- D:O(n+i)
解析:
设q为一共要执行的次数
k=0+1; k=1+1
q ^ 2+q+1/4=2n+1/4
(q+1/2)=(2n+1/4) ^ 1/2
q=(2n+1/4)^1/2-1/2
所以 T(n)=O(n^1/2)
JVM
33
运用下列哪个命令能够获取JVM的内存映像
- A:jinfo
- B:jmap
- C:jhat
- D:jstat
解析:
jps:查看本机java进程信息。
jstack:打印线程栈信息,制作线程dump文件。
jmap:打印内存映射,制作堆dump文件
jstat:性能监控工具。
jhat:内存分析工具
jconsole:简易的可视化控制台
jvisualvm:功能强大的控制台
jinfo
如何查看当前运行程序的配置
jps -l查看当前所有的进程及进程号
方式一:jinfo -flag 配置项 进程号
方式二:jinfo -flags 进程号(可查看所有配置项,包括系统默认的和人工自己配置的)



