考点1:

下列说法哪个正确( )

  • A 不需要定义类,就能创建对象
  • B 对象中必须有数据域和方法
  • C 数据域可以是基本类型变量,也可以是一个对象
  • D 数据域必须是基本类型变量

解析

显示答案/隐藏答案正确答案: C

数据域,也就是个成员变量(类的属性),不包括成员方法。成员变量可以是基本数据类型的变量,也可以是引用数据类型的变量(既可以说一个类的引用,如String str)

考点2:成员变量的初始化

程序Demo.java编译运行后输出的结果是:( )

1
2
3
4
5
6
7
8
9
public class Demo{
int x=1;
int y;
public static void main(String [] args){
int z=2;
Demo t=new Demo();
System.out.println(t.x+t.y+z);
}
}
  • A 3
  • B 12
  • C 1
  • D 5

解析

显示答案/隐藏答案正确答案: A

成员变量有默认初始化

成员变量和静态变量是有默认值的。

成员变量为int类型可以不初始化,默认值为0

局部变量必须初始化

局部变量为int类型必须初始化,没有默认值

这题考的是默认初始化问题,但是可以引出另外一个问题:
局部变量参与运算前是必须要初始化的,比如下面的代码就会编译出错,提示y必须要初始化。

1
2
3
4
5
public static void main(String[] args) {
int x = 1;
int y;
int z = x + y;
}

编译器错误提示:

1
The local variable y may not have been initialized

考点3:static 访问控制符

在java中,在同一包内,类Cat里面有个公有方法sleep(),该方法前有static修饰,则可以直接用Cat.sleep()。( )

  • A 正确
  • B 错误

解析

显示答案/隐藏答案正确答案: A

如果是private,则在其他类中
但并且在其他类就不能这么直接用了

访问控制符修饰的成员可见范围

位置 public protected default private
同一个类中
同一个包中
子类中
全局

考点4:

下列表述错误的是?()

  • A int是基本类型,直接存数值,Integer是对象,用一个引用指向这个对象。
  • B 在子类构造方法中使用super()显示调用父类的构造方法,super()必须写在子类构造方法的第一行,否则编译不通过
  • C 封装的主要作用在于对外隐藏内部实现细节,可以增强程序的安全性
  • D finaljava中的修饰符,可以修饰类、接口、抽象类、方法和属性。

解析

显示答案/隐藏答案正确答案: D

abstract和final矛盾

抽象类:子类可以继承和重写;
final:类不允许被重写;
故,final不能修饰抽象类,否则自相矛盾。

考点5:访问控制符

下列哪个修饰符可以使在一个类中定义的成员变量只能被同一包中的类访问?

  • A private
  • B 无修饰符
  • C public
  • D protected

解析

显示答案/隐藏答案正确答案: B

访问控制符修饰的成员可见范围

位置 public protected 无修饰符 private
同一个类中
同一个包中
子类中
全局

包访问权限

无修饰符就是默认权限,也叫包访问权限,只能被同一包内的类访问。

考点6:

已知如下类说明:

1
2
3
4
5
6
7
8
public class Test{
private float f=1.0f;
int m=12;
static int n=1;
public static void main(String args[]){
Test t=new Test();
}
}

在main方法中如下哪些使用是正确的()

  • A t.f = 1.0
  • B this.n
  • C Test.m
  • D Test.n

解析

显示答案/隐藏答案正确答案: D

A. 1.0默认为double类型,float f = 1.0编译出错,如果是float f= 1或者float f=1.0f就可以通过
编译器报错如下

1
Type mismatch: cannot convert from double to float

B. main方式是static修饰的,main方法存在时,当前对象还没有初始化,也就是没有this引用。
编译器报错如下:

1
Cannot use this in a static context

C. m不是static的,需要依附于对象存在,不能通过类名调用。
编译器报错如下:

1
Cannot make a static reference to the non-static field Test.m

考点7:访问控制符

访问权限控制从最大权限到最小权限依次为:public、 包访问权限、protected和private 。( )

  • A 正确
  • B 错误

解析

显示答案/隐藏答案正确答案: B

访问控制符从大到小

位置 public protected 无修饰符 private
同一个类中
同一个包中
子类中
全局

考点8:哪个式子有可能在某个进制下成立

以下哪个式子有可能在某个进制下成立()?

  • A 13*14=204
  • B 12*34=568
  • C 14*14=140
  • D 1+1=3

解析

显示答案/隐藏答案正确答案: A

N进制按权展开

A选项

$$
13 \times 14=204
$$

设在$x$​进制下该式子成立,按$x$​展开得到:

$$
\begin{aligned}
(1\times x^1+3\times x^0)\times (1\times x^1+4\times x^0)&=2\times x^2+0\times x^1+4\times x^0\\
(x+3)\times(x+4)&=2x^2+4\\
x^2+7x+12&=2x^2+4\\
7x+8&=x^2\\
x^2-7x-8&=0
\end{aligned}
$$

这是个一元二次方程,使用韦达定理

$$
x ={-b \pm \sqrt{b^2-4ac}\over 2a}
$$

来求解:

$$
\sqrt{b^2-4ac}=\sqrt{(-7)^2-4\times 1\times(-8)}=\sqrt{81}=9
$$

$$
x_1 ={-b + \sqrt{b^2-4ac}\over 2a}
=\frac{-(-7)+9}{2\times 1}
=\frac{16}{2}=8
$$

$$
x_2={-b - \sqrt{b^2-4ac}\over 2a}
=\frac{-(-7)-9}{2\times 1}
=\frac{-2}{2}
=-1
$$

得到 $x_1=8$​​ , $x_2=-1$​​,

没有$-1$进制,排除$x_2$​​.

所以在$8$​​进制下,这个式子成立。A选项正确

B选项

$$
12\times 34=568
$$

设在x进制下,这个式子成立,则:

$$
\begin{aligned}
(x+2)(3x+4)&=5x^2+6x+8\\
3x^2+4x+6x+8&=5x^2+6x+8\\
3x^2+4x&=5x^2\\
4x&=2x^2\\
2x&=x^2\\
x^2-2x&=0\\
x(x-2)&=0\\
\end{aligned}
$$

解得

$$
x_1=0,x_2=2
$$

没有0进制,$x_1$​排除,

$N$​进制的最大的数为$N-1$​

2进制的最大的数为1,式子$12\times 34=568$中2,3,4,5,6,8都大于2进制的数1.

$x_2$​​排除所以式子不成立,B选项错误

C选项

$$
\begin{aligned}
(x+4)(x+4)&=x^2+4x\\
x^2+4x+4x+16&=x^2+4x\\
4x+16&=0\\
\end{aligned}
$$

解得$x=-4$。没有$-4$进制,C选项错误

D选项

$$\begin{aligned}
1\times x^0+1\times x^0&=3\times x^0\\
2 \times x^0&=3\times x^0\\
0&=1\times x^0\\
0&=1\times 1\\
\end{aligned}
$$

得到
$$
0=1
$$
实际上,0不等于1D选项错误

考点9:线程安全

下列那些方法是线程安全的(所调用的方法都存在)

  • A public class MyServlet implements Servlet { public void service (ServletRequest req, ServletResponse resp) { BigInteger I = extractFromRequest(req); encodeIntoResponse(resp,factors); } }
  • B public class MyServlet implements Servlet { private long count =0; public long getCount() { return count; } public void service (ServletRequest req, ServletResponse resp) { BigInteger I = extractFromRequest(req); BigInteger[] factors = factor(i); count ++; encodeIntoResponse(resp,factors); } }
  • C public class MyClass { private int value; public synchronized int get() { return value; } public synchronized void set (int value) { this.value = value; } }
  • D public class Factorizer implements Servlet { private volatile MyCache cache = new MyCache(null,null); public void service(ServletRequest req, ServletResponse resp) { BigInteger i = extractFromRequest(req); BigInteger[] factors = cache.getFactors(i); if (factors == null) { factors = factor(i); cache = new MyCache(i,factors); } encodeIntoResponse(resp,factors); }

解析

显示答案/隐藏答案正确答案: ACD

这种题排版真变态:
A

1
2
3
4
5
public class MyServlet implements Servlet {
public void service (ServletRequest req, ServletResponse resp) {
BigInteger I = extractFromRequest(req); encodeIntoResponse(resp,factors);
}
}

B

1
2
3
4
5
6
7
8
9
10
public class MyServlet implements Servlet {
private long count =0;
public long getCount() { return count; }
public void service (ServletRequest req, ServletResponse resp) {
BigInteger I = extractFromRequest(req);
BigInteger[] factors = factor(i);
count ++;
encodeIntoResponse(resp,factors);
}
}

C

1
2
3
4
5
public class MyClass { 
private int value;
public synchronized int get() { return value; }
public synchronized void set (int value) { this.value = value; }
}

D

1
2
3
4
5
6
7
8
9
10
11
12
13
public class Factorizer implements Servlet {
private volatile MyCache cache = new MyCache(null, null);

public void service(ServletRequest req, ServletResponse resp) {
BigInteger i = extractFromRequest(req);
BigInteger[] factors = cache.getFactors(i);
if (factors == null) {
factors = factor(i);
cache = new MyCache(i, factors);
}
encodeIntoResponse(resp, factors);
}
}

自定义Servlet时尽量不要定义成员变量,多线程环境下定义的成员变量会成为线程共享变量,导致数据不一致问题。
A 无状态的,天然线程安全
B 存在静态条件变量count
C 涉及写的set方法使用了synchronize关键字,线程安全
D 使用了volatile关键字和null的判断,可能不存在重排序的问题,不懂这个 欢迎指正,说的可能不对。

怎样做到线程安全

一个对象是否安全取决于它是否被多个线程访问(访问时访问对象的方式)。
要使对象线程安全,那么需要采用同步的机制来协同对对象可变状态的访问。(java这边采用synchronized,其他还有volatile类型的变量,显式锁以及原子变量)

当某个多线程访问同一个可变状态时候没有同步,则会出现错误,解决办法:

1、不在线程之间共享该变量
2、将该变量修改为不可变变量
3、访问状态时候使用同步

安全性的解释:

当多线程访问某个类时,这个类始终能表现出正确的行为(不管运行时采用何种调度方式或者这些线程将如何交替执行,并且在主调代码中不需要任何额外的同步或协同),那么这个类安全的。

  • 无状态对象一定是线程安全的。
  • 在实际情况下,尽可能使用户现有的线程安全对象,比如用Vector而不是ArrayList。

原子性 可见性 有序性

要想并发程序正确地执行,必须要保证“原子性”、“可见性”以及“有序性”。只要有一个没有被保证,就有可能会导致程序运行不正确。

考点10:CMS垃圾回收器

CMS垃圾回收器在那些阶段是没用用户线程参与的

  • A 初始标记
  • B 并发标记
  • C 重新标记
  • D 并发清理

解析

显示答案/隐藏答案正确答案: AC

考点1:switch-case穿透 没有break的switch-case语句

1
2
3
4
5
6
7
8
9
10
11
12
13
int i = 3;
String result = new String();
switch (i) {
case 1:
result = result + "him ";
case 2:
result = result + "her ";
case 3:
result = result + "it ";
default:
result = result + "me ";
}
System.out.println(result);

请给出最终输出内容。

  • A it me
  • B him her it me
  • C him her
  • D me

解析

显示答案/隐藏答案正确答案: A

没有break,会产生穿透,从满足条件的case开始执行到底

考点2:java常用包

下面有关JDK中的包和他们的基本功能,描述错误的是?

  • A java.awt: 包含构成抽象窗口工具集的多个类,用来构建和管理应用程序的图形用户界面
  • B java.io:  包含提供多种输出输入功能的类
  • C java.lang: 包含执行与网络有关的类,如URL,SCOKET,SEVERSOCKET
  • D java.util:  包含一些实用性的类

解析

显示答案/隐藏答案正确答案: C
  1. java.awt:提供了绘图和图像类,主要用于编写GUI程序,包括按钮、标签等常用组件以及相应的事件类。
  2. java.lang:java的语言包,是核心包,默认导入到用户程序,包中有object类,数据类型包装类,数学类,字符串类,系统和运行时类,操作类,线程类,错误和异常处理类,过程类。
  3. java.io:包含提供多种输出输入功能的类。
  4. java.net: 包含执行与网络有关的类,如URL,SCOKET,SEVERSOCKET等。
  5. java.applet:包含java小应用程序的类。
  6. java.util:包含集合框架、遗留的 collection 类、事件模型、日期和时间设施、国际化和各种实用工具类(字符串标记生成器、随机数生成器和位数组、日期Date类、堆栈Stack类、向量Vector类等)。集合类、时间处理模式、日期时间工具等各类常用工具包。
  7. java.sql:提供使用 JavaTM 编程语言访问并处理存储在数据源(通常是一个关系数据库)中的数据的 API。

java.lang——包含一些Java语言的核心类,如String、Math、Integer、System和Thread,提供常用功能。
java.net——包含执行与网络相关的操作的类和接口。
java.io——包含提供多种输入/输出功能的类。
java.util——包含一些实用性工具类,如定义系统特性、接口的集合框架类、使用与日期日历相关的函数。
java.text——包含了一些java格式化相关的类
java.sql——包含了java进行JDBC数据库编程的相关类/接口
java.awt——包含了构成抽象窗口工具集(abstract window toolkits)的多个类,这些类被用来构建和管理应用程序的图形用户界面(GUI)。

考点3:运算符

Java中只有整型才能使用的运算符为?

  • A *
  • B /
  • C %
  • D +

解析

显示答案/隐藏答案正确答案: C

答案:C
ABD选项的操作符都可用于float和double
只有%取余操作,只适用于整型

运算对象为整型的运算符:%取余~取反,&按位与, |按位或,^按位异或.

C不对,%可以应用于doube,并非整型才能用。感觉这道题没有正确答案

这题有问题吧,java中浮点数也可以用%,只不过由于精度问题,结果常会不准确。

取余如何实现

java取余就是用被除数一直减去除数,直到差小于除数为止,这也正是余数的定义
例如:

1
2
3
4
5
6
7
8
9
10
double a = 10%3.0;
System.out.println(a); //输出:1.0
double b = 8.3%3.2;
System.out.println(b); //输出:1.9000000000000004
double c = 10 - 3.0;
System.out.println(c); //输出:7.0
double d = 8.3 - 3.2;
System.out.println(d); //输出:5.1000000000000005
d -= 3.2;
System.out.println(d); //输出:1.9000000000000004

可以看出,在求余时的减法过程中,就已经丢失精度了,所以最后的结果当然不准确。

考点4:循环

以下代码的循环次数是

1
2
3
4
5
6
7
8
9
10
public class Test {
public static void main(String args[]) {
int i = 7;
do {
System.out.println(--i);
--i;
} while (i != 0);
System.out.println(i);
}
}
  • A 0
  • B 1
  • C 7
  • D 无限次

解析

显示答案/隐藏答案正确答案: D

执行1次,5
执行2次,3
执行3次,1
执行4次,-1
永远执行不到0

每一次循环都会减二,7每次减2都是成奇数。永远执行不到0。

考点5:异常处理

在异常处理中,以下描述不正确的有

  • A try块不可以省略
  • B 可以使用多重catch
  • C finally块可以省略
  • D catch块和finally块可以同时省略

解析

显示答案/隐藏答案正确答案: D

选D 假如try中有异常抛出,则会去执行catch块,再去执行finally块;假如没有catch 块,可以直接执行finally
块。catch和finally不能同时都省略。

G:\dev2\idea_workspace\MyJavaTools\RunableTools\src\base\TestCatchFinally.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
package base;

public class TestCatchFinally {
// 自定义异常
static class MyException extends Exception {

}

public static void main(String args[]) {
try {
testThrowInCatch();
} catch (MyException e) {
}
testExitInCatch();
System.out.println("main end...");
}

/**
* 在catch语句中抛出异常的情况
* @throws MyException 自定义异常
*/
private static void testThrowInCatch() throws MyException {
try {
// 除零异常
int a = 10 / 0;
} catch (Exception e) {
System.out.println("catch-1...");
throw new MyException();
} finally {
System.out.println("finally-1...");
}
}

/**
* 在catch块中直接终止当前运行的Java虚拟机的情况
*/
private static void testExitInCatch() {
try {
int a = 10 / 0;
} catch (Exception e) {
System.out.println("catch-2...");
System.exit(0);
} finally {
System.out.println("finally-2...");
}
}
}

运行结果:

1
2
3
catch-1...
finally-1...
catch-2...

可以看到

  • finally块一定会执行,
  • 只有在catch块中调用System.exit()结束了虚拟机,finally才不会执行。

考点6:接口修饰符

能用来修饰interface的有()

  • A private
  • B public
  • C protected
  • D static

解析

显示答案/隐藏答案正确答案: B

定义非内部java接口可以使用public和package修饰,这一点可以在Eclipse创建接口时查看:

image-20210903005053027

package权限的接口

所以的package权限,就是什么都不写:

1
2
3
4
5
package interfacetest;

interface A {

}

public修饰的接口

1
2
3
4
5
package interfacetest;

public interface B {

}

内部接口没有限制

内部接口与类的成员变量一样,如下的代码是没有错误的:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
package interfacetest;

public class C {
// 私有内部接口
private interface C1 {
}

// 子类权限内部接口
protected interface C2 {
}

// 包权限内部接口
interface C3 {
}

// 公共权限内部接口
public interface C4 {
}

private static interface C5 {
}

// 实现内部接口
public class C1Impl implements C1 {
}
}

考点7:调动线程的start方法才会启动线程

以下程序运行的结果为 ( )

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public class Example extends Thread{
@Override
public void run(){
try {
Thread.sleep(1000);
} catch (InterruptedException e){
e.printStackTrace();
}
System. out .print( "run" );
}
public static void main(String[] args){
Example example= new Example();
example.run();
System. out .print( "main" );
}
}
  • A run main
  • B main run
  • C main
  • D run
  • E 不能确定

解析

显示答案/隐藏答案正确答案: A

调用example.run(),并没有创建新线程,只有main线程由上而下执行,Thread.sleep(1000)只是让main线程休眠了1000ms;最终打印出了run main

调用example.start(),创建了一个新线程,运行到Thread.sleep(1000),该线程休眠了1000ms;main线程先打印main,新创建的线程结束休眠后,打印run,最终打印出了main run

考点8:多态 向上转型 类的加载顺序 运行时表现子类特性

下面代码的输出是什么?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
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 null
  • B sub
  • C base

解析

显示答案/隐藏答案正确答案: A

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

本题与内部类无关系,去掉内部类后代码如上,

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public class Base {
private String baseName = "base";
public Base() {
callName();
}
public void callName() {
System.out.println(baseName);
}
public static void main(String[] args) {
Base b = new Sub();
}
}
class Sub extends Base {
private String baseName = "sub";
public void callName() {
System.out.println(baseName);
}
}

编译时表现为父类特性,运行时表现为子类特性

执行Base b = new Sub();时由于多态 b编译时表现为Base类特性,运行时表现为Sub类特性,
Base b = new Sub();不管是哪种状态都会调用Base构造器执行callName()方法;
执行方法时,由于多台表现为子类特性,所以会先在子类是否有callName();如果有就执行,没有再去父类寻找

现在,子类有这个方法,所以执行子类重写的方法。而此时子类尚未初始化(执行完父类构造器后才会开始执行子类构造器),

优先执行子类重写的方法

向上转型加载顺序

本题考查知识点是多态(上转型)以及类的先后加载顺序
上转型 类似 Father father = new Son();
1:父类中的静态代码块
2:子类中的静态代码块
3:父类中构造方法
4:子类当中的构造方法

下面来简单分析一下加载顺序
当执行到Base b =newSub()时,本题的加载顺序是:
加载父类Base类中的构造方法Base()进而调用callName()(因为子类把父类的这个方法给覆盖了,所以此方法执行的是子类中的)
因为子类中的baseName变量还没进行初始化,故为null

解题要点:

1、静态内部类是不依赖于外部类的,静态内部类中只能访问外部类的静态成员(变量和方法),此处的内部类没有意义,静态非静态,只是在构造内部类对象时写法不同,但程序执行没有差异;

2、继承关系类的加载顺序(不考虑静态属性和静态代码的情况下):初始化父类的非静态成员属性或非静态代码块–>执行父类的构造函数–>初始化子类的非静态成员属性或非静态代码块–>执行子类的构造函数;本题中首先执行父类的 private String baseName = “base”;,然后执行父类的构造函数;执行过程中调用callName()方法;

3、多态:父类引用指向子类对象,父类引用b指向了子类对象new
Sub();多态中,实际执行时如果子类重写了父类的方法,则执行子类的方法;

4、根据多态的原则,再执行父类的构造方法中调用callName方法,实际调用的是子类的callName方法,子类的callName方法输出的是属性baseName的值,可是这时子类的baseName属性还没有被初始化,因为此时仍处在父类构造函数执行过程中。

多态 编译看左 运行看右

Base b = new Sub(),因为是多态,遵循着编译看左运行看右,所以首先调用Base的构造方法,

1
public Base () {callName();}

调试一下就可以很清楚的看到执行步骤,当执行父类的callName方法时,直接跳到子类的输出 System.out.println(baseName),此时子类还没有初始化,所以是null

考点9:线程安全的集合

线程安全的map在JDK 1.5及其更高版本环境 有哪几种方法可以实现?

  • A Map map = new HashMap()
  • B Map map = new TreeMap()
  • C Map map = new ConcurrentHashMap();
  • D Map map = Collections.synchronizedMap(new HashMap());

解析

显示答案/隐藏答案正确答案: CD

答案 : C D

  1. HashMap,TreeMap 未进行同步考虑,是线程不安全的。
  2. HashTable 和 ConcurrentHashMap 都是线程安全的。区别在于他们对加锁的范围不同,HashTable
    对整张Hash表进行加锁,而ConcurrentHashMap将Hash表分为16桶(segment),每次只对需要的桶进行加锁。
  3. Collections 类提供了synchronizedXxx()方法,可以将指定的集合包装成线程同步的集合。比如,
    List list = Collections.synchronizedList(new ArrayList());
    Set set = Collections.synchronizedSet(new HashSet());

Hashtable线程安全效率低

HashMap不是线程安全的; Hashtable线程安全,但效率低,因为是Hashtable是使用synchronized的,所有线程竞争同一把锁;

ConcurrentHashMap线程安全效率高

ConcurrentHashMap不仅线程安全而且效率高,因为它包含一个segment数组,将数据分段存储,给每一段数据配一把锁,也就是所谓的锁分段技术

为什么HashMap不是线程安全的?

1、如果多个线程同时使用put方法添加元素,而且假设正好存在两个put的key发生了碰撞(根据hash值计算的bucket一样),那么根据HashMap的实现,这两个key会添加到数组的同一个位置,这样最终就会发生其中一个线程的put的数据被覆盖。
2、如果多个线程同时检测到元素个数超过 数组大小*loadFactor,这样就会发生多个线程同时对Node数组进行扩容,都在重新计算元素位置以及复制数据,但是最终只有一个线程扩容后的数组会赋给table,也就是说其他线程的都会丢失,并且各自线程put的数据也丢失。

hashMap实现线程安全:

1
2
3
4
5
6
//1、
Hashtable<String, String> hashtable =new Hashtable<>();
//2、
Map<String, String> synchronizedHashMap = Collections.synchronizedMap(new HashMap<String, String>());
//3、
ConcurrentHashMap<String, String> concurrentHashMap = new ConcurrentHashMap<>();

考点10:CMS垃圾回收器

CMS垃圾回收器在那些阶段是没用用户线程参与的

  • A 初始标记
  • B 并发标记
  • C 重新标记
  • D 并发清理

解析

显示答案/隐藏答案正确答案: AC

CMS

CMS全称Concurrent Mark Sweep,是一款并发的、使用标记-清除算法的垃圾回收器,以牺牲吞吐量为代价来获得最短回收停顿时间的垃圾回收器,对于要求服务器响应速度的应用上,这种垃圾回收器非常适合。

CMS的基础算法是:标记—清除
它的过程可以分为以下6个步骤:

  1. 初始标记(STW initial mark)
  2. 并发标记(Concurrent marking)
  3. 并发预清理(Concurrent precleaning)
  4. 重新标记(STW remark)
  5. 并发清理(Concurrent sweeping)
  6. 并发重置(Concurrent reset)
  1. 初始标记:在这个阶段,需要虚拟机停顿正在执行的任务,官方的叫法STW(Stop The Word)。这个过程从垃圾回收的”根对象”开始,只扫描到能够和”根对象”直接关联的对象,并作标记。所以这个过程虽然暂停了整个JVM,但是很快就完成了
  2. 并发标记:这个阶段紧随初始标记阶段,在初始标记的基础上继续向下追溯标记。并发标记阶段,应用程序的线程和并发标记的线程并发执行,所以用户不会感受到停顿
  3. 并发预清理:并发预清理阶段仍然是并发的。在这个阶段,虚拟机查找在执行并发标记阶段新进入老年代的对象(可能会有一些对象从新生代晋升到老年代, 或者有一些对象被分配到老年代)。通过重新扫描,减少下一个阶段”重新标记”的工作,因为下一个阶段会Stop The World。
  4. 重新标记:这个阶段会暂停虚拟机,收集器线程扫描在CMS堆中剩余的对象。扫描从”根对象”开始向下追溯,并处理对象关联。
  5. 并发清理:清理垃圾对象,这个阶段收集器线程和应用程序线程并发执行
  6. 并发重置:这个阶段,重置CMS收集器的数据结构,等待下一次垃圾回收。

CMS不会整理、压缩堆空间,这样就带来一个问题:经过CMS收集的堆会产生空间碎片,CMS不对堆空间整理压缩节约了垃圾回收的停顿时间,但也带来的堆空间的浪费。 为了解决堆空间浪费问题,CMS回收器不再采用简单的指针指向一块可用堆空 间来为下次对象分配使用。;而是把一些未分配的空间汇总成一个列表,当JVM分配对象空间的时候,会搜索这个列表找到足够大的空间来hold住这个对象。
从上面的图可以看到,为了让应用程序不停顿,CMS线程和应用程序线程并发执行,这样就需要有更多的CPU,单纯靠线程切 换是不靠谱的。并且,重新标记阶段,为空保证STW快速完成,也要用到更多的甚至所有的CPU资源。

B.并发标记 和 D.并发清理 这两个阶段是有用户线程参与的,所以答案选A和C。

考点1:try-catch-finally执行流程

分析以下代码,说法正确的是()

1
2
3
4
5
6
7
8
9
10
11
12
13
14
public static void main(String[] args) {
System.out.println(val());
}
public static int val() {
int num = 5;
try {
num = num / 0;
} catch (Exception e) {
num = 10;
} finally {
num = 15;
}
return num;
}
  • A 运行时报错
  • B 程序正常运行,输出值为5
  • C 程序正常运行,输出值为10
  • D 程序正常运行,输出值为15

解析

显示答案/隐藏答案正确答案: D

第7行出现除零异常,然后执行catch块,最后执行finally块。

考点2:数据类型

若所用变量都已正确定义,以下选项中,非法的表达式是()

  • A a!= 4||b==1
  • B 'a' % 3
  • C 'a' = 1/3
  • D 'A' + 32

解析

显示答案/隐藏答案正确答案: C

‘a’是个常数,不能赋值

考点3:自动类型提升

若有定义语句: int a=10 ; double b=3.14 ; 则表达式 ‘A’+a+b 值的类型是()

  • A char
  • B int
  • C double
  • D float

解析

显示答案/隐藏答案正确答案: C

类型自动提升

char < short < int < float < double不同类型运算结果类型向右边靠齐。
类型大的与类型小的进行运算,强制转换为大类型
自动转换,精度小的自动转换为精度大的 因此统一转换为double类型。如果是要精度大的转化为精度小的 则需要进行强制类型转换

考点4:检查异常和非检查异常

下列哪种异常是检查型异常,需要在编写程序时声明?

  • A NullPointerException
  • B ClassCastException
  • C FileNotFoundException
  • D IndexOutOfBoundsException

解析

显示答案/隐藏答案正确答案: C

java中的异常通常分为编译时异常和运行异常。编译时异常需要我们手动的进行捕捉处理,也就是我们用try….catch块进行捕捉处理。
对于运行时异常只有在编译器在编译运行时才会出现,这些不需要我们手动进行处理。对于A、
B、 D来说都是运行时异常,因此答案为C

Java异常族谱

214250_1444467985224_6A144C1382BBEF1BE30E9B91BC2973C8

  1. 粉红色的是受检查的异常(checked exceptions),其必须被try{}catch语句块所捕获,或者在方法签名里通过throws子句声明.受检查的异常必须在编译时被捕捉处理,命名为 Checked Exception 是因为Java编译器要进行检查,Java虚拟机也要进行检查,以确保这个规则得到遵守.
  2. 绿色的异常是运行时异常(runtime exceptions),需要程序员自己分析代码决定是否捕获和处理,比如空指针,被0除…
  3. 而声明为Error的,则属于严重错误,如系统崩溃、虚拟机错误、动态链接失败等,这些错误无法恢复或者不可能捕捉,将导致应用程序中断,Error不需要捕捉。

Java异常

  • 检查型异常(编译时异常 checked exceptions)
  • 需要在编写程序时声明
  • 需要我们手动的进行捕捉处理,也就是我们用try….catch块进行捕捉处理。或者在方法签名里通过throws子句声明
  • Throwable、Exception、IOException、ClassNotFoundException、CloneNotSupportedException、EOFException、FileNotFoundException、MalformedURLException、UnknownHostException
  • 运行异常(runtime exceptions)
  • 只有在编译器在编译运行时才会出现,这些不需要我们手动进行处理
  • 需要程序员自己分析代码决定是否捕获和处理,比如 空指针,被0除…
  • RuntimeException、ArithmeticException、ClassCastException、IllegalArgumentException、IllegalStateException、IndexOutOfBoundsException、NoSuchElementException、NullPointerException
  • Error
  • 属于严重错误,如系统崩溃、虚拟机错误、动态链接失败等,这些错误无法恢复或者不可能捕捉,将导致应用程序中断,Error不需要捕捉。

1、Java 基本上除了 File、SQL 相关的异常外,都是运行时异常

考点5:Object方法

以下 _____ 不是 Object 类的方法

  • A clone()
  • B finalize()
  • C toString()
  • D hasNext()

解析

显示答案/隐藏答案正确答案: D

这种类型的题一般考察点有两个:
1.Object中没有hasNext() 方式,这个方法是迭代器中的
2.Object没有copy方法,但是有clone()方法, 用于创建并返回该对象的一个副本

hasNext一般为迭代器方法

hasNext() 一般是迭代器(Iterater)的方法,表示是否存在下一个元素,用next()方法取到下一个元素。

Object方法

https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/lang/Object.html

java.lang.Object方法 描述
protected Object clone() Creates and returns a copy of this object.
boolean equals(Object obj) Indicates whether some other object is “equal to” this one.
protected void finalize() Deprecated. The finalization mechanism is inherently problematic.
Class<?> getClass() Returns the runtime class of this Object.
int hashCode() Returns a hash code value for the object.
void notify() Wakes up a single thread that is waiting on this object’s monitor.
void notifyAll() Wakes up all threads that are waiting on this object’s monitor.
String toString() Returns a string representation of the object.
void wait() Causes the current thread to wait until it is awakened, typically by being notified or interrupted.
void wait(long timeoutMillis) Causes the current thread to wait until it is awakened, typically by being notified or interrupted, or until a certain amount of real time has elapsed.
void wait(long timeoutMillis, int nanos) Causes the current thread to wait until it is awakened, typically by being notified or interrupted, or until a certain amount of real time has elapsed.

考点6:值传递引用传递问题

指出下来程序运行的结果是

4819419_1512815363858_050A1C016A89DF3247F32E71DC8461D3

  • A good and abc
  • B good and gbc
  • C tst ok and abc
  • D tst ok and gbc

解析

显示答案/隐藏答案正确答案: B

值传递和引用传递

  • 基本数据类型都是值传递
  • 类,数组,接口是引用传递。 由于String对象本身的特殊性,导致它值传递的特征

考点7:abstract和final

关于抽象类与最终类,下列说法错误的是?

  • A 抽象类能被继承,最终类只能被实例化。
  • B 抽象类和最终类都可以被声明使用
  • C 抽象类中可以没有抽象方法,最终类中可以没有最终方法
  • D 抽象类和最终类被继承时,方法可以被子类覆盖

解析

显示答案/隐藏答案正确答案: D

最终类就是被final修饰的类,最终方法就是被final修饰的方法。最终类不能被继承,最终方法不能被重写。

1,抽象类中可以有抽象方法,也可以没有抽象方法。
2,抽象类当然可以被继承,因为它就是用来继承的,
3,继承抽象类,若有抽象方法,则子类必须将其抽象方法实现,
4,抽象类中的非抽象方法可以被重写。

最终类和抽象类正好相反
5,加上final的类就叫最终类,加上final的方法就叫最终方法,
6,最终类中可以有最终方法也可以没有
7,最终类不能有子类,最终方法不能被重写

抽象类和最终类的区别

1.抽象类可以被继承,并且触创建抽象类就是为了被继承,但是最终类只能实例化;
2.抽象类和最终类都可以被声明使用。
3.抽象类可以没有抽象方法,最终类中可以没有最终方法。
4.最终类不能被继承,子类继承非最终类时,子类可以继承该类的最终方法,但不能重写父类的最终方法。
5.抽象类是不能实例化的,实例化必将加载类,然后根本不知道抽象方法的方法体大小,所以不能实例化。

然后是抽象类和接口的区别

类中只要含有一个抽象方法,该类就是抽象类;抽象类中可以包含一个或多个抽象方法,也可以不含有抽象方法,直接在类声明时候加上abstract
,该类就是抽象类,但是这种情况没有意义。

Java7之前接口中的方法只有声明,没有实现,类似抽象方法,

接口方法默认public abstract修饰;
接口中的变量默认是public static final修饰的;

接口定义时候,如果不声明为public的接口,那么该接口只有包访问权限。

一个子类只能继承一个抽象类(虚类),但能实现多个接口;
一个抽象类可以有构造方法,接口没有构造方法;
一个抽象类中的方法不一定是抽象方法,即其中的方法可以有实现(有方法体),
接口中的方法都是抽象方法,不能有方法体,只有声明;

一个抽象类可以是public、private、protected、default,
接口只有public;

一个抽象类中的方法可以是public、private、protected、default
接口中的方法只能是public和default。

考点8:异常处理

对于Java中异常的描述正确的是( )

  • A 用throws定义了方法可能抛出的异常,那么调用此方法时一定会抛出此异常。
  • B 如果try块中没有抛出异常,finally块中的语句将不会被执行。
  • C 抛出异常意味着程序发生运行时错误,需要调试修改
  • D Java中的可不检测(unchecked)异常可能来自RuntimeException类或其子类。

解析

显示答案/隐藏答案正确答案: D

A错 在调用此方法的时候 也可以再次申明以将异常交由更高一级处理。
B错 finally块中的语句一定会被执行。除非catch块中有System.exit(0)
C错 抛出异常不一定是运行时异常,也有可能是编译时异常。
D对 运行时异常的特点是Java编译器不会检查它。

Exception(异常)

是程序本身可以处理的异常。主要包含RuntimeException等运行时异常和IOException,SQLException等非运行时异常。

运行时异常

包括:都是RuntimeException类及其子类异常,如NullPointerException(空指针异常)、IndexOutOfBoundsException(下标越界异常)等,这些异常是不检查异常,程序中可以选择捕获处理,也可以不处理。这些异常一般是由程序逻辑错误引起的,程序应该从逻辑角度尽可能避免这类异常的发生。

编译器不会检查运行时异常

运行时异常的特点是Java编译器不会检查它,也就是说,当程序中可能出现这类异常,即使没有用try-catch语句捕获它,也没有用throws子句声明抛出它,也会编译通过。

非运行时异常(编译异常)

包括:RuntimeException以外的异常,类型上都属于Exception类及其子类。从程序语法角度讲是必须进行处理的异常,如果不处理,程序就不能编译通过。如IOException、SQLException等以及用户自定义的Exception异常,一般情况下不自定义检查异常

考点9:线程安全的集合

下面哪些具体实现类可以用于存储键,值对,并且方法调用提供了基本的多线程安全支持:()

  • A java.util.ConcurrentHashMap
  • B java.util.Map
  • C java.util.TreeMap
  • D java.util.SortMap
  • E java.util.Hashtable
  • F java.util.HashMap

解析

显示答案/隐藏答案正确答案: AE

Hashtable线程安全

Hashtable的方法都是synchrnized修饰的,所以线程安全.

java.util.Hashtable.java
1
2
3
4
5
6
7
8
......
public synchronized int size() {...}
public synchronized boolean contains(Object value) {...}
public synchronized boolean containsKey(Object key) {...}
public synchronized V get(Object key) {...}
public synchronized V put(K key, V value) {...}
public synchronized V remove(Object key) {...}
......

ConcurrentXxx线程安全

ConcurrentHashMap并发容器,JDK7采用分段锁,JDK8采用CAS算法,线程安全,建议使用,

https://blog.csdn.net/xuefeng0707/article/details/40834595
https://www.jianshu.com/p/863542dcbd5b

Connections.synchrnizedMap(map)非线程安全的Map包装成线程安全的Map

Connections工具类提供了一个方法synchrnizedMap可以把Map同步,本质就是给每一个方法加上synchrnized关键字进行同步

考点10:Servlet族谱

下面有关servlet的层级结构和常用的类,说法正确的有?

  • A GenericServlet类:抽象类,定义一个通用的、独立于底层协议的Servlet
  • B 大多数Servlet通过从GenericServletHttpServlet类进行扩展来实现
  • C ServletConfig接口定义了在Servlet初始化的过程中由Servlet容器传递给Servlet得配置信息对象
  • D HttpServletRequest接口扩展ServletRequest接口,为HTTP Servlet提供HTTP请求信息

解析

显示答案/隐藏答案正确答案: ABCD

1562929_1495091266467_AA89EDF1B0D43CAA9A893C73A1615398

GenericServlet抽象类

GenericServlet是个抽象类,必须给出子类才能实例化。它给出了设计servlet的一些骨架,定义了servlet生命周期,还有一些得到名字、配置、初始化参数的方法,其设计的是和应用层协议无关的,也就是说 你有可能用非http协议实现它。

HttpServlet

HttpServlet是GenericServlet的子类,当然就具有GenericServlet的一切特性,还添加了doGet, doPost, doDelete,doPut, doTrace等方法对应处理http协议里的命令的请求响应过程。

一般没有特殊需要,自己写的Servlet都扩展HttpServlet 。

考点2:

以下语句的执行结果是什么?

1
1+"10"+3+"2"
  • A “11032”
  • B “16”
  • C 16
  • D “32101”

解析

显示答案/隐藏答案正确答案: A
1
2
3
System.out.println(1+"10"+3+"2");//11032
System.out.println(1+2+"10"+3+"2");//31032
System.out.println(1+"10"+3+1+"2");//110312

注意“+”的两边的类型

相当于按顺序从左向右+,以2个为一个单元,例如
System.out.println(3+5+”12”+3+3);
前两个是3+5,值为8,这时变为
System.out.println(8+”12”+3+3);
前两个是8+”12”,值为”812”,然后”812”+3=”8123”,故最后值为”81233”。

考点3:

以下程序的运行结果是:( )

1
2
3
4
5
6
7
8
9
10
TreeSet<Integer> set = new TreeSet<Integer>();
TreeSet<Integer> subSet = new TreeSet<Integer>();
for(int i=606;i<613;i++){
if(i%2==0){
set.add(i);
}
}
subSet = (TreeSet)set.subSet(608,true,611,true);
set.add(629);
System.out.println(set+" "+subSet);
  • A 编译失败
  • B 发生运行时异常
  • C [606, 608, 610, 612, 629] [608, 610]
  • D [606, 608, 610, 612, 629] [608, 610,629]

解析

显示答案/隐藏答案正确答案: C

Set的subset方法

subset方法是求set的范围内的子集,两个true是表示是否包含端点(608和611),故subSet的值为[608,610]

subset(form,true,to,true)是Treeset的非静态方法,该方法返回从form元素到to元素的一个set集合,两个boolean类型是确认是否包含边境值用的。
https://blog.csdn.net/yingpaixiaochuan/article/details/49019131

1
2
3
4
5
6
7
8
9
10
11
/**
* set=[606, 608, 610, 612, 629]
*/
s1 = (TreeSet)set.subSet(608, true,611,true); //表示从set数组中取出从from到to的值
s2 = (TreeSet)set.subSet(608, false,611,true);//表示从set数组取出from到to(不包含from)的值
s3 = (TreeSet)set.subSet(608, true,611,false);//表示从set数组取出从from到to(不包含to)的值
/** 输出:
* s1=[608, 610, 612]
* s2=[610, 612]
* s3=[608, 610]
*/

总结:subset()就是截取from到to的值。其中截取的值是否包含边境由fromInclusive、toInclusive的boolean值的变化决定。

考点4:

下面有关java的一些细节问题,描述错误的是?

  • A 构造方法不需要同步化
  • B 一个子类不可以覆盖掉父类的同步方法
  • C 定义在接口中的方法默认是public
  • D 容器保存的是对象的引用

解析

显示答案/隐藏答案正确答案: B

A构造方法都是构造出新的对象,所以不需要同步

B synchronized关键字不能被继承。虽然可以用synchronized来定义方法,但是synchronized却并不属于方法定义的一部分,所以synchronized关键字并不能被继承。如果父类中的某个方法使用了synchronized关键字,而子类中也覆盖了这个方法,默认情况下子类中的这个方法并不是同步的,必须显示的在子类的这个方法中加上synchronized关键字才可

C接口里面的变量其实际是常量,常用public static final修饰 ;接口里面的方法其实际是抽象方法,常用public abstrac修饰

D容器保存的是对象的引用 而非对象本身

考点5:

以下哪个式子有可能在某个进制下成立()?

  • A 13*14=204
  • B 12*34=568
  • C 14*14=140
  • D 1+1=3

解析

显示答案/隐藏答案正确答案: A

按权展开,然后相乘

我们假设是x进制,然后带入算式计算即可: A选项:13*14=204

1
2
3
4
(1*x^1+3*x^0) *( 1*x^1+4*x^0)= 2*x^2+4*x^0 
==>(x+3)*(x+4)=2x^2+4
==>(x-8)(x+1)=0
==>x=8或x=-1

A选项有答案,为八进制时,可成功匹配,所以A答案正确。
B选项:12*34=568;

1
2
3
(1*x^1+2*x^0)*(3*x^1+4*x^0)=5*x^2+6*x^1+8*x^0 
==>(x+2)(3x+4)=5x^2+6x+8
==>x=2

B选项也有答案,为二进制,但是却是错误的,因为就像在16进制中一样,不能出现比15(也就是F)更大的数,到了16就会进位了。所以在二进制中,不能出现比1更大的数,到了2就会进位了。而B选项的等式中,出现了3,4,5,6,8都比1更大,所以肯定不是二进制数,所以也是错误的。

C,D选项也是类似规则

考点6:

Java语言中,方法的重写(Overriding)和重载(Overloading)是多态性的不同表现。下边哪些说法是对的?

  • A 重写是父类与子类之间多态性的一种表现
  • B 重写是一个类中多态性的一种表现
  • C 重载是一个类中多态性的一种表现
  • D 重载是父类与子类之间多态性的一种表现

解析

显示答案/隐藏答案正确答案: AC

重写Overriding是父类与子类之间多态性的一种表现,重载Overloading是一个类中多态性的一种表现。如果在子类中定义某方法与其父类有相同的名称和参数,我们说该方法被重写
(Overriding)。子类的对象使用这个方法时,将调用子类中的定义,对它而言,父类中的定义如同被“屏蔽”了。

如果在一个类中定义了多个同名的方法,它们或有不同的参数个数有不同的参数类型,则称为方法的重载(Overloading)。

Overloaded的方法是可以改变返回值的类型。

重写是子类继承父类方法并对其进行修改,可选择调用父类方法或子类重写后的同名方法
重载是在一个类可以存在同名但参数列表不同的方法,可根据传入的参数调用相应的方法

考点7:

以下 json 格式数据,错误的是

  • A {company:4399}
  • B {"company":{"name":[4399,4399,4399]}}
  • C {[4399,4399,4399]}
  • D {"company":[4399,4399,4399]}
  • E {"company":{"name":4399}}

解析

显示答案/隐藏答案正确答案: AC
  1. 必须有键 和 值
  2. 键和值必须用双引号
  3. 值中可以嵌套 JSON 元素

考点8:

关于OutOfMemoryError,下面说法正确的是()?

  • A java.lang.OutOfMemoryError: PermGen space 增加-XX:MaxPermSize这个参数的值的话,这个问题通常会得到解决。
  • B java.lang.OutOfMemoryError: Requested array size exceeds VM limit当你正准备创建一个超过虚拟机允许的大小的数组时,这条错误将会出现
  • C java.lang.OutOfMemoryError: Java heap space 一般情况下解决这个问题最快的方法就是通过-Xmx参数来增加堆的大小
  • D java.lang.OutOfMemoryError: nativeGetNewTLA这个异常只有在jRockit虚拟机时才会碰到

解析

显示答案/隐藏答案正确答案: ABC

关于此题,《深入理解java虚拟机》有关于OOM(OutOfMemory)问题的解释 A:属于运行时常量池导致的溢出,设置-XX:MaxPermSize可以解决这个问题, B:属于堆空间不足导致的错误,问题比较少见,解决方式和C相同, C:属于java堆内存问题,一般的手段是通过内存映像分析工具,对Dump出来的堆转储存快照进行分析,重点是确认内存中的对象是否是有必要的,也就是要判断是出现了内存泄漏,还是出现了内存溢出,如果是内存列楼,通过工具检查泄露对象打GC Roots的引用链信息,可以准确的确定出泄露代码的位置,不存在泄露,就应该检查虚拟机的堆参数,如果可以继续调大,可以设置-Xmx解决问题 D:java.lang.OutOfMemoryError: nativeGetNewTLA指当虚拟机不能分配新的线程本地空间(Thread Local Area)的时候错误信息,此错误是线程申请一个新的TLA时产生的,这个异常一般只会发生在jRockit虚拟机,只有过于绝对。

考点9:

如下哪些是 java 中有效的关键字()

  • A native
  • B NULL
  • C false
  • D this

解析

显示答案/隐藏答案正确答案: AD

true false null都是常量而不是关键字

const和goto是保留关键字。
true和false看起来像关键字,但严格来说,它们是boolean常量;
null看起来也像关键字,但严格来说,它是null常量。

综上,true,false,null不是关键字。而是常量。

点击查看 java se 8 官方解释

这里有一张图片

考点1:

java 中哪个关键字可以对对象加互斥锁?

  • A transient
  • B synchronized
  • C serialize
  • D static

解析

显示答案/隐藏答案正确答案: B

transient修饰符是指字段不会被序列化。
synchronized修饰符是指对象锁. 用来给对象和方法或者代码块加锁,当它锁定一个方法或者一个代码块的时候,同一时刻最多只有一个线程执行这个段代码
serialize序列化.

volatile:用来确保将变量的跟新操作通知到其他线程,当把变量声明为volatile类型后,编译器与运行时都会注意到这个变量是共享的,因此不会将该变量上的操作与其他内存操作一起重排序。然而,在访问volatile变量时不会执行加锁操作,因此也就不会使执行线程阻塞,因此volatile变量是一种比 synchronized关键字更轻量级的同步机制。

  • static 修饰符,用来创建类方法和类变量。
  • final 修饰符,用来修饰类、方法和变量,final 修饰的类不能够被继承,修饰的方法不能被继承类重新定义,修饰的变量为常量,是不可修改的。
  • abstract 修饰符,用来创建抽象类和抽象方法。
  • synchronized 用于多线程的同步。用来给对象和方法或者代码块加锁,各线程互斥访问。
  • volatile 修饰的成员变量在每次被线程访问时,都强制从共享内存中重新读取该成员变量的值。而且,当成员变量发生变化时,会强制线程将变化值回写到共享内存。这样在任何时刻,两个不同的线程总是看到某个成员变量的同一个值。
  • transient:序列化的对象包含被 transient 修饰的实例变量时,java
  • 虚拟机(JVM)跳过该特定的变量。

A、transient,反序列化修饰符,序列化的时候,类中的属性都会被复制,但是被transient和static修饰的属性不会被复制。

考点2:

在Web应用程序的文件与目录结构中,web.xml是放置在( )中。

  • A WEB-INF目录
  • B conf目录
  • C lib目录
  • D classes目录

解析

显示答案/隐藏答案正确答案: A

Java Web应用程序目录结构

web.xml文件是用来初始化配置信息,web.xml是放置在WEB-INF目录中

Web工程的目录结构如图所示

(1)/WEB-INF/web.xml 是部署描述文件
(2)/WEB-INF/classes 用来放置应用程序用到的自定义类(.class),必须包括包(package)结构。
(3)/WEB-INF/lib 用来放置应用程序用到的JAR文件。

考点3:

java语言中的数组元素下标总是从0开始,下标可以是整数或整型表达式。()

  • A 正确
  • B 错误

解析

显示答案/隐藏答案正确答案: A

例如平时有这样的用法

1
2
3
for(int i=0;i<10;i++){
a[i+1]=a[i];
}

这个i+1就是整数型表达式 或者a[5+3]就是a[8]

考点4:

类A1和类A2在同一包中,类A2有个protected的方法testA2,类A1不是类A2的子类(或子类的子类),类A1可以访问类A2的方法testA2。( )

  • A 正确
  • B 错误

解析

显示答案/隐藏答案正确答案: A

访问控制符作用范围

作用域 当前类 同一package 子孙类 其他package
public
protected ×
default × ×
private × × ×
@ public protected default private
当前类 y y y y
同包中 y y y n
子类 y y n n
其它 y n n n

考点5:

下面对静态数据成员的描述中,正确的是

  • A 静态数据成员可以在类体内进行初始化
  • B 静态数据成员不可以被类的对象调用
  • C 静态数据成员不受private控制符的作用
  • D 静态数据成员可以直接用类名调用

解析

显示答案/隐藏答案正确答案: A

静态数据成员可以直接用类名调用,前提是访问权限修饰符为public。
本类的私有静态数据成员,无法被其他类调用。

考点6:

将下列哪个代码(A、B、C、D)放入程序中标注的【代码】处将导致编译错误?

1
2
3
4
5
6
7
8
class A{
public float getNum(){
return 3.0f;
}
}
public class B extends A{
【代码】
}
  • A public float getNum(){return 4.0f}
  • B public void getNum(){}
  • C public void getNum(double d){}
  • D public double getNum(float d){return 4.0d}

解析

显示答案/隐藏答案正确答案: B

A是重写
B是重写,但是返回值类型不对
C是重载
D是重载

方法重写 两同两小一大

方法重写要遵循“两同两小一大”规则,

  • “两同”即方法名相同、形参列表相同
  • “两小”指的是子类方法返回值类型应比父类方法返回值类型更小或相等,子类方法声明抛出的异常类应比父类方法声明抛出的异常类更小或相等;
  • “一大”指的是子类方法的访问权限应比父类方法的访问权限更大或相等。

并且,覆盖方法和被覆盖方法要么都是类方法,要么都是实例方法,不能一个是类方法一个是实例方法。

方法重载 两同一不同

方法重载的要求就是“两同一不同”:

  • 同一个类中
  • 方法名相同,
  • 形参列表不同

子类重载方法:参数列表不同

什么时候发生子类方法和父类方法的重载?
如果子类定义了一个与父类方法有相同的方法名,但参数列表不同的方法,就会形成父类方法和子类方法的重载,

如何区分重载和重写

看参数列表,
如果参数列表相同,就认定为重写。
如果参数列表不同,就认定为重载。

考点1:

一个以”. java”为后缀的源文件,哪些说法是正确的?

  • A 只能包含一个类,类名必须与文件名相同
  • B 只能包含与文件名相同的类,以及其中的内部类
  • C 只能有一个与文件名相同的类,可以包含其他类
  • D 可以包含任意类

解析

显示答案/隐藏答案正确答案: C

一个java文件可以包含多个java类,但是只能包含一个public类,并且public类的类名必须与java文件名相同。

考点2:

默认RMI采用的是什么通信协议?

  • A HTTP
  • B UDP/IP
  • C TCP/IP
  • D Multicast

解析

显示答案/隐藏答案正确答案: C

RMI(Remote Method Invocation)远程方法调用是一种计算机之间利用远程对象互相调用实现双方通讯的一种通讯机制。 而TCP/IP是远程通讯的主要手段。

考点3:

下面有关java final的基本规则,描述错误的是?

  • A final修饰的类不能被继承
  • B final修饰的成员变量只允许赋值一次,且只能在类方法赋值
  • C final修饰的局部变量即为常量,只能赋值一次。
  • D final修饰的方法不允许被子类覆盖

解析

显示答案/隐藏答案正确答案: B

考点3:

下面有关java final的基本规则,描述错误的是?

  • A final修饰的类不能被继承
  • B final修饰的成员变量只允许赋值一次,且只能在类方法赋值
  • C final修饰的局部变量即为常量,只能赋值一次。
  • D final修饰的方法不允许被子类覆盖

解析

显示答案/隐藏答案正确答案: B

答案为:B

final修饰的成员变量为基本数据类型是,在赋值之后无法改变。
当final修饰的成员变量为引用数据类型时,在赋值后其指向地址无法改变,但是对象内容还是可以改变的。
final修饰的成员变量在赋值时可以有三种方式。
1、在声明时直接赋值。
2、在构造器中赋值。
3、在初始代码块中进行赋值。

final修饰的方法,不允许被子类覆盖。
final修饰的类,不能被继承。
final修饰的变量,不能改变值。
final修饰的引用类型,不能再指向别的东西,但是可以改变其中的内容。

final所修饰的成员变量只能赋值一次,
可以在类方法中赋值,
也可以在声明的时候直接赋值,

而final修饰的局部变量可以在声明的时候初始化,也可以在第一次使用时,通过方法或者表达式给它赋值。

final修饰的成员的赋值方式

第一种:修饰成员变量时有3种初始化方式:
1,在定义变量时直接赋值
2,声明完变量后在构造方法中为其赋值
3,声明完变量后在构造代码块中为其赋值 { }

第二种:修饰类变量(静态变量)
1,在定义类变量时直接赋值

2,在静态代码块中赋值

考点4:

以下程序执行的结果是:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
class X{
Y y=new Y();
public X(){
System.out.print("X");
}
}
class Y{
public Y(){
System.out.print("Y");
}
}
public class Z extends X{
Y y=new Y();
public Z(){
System.out.print("Z");
}
public static void main(String[] args) {
new Z();
}
}
  • A ZYXX
  • B ZYXY
  • C YXYZ
  • D XYZX

解析

显示答案/隐藏答案正确答案: C

类初始化顺序

涉及继承:
a.初始化父类中的静态成员变量和静态代码块
b.初始化子类中的静态成员变量和静态代码块
c.初始化父类的普通成员变量和构造代码块(按次序),再执行父类的构造方法
d.初始化子类的普通成员变量和构造代码块(按次序),再执行子类的构造方法

考点5:

下面程序输出结果为():

1
2
3
4
5
6
7
8
public class Demo{
public static void main (String [] args) {
String lx = "LeXin";
String nb = lx;
lx = "Fenqile";
System.out.println(nb);
}
}
  • A 程序异常,编译不通过
  • B 程序编写正常,可正常运行
  • C 程序输出值为”LeXin
  • D 程序输出值为”Fenqile

解析

显示答案/隐藏答案正确答案: BC

考点6:

JDK1.7版本之前,接口和抽象类描述正确的有( )

  • A 抽象类没有构造函数。
  • B 接口没有构造函数。
  • C 抽象类不允许多继承。
  • D 接口中的方法可以有方法体。

解析

显示答案/隐藏答案正确答案: BC

A.抽象类可以有构造方法,只是不能直接创建抽象类的实例对象而已
B.在接口中 不可以有构造方法,在接口里写入构造方法时,编译器提示:Interfaces cannot have constructors。
C.Java不允许类多重继承
D.jdk1.8后接口中的方法可以有方法体,jdk1.8之前不可以有方法体

JDK1.8后,接口中可以有静态方法,静态方法必须有方法体。

考点7:

根据下面这个程序的内容,判断哪些描述是正确的:( )

1
2
3
4
5
6
7
8
9
10
11
12
13
14
public class Test {
public static void main(String args[]) {
String s = "tommy";
Object o = s;
sayHello(o); //语句1
sayHello(s); //语句2
}
public static void sayHello(String to) {
System.out.println(String.format("Hello, %s", to));
}
public static void sayHello(Object to) {
System.out.println(String.format("Welcome, %s", to));
}
}
  • A 这段程序有编译错误
  • B 语句1输出为:Hello, tommy
  • C 语句2输出为:Hello, tommy
  • D 语句1输出为:Welcome, tommy
  • E 语句2输出为:Welcome, tommy
  • F 根据选用的Java编译器不同,这段程序的输出可能不同

解析

显示答案/隐藏答案正确答案: CD

Java语言是静态多分派,动态单分派的。 如果是重载方法之间的选择,则是使用静态类型。 如果是父类与子类之间的重写方法的选择,则是使用动态类型。 如A a = new B(); 会使用类型B去查找重写的方法,使用类型A去查找重载的方法。 所以此题的输出分别为

Welcome, tommy
Hello, tommy

考点8:

错误的有:

  • A public abstract final class Test { abstract void method(); }
  • B public abstract class Test { abstract final void method(); }
  • C public abstract class Test { abstract void method() { } }
  • D public class Test { final void method() { } }

解析

显示答案/隐藏答案正确答案: ABC

A、final修饰的类为终态类,不能被继承,而抽象类是必须被继承的才有其意义的,因此,final是不能用来修饰抽象类的
B、final修饰的方法为终态方法,不能被重写。而继承抽象类,必须重写其方法。因此,final不能修饰抽象方法
C、抽象方法是仅声明,并不做实现的方法。也就是不能带有方法体:{ }

考点1:

队列(Queue)是先进先出的。( )

  • A 正确
  • B 错误

解析

显示答案/隐藏答案正确答案: A

举个栗子,可以这样理解: 1.队列:先进先出。很好理解就是排队。 2.栈:后进先出。就像堆放在桌子上的一碟碟盘子,最后放的,肯定是最先拿的。

考点2:

关于AOP错误的是?

  • A AOP将散落在系统中的”方面”代码集中实现
  • B AOP有助于提高系统可维护性
  • C AOP已经表现出将要替代面向对象的趋势
  • D AOP是一种设计模式,Spring提供了一种实现

解析

显示答案/隐藏答案正确答案: C

AOP和OOP的区别

1.面向方面编程 AOP

偏重业务处理过程的某个步骤或阶段,强调降低模块之间的耦合度,使代码拥有更好的移植性。

2.面向对象编程 (OOP)

则是对业务分析中抽取的实体进行方法和属性的封装。

也可以说AOP是面向业务中的动词领域,OOP面向名词领域。
AOP的一个很重要的特点是源代码无关性,也就是说如果我们的系统中引用了AOP组件,即使我们把该组件去掉,系统代码也应该能够编译通过。要实现这一点,可以使用动态proxy模式。

AOP与OOP是面向不同领域的两种设计思想。 OOP(面向对象编程)针对业务处理过程的实体及其属性和行为进行抽象封装,以获得更加清晰高效的逻辑单元划分。 AOP(面向切面编程)是针对业务处理过程中的切面进行提取,它所面对的是处理过程中的某个步骤或阶段,以获得逻辑过程中各部分之间低耦合性的隔离效果。 这两种设计思想在目标上有着本质的差异。

考点3:

非抽象类实现接口后,必须实现接口中的所有抽象方法,除了abstract外,方法头必须完全一致.

  • A 正确
  • B 错误

解析

显示答案/隐藏答案正确答案: B

两同两小一大

实际上这道题考查的是两同两小一大原则:

  • 方法名相同,
  • 参数类型相同
  • 子类返回类型小于等于父类方法返回类型,
  • 子类抛出异常小于等于父类方法抛出异常,
  • 子类访问权限大于等于父类方法访问权限。

方法头指:修饰符+返回类型+方法名(形参列表)

什么是方法头方法体方法签名

方法由方法头(Method Header)和方法体(Method Body)组成,

https://blog.csdn.net/tgvincent/article/details/97516256
方法头: 包括方法的修饰符、返回值类型、方法名、形式参数(最后两项是方法签名)
方法体: 在Java语言中方法体一个方法中用大括号{}括起来的部分
方法签名: 方法名称+参数列表(包括参数的类型和顺序)
注意,签名不包括方法的访问修饰符、返回类型

应用场景-重载和重写:

重载(Override): 一个类中,定义的多个方法名相同但是参数列表不同的方法(签名不同)
重写(Overlode): 子父类中,子类定义了与父类方法签名相同的方法。
注意:必须是从父类继承而来的方法。父类中的private方法,子类没有权限继承,因而重写不了。

例如:

1
2
3
4
public static void main(String []args)
{
//方法体
}

方法头:

1
public static void main(String []args)

方法体:

1
2
3
{
//方法体
}

方法签名:

1
main(String[])

考点4:

下面代码的运行结果是( )

1
2
3
4
5
6
7
public class Arraytest
{
int a[] = new int[6];
public static void main ( String arg[] ) {
System.out.println ( a[0] );
}
}
  • A null
  • B 0
  • C 编译出错
  • D 运行出错

解析

显示答案/隐藏答案正确答案: C

静态成员不能访问非静态成员

在java中静态方法中不能使用非静态方法和非静态变量。但非静态方法中可以使用静态变量。

考点5:

下面哪些类实现或继承了 Collection 接口?

  • A HashMap
  • B ArrayList
  • C Vector
  • D Iterator

解析

显示答案/隐藏答案正确答案: BC

这里有一张图片

这里有一张图片

这里有一张图片

这里有一张图片

这里有一张图片

这里有一张图片

Collection下有三个子接口List,Set,Queue。
Map下有两个子接口AbstractMap,SortedMap,
所以看到:

  • 一个类名属于什么什么List,Set,Queue就是实现了Collection接口,
  • 一个类名属于什么什么Map就是实现了Map接口

考点6:

实现或继承了Collection接口的是()

  • A Map
  • B List
  • C Vector
  • D Iterator
  • E Set

解析

显示答案/隐藏答案正确答案: BCE

这里有一张图片

在java.util包中提供了一些集合类,常用的有List、Set和Map类,其中List类和Set类继承了Collection接口。这些集合类又称为容器,长度是可变的,数组用来存放基本数据类型的数据,集合用来存放类对象的引用。
List接口、Set接口、Map接口以及Collection接口的主要特征如下:

1.Collection接口是List接口和Set接口的父接口,通常情况下不被直接使用。
2.List接口继承了Collection接口,List接口允许存放重复的对象,排序方式为按照对象的插入顺序。
3.Set接口继承了Collection接口,Set接口不允许存放重复的对象,排序方式为按照自身内部的排序规则。
4.Map接口以键值对(key—value)的形式存放对象,其中键(key)对象不可以重复,值(value)对象可以重复,排序方式为按照自身内部的规则。

C:Vector实现了List接口,即间接实现Collection接口
D:Iterator是Java迭代器最简单的实现,没有实现Collection接口

这里有一张图片

这里有一张图片

考点7:

下面关于Applet的说法是正确的是

  • A Applet可以在带有Java解释器的浏览器中运行
  • B Applet类必须继承java.applet.Applet
  • C Applet可以访问本地文件
  • D AppletObject类的子类

解析

显示答案/隐藏答案正确答案: ABCD

考点1:Java编程单元

Java中基本的编程单元为:

  • A 类
  • B 函数
  • C 变量
  • D 数据

解析

显示答案/隐藏答案正确答案: A

java的基本编程单元是类,基本存储单元是变量。

考点2:

下列说法正确的是

  • A 在类方法中可用this来调用本类的类方法
  • B 在类方法中调用本类的类方法可直接调用
  • C 在类方法中只能调用本类的类方法
  • D 在类方法中绝对不能调用实例方法

解析

显示答案/隐藏答案正确答案: B

考点3:

语句:char foo=’中’,是否正确?(假设源文件以GB2312编码存储,并且以javac – encoding GB2312命令编译)

  • A 正确
  • B 错误

解析

显示答案/隐藏答案正确答案: A

考点5:

1
2
3
4
5
6
7
8
9
//point X
public class Foo {
public static void main(String[] args) throws Exception {

PrintWriter out = new PrintWriter(
new java.io.OutputStreamWriter(System.out), true);
out.printIn("Hello");
}
}

下面哪个选项放在poinx X这里可以正确执行?

  • A import java.io.PrintWriter;
  • B include java.io.PrintWriter;
  • C import java.io.OutputStreamWriter;
  • D include java.io.OutputStreamWriter;
  • E no statement is needed.

解析

显示答案/隐藏答案正确答案: A

java中没有include关键字,导包用import
由于代码中使用了printWriter 类,所以要导入此类Import java.io.PrintWriter;

考点6:

下列语句中,正确的是

  • A float x=0.0
  • B boolean b=3>5
  • C char c="A"
  • D double =3.14

解析

显示答案/隐藏答案正确答案: B

A小数默认double,float x=0.0f
C字符串不能赋值给字符
D没有变量名

考点7:

1.将下列(A、B、C、D)哪个代码替换下列程序中的【代码】不会导致编译错误?

1
2
3
4
5
6
7
interface Com{
int M=200;
int f();
}
class ImpCom implements Com{
【代码】
}
  • A public int f(){return 100+M;}
  • B int f(){return 100;}
  • C public double f(){return 2.6;}
  • D public abstract int f();

解析

显示答案/隐藏答案正确答案: A

C: The return type is incompatible with Com.f()
D:The abstract method f in type ImpCom can only be defined by an abstract class

必须实现接口的所有方法 方法原型要一致

1、必须实现接口中所有的方法。
在实现类中实现接口时,方法的名字、返回值类型、参数的个数及类型必须与接口中的完全一致,并且必须实现接口中的所有方法。

访问权限要更低

2、接口实现类相当于子类,子类的访问权限是不能比父类小的。

实现的接口方法都是public

接口中所有方法默认都是public,至于为什么要是public,原因在于如果不是public,那么只能在同个包下被实现,可访问权限就降低很多了,那么在实现类中,实现的类相当于子类,子类的访问权限是不能比父类小的,而在java中一个类如果没有权限的修饰符,默认是friendly(同一个包内的其它类才可访问),所以在接口的实现类重写的方法中一定要写public

两同两小一大

接口中的抽象方法默认的修饰符是public abstract,后重写,两同两小一大可知,前边修饰符应该是public

接口的成员特点是:

  1. 成员变量修饰符 默认 public static final
  2. 成员方法修饰符 默认 public abstract

考点8:

下面哪些接口直接继承自Collection接口()

  • A List
  • B Map
  • C Set
  • D Iterator

解析

显示答案/隐藏答案正确答案: AC

集合继承树

这里有一张图片

这里有一张图片

这里有一张图片

这里有一张图片

Iterator接口 不继承任何接口!

考点9:

抽象类和接口的区别,以下说法错误的是

  • A 接口是公开的,里面不能有私有的方法或变量,是用于让别人使用的,而抽象类是可以有私有方法或私有变量的。
  • B abstract classJava 语言中表示的是一种继承关系,一个类只能使用一次继承关系。但是,一个类却可以实现多个interface,实现多重继承。接口还有标识(里面没有任何方法,如Remote接口)和数据共享(里面的变量全是常量)的作用。
  • C 在abstract class 中可以有自己的数据成员,也可以有非abstarct的成员方法,而在interface中,只能够有静态的不能被修改的数据成员(也就是必须是 static final的,不过在 interface中一般不定义数据成员),所有的成员方法默认都是 public abstract 类型的。

-D abstract classinterface所反映出的设计理念不同。其实abstract class表示的是has-a关系,interface表示的是is-a关系。

解析

显示答案/隐藏答案正确答案: ACD

抽象类:在Java中被abstract关键字修饰的类称为抽象类,被abstract关键字修饰的方法称为抽象方法,抽象方法只有方法的声明,没有方法体。抽象类的特点: a、抽象类不能被实例化只能被继承; b、包含抽象方法的一定是抽象类,但是抽象类不一定含有抽象方法; c、抽象类中的抽象方法的修饰符只能为public或者protected,默认为public; d、一个子类继承一个抽象类,则子类必须实现父类抽象方法,否则子类也必须定义为抽象类; e、抽象类可以包含属性、方法、构造方法,但是构造方法不能用于实例化,主要用途是被子类调用。 接口:Java中接口使用interface关键字修饰,特点为: a、接口可以包含变量、方法;变量被隐士指定为public static final,方法被隐士指定为public abstract(JDK1.8之前); b、接口支持多继承,即一个接口可以extends多个接口,间接的解决了Java中类的单继承问题; c、一个类可以实现多个接口; d、JDK1.8中对接口增加了新的特性: (1)、默认方法(default method):JDK 1.8允许给接口添加非抽象的方法实现,但必须使用default关键字修饰;定义了default的方法可以不被实现子类所实现,但只能被实现子类的对象调用;如果子类实现了多个接口,并且这些接口包含一样的默认方法,则子类必须重写默认方法; (2)、静态方法(static method):JDK 1.8中允许使用static关键字修饰一个方法,并提供实现,称为接口静态方法。接口静态方法只能通过接口调用(接口名.静态方法名)。 注意:jdk1.9是允许接口中出现private修饰的默认方法和静态方法

解析:
A:jdk1.9是允许接口中出现private修饰的默认方法和静态方法,A错误;
抽象类可以有私有的变量和方法。 B:正确
C:抽象类可以有抽象和非抽象的方法;jdk1.8接口中可以有默认方法和静态方法,C错误。
D:强调继承关系,is-a,如果A is-a B,那么B就是A的父类;
代表组合关系,like-a,接口,如果A like a B,那么B就是A的接口。 ;
强调从属关系,has-a,如果A has a B,那么B就是A的组成部分。
D项错误。

is a是继承(抽象类),has a是组合(接口)

在JDK9后,接口中可以有私有静态方法和私有普通方法

考点10:

下面的Java赋值语句哪些是有错误的 ()

  • A int i =1000;
  • B float f = 45.0;
  • C char s = ‘\u0639’
  • D Object o = ‘f’;
  • E String s = “hello,world\0”;
  • F Double d = 100;

解析

显示答案/隐藏答案正确答案: BCF

选项F是自动装箱, 装箱过程中调用的是Double类的valueOf(double d)方法, 而这里是100为int型, 所以编译会“cannot convert from int to Double”。

最后一个选项F项,很多人都没解释清楚。 首先,double d =100; 是不会错的,double是8个字节64位,int 是4个字节,32位。所以int转double,32位转64位,肯定是不会错的。

那F项错在哪里?仔细看是Double 不是double哦,所以这道题考的是java自动装箱,对于Integer和Double的自动装箱,只能装对应的数据类型,不对应就会报错。java中100默认是int型,而不是byte,short和long;100.0默认是double,而不是float。想了解int装箱,请大家仔细阅读这篇文章:关于int装箱更多问题。而装箱远比这个复杂,看下面。

Integer i=100;//没有问题
Integer i2=100.0;//报红杠,因为默认是double
Integer i3=(byte)100;//报红杠
Short s = (byte) 100;//没有问题,是不是很神奇?说明上面的规律对Short不适用
Double d=100; //报红杠
Double d=100.0;//没有问题
Double d=100.0f;//报红杠
double d=100;//没有问题,100是int类型,自动转换为double.
Double d=Double.valueOf("100"); //正确
Double d=Double.valueOf(100);//正确
Double d=new Double(100);//正确

考点1:构造方法

以下不属于构造方法特征的是()

  • A 构造方法名与类名相同
  • B 构造方法不返回任何值,也没有返回类型
  • C 构造方法在创建对象时调用,其他地方不能显式地直接调用
  • D 每一个类只能有一个构造方法

解析

显示答案/隐藏答案正确答案: D

考点2:类定义

有以下程序片段,下列哪个选项不能插入到第一行 。( )。

1
2
3
4
1.
2. public class A{
3. //do sth
4. }
  • A public class MainClass{ }
  • B package mine;
  • C class ANotherClass{ }
  • D import java.util.*;

解析

显示答案/隐藏答案正确答案: A

Java一个源程序只能有一个public类存在,且类名与文件名相同。
Java程序是从main方法开始执行的,public为类加载器提供入口,然后找到public类中的main方法开始执行。
如果存在多个public类,程序将不知道该从哪里执行。
注意,内部类可以是 public的,因为内部类是作为外部类的成员存在的

考点3:可信数据

后端获取数据,向前端输出过程中,以下描述正确的是

  • A 对于前端过滤过的参数,属于可信数据,可以直接输出到前端页面
  • B 对于从数据库获得的数据,属于可信数据,可以直接输出到前端页面
  • C 对于从用户上传的Excel等文件解析出的数据,属于可信数据,可以直接输出到前端页面
  • D 其它选项都不属于可信数据,输出前应该采用信息安全部发布的XSSFilter做进行相应编码

解析

显示答案/隐藏答案正确答案: D

考点4:线程 线程执行体 run(),start(),join()方法

以下哪个方法用于定义线程的执行体? ()

  • A start()
  • B join()
  • C run()
  • D synchronized()

解析

显示答案/隐藏答案正确答案: C

run()方法是用来定义这个线程在启动的时候需要做什么,但是,直接调用线程的run()方法只会执行一遍函数体,而不会开辟线程,必须使用star()来启动线程。

线程B.join()方法是停止当前正在运行的线程,先转去运行调用join()方法的线程B,直到线程B运行结束后。再返回运行当前线程。

考点5:抽象类 abstract,final,static关键字

以下关于 abstract 关键字的说法,正确的是()

  • A abstract 可以与final 并列修饰同一个类。
  • B abstract 类中不可以有private的成员。
  • C abstract 类中必须全部是abstract方法。
  • D abstract 方法必须在abstract类或接口中。

解析

显示答案/隐藏答案正确答案: D
  1. abstract类不能与final,static使用。final修饰方法,子类可以调用,但不能覆盖。
  2. 抽象类可以有private成员,但最好不要有private,因为私有和抽象放在一起,子类如果想重写父类的私有方法根本继承不过来,也就无法重写
  3. 抽象类中可以有非抽象方法
  4. 抽象类中可以都是非抽象的,但是抽象方法一定要在类和接口
  • abstract类是需要被继承使用的,所以它不能被final使用,所以A错,
  • 也可以有private属性,B错,
  • 也可以有普通方法 甚至所有都可以是普通方法,当然这样也就失去了abstract类的意义,C错,
  • interface属于特殊的abstract类,也是abstract类,所以D对
  1. abstract类不能使用final,static修饰。
    • abstract类就是要被继承实现。
    • final修饰的类不能被继承,所以abstract不能和final共同修饰一个类
      • final修饰方法,子类可以调用,但不能覆盖。
      • final修饰的变量不能修改,既是常量。
    • static修饰的类只能是内部类static不能修饰外部类
      • 抽象类是不能实例化的,即不能被分配内存;
    • static修饰的方法在类实例化之前就已经别分配了内存,这样一来矛盾就出现了。所以abstract不能和static共同修饰同一个类,在abstract类里面,可以不能定义static内部类
  2. 最好不要有private因为私有和抽象放在一起,子类如果想重写父类的私有方法根本继承不过来,也就无法重写 。但是抽象类中是可以有私有的成员。
  3. 抽象类中可以有非抽象方法
  4. 抽象类中可以都是非抽象的,但是抽象方法一定要在抽象类和接口中。普通类可以被实例化,而抽象方法本身不能被调用,如果普通类有抽象方法,那么该方法被调用就会出错。

static不能修饰外部类

1
2
3
static class A{

}

报错:

1
Illegal modifier for the class A; only public, abstract & final are permitted

外部类只能是public,abstract,或者final修饰

abstract和static不能共同修饰方法

1
2
3
public abstract class B {
abstract static void method();
}

报错:

1
The abstract method method in type B can only set a visibility modifier, one of public or protected

abstract方法只能被public或protected修饰

1
private abstract void method();

报错:

1
The abstract method method in type B can only set a visibility modifier, one of public or protected

考点6:

下面关于JAVA的垃圾回收机制,正确的是( )

  • A 当调用”System.gc()“来强制回收时,系统会立即回收垃圾
  • B 垃圾回收不能确定具体的回收时间
  • C 程序可明确地标识某个局部变量的引用不再被使用
  • D 程序可以显式地立即释放对象占有的内存

解析

显示答案/隐藏答案正确答案: B

java提供了一个系统级的线程,即垃圾回收器线程。用来对每一个分配出去的内存空间进行跟踪。当JVM空闲时,自动回收每块可能被回收的内存,GC是完全自动的,不能被强制执行。程序员最多只能用System.gc()来建议执行垃圾回收器回收内存,但是具体的回收时间,是不可知的。当对象的引用变量被赋值为null,可能被当成垃圾。

考点7:hibernate延迟加载

下面有个hibernate延迟加载,说法错误的是?

  • A Hibernate2延迟加载实现:a)实体对象 b)集合(Collection)
  • B Hibernate3 提供了属性的延迟加载功能
  • C get支持延迟加载,load不支持延迟加
  • D hibernate使用Java反射机制,而不是字节码增强程序来实现透明性

解析

显示答案/隐藏答案正确答案: C

Hibernate 中 get()和load() 的区别:

get是立即加载,load是延迟加载。
get()采用立即加载方式,当get()执行的时候会立即向数据库发出查询语句,如果没有对应的记录,返回null,而load()采用延迟加载,执行此方法的时候返回的是一个***,只有等真正使用该对象属性的时候,才会发出SQL语句进行查询,若没有,则出现异常ObjectNotFoundException

考点8:IO流支持Unicode的IO流

哪个类可用于处理Unicode?

  • A InputStreamReader
  • B BufferedReader
  • C Writer
  • D PipedInputStream

解析

显示答案/隐藏答案正确答案: A

InputStreamReader可以指定字符编码格式
InputStreamReader是转换流,将字节流转换成字符流。

BufferedReader只是起到了装饰的作用,就是不用每次都new一个数组了,增加了缓冲区,缓冲区有和没有都一样,只是读取的快慢不同,真正实现功能的是InputStreamReader

看API就知道了。
A、 InputStreanReader的构造函数:

方法 描述
InputStreamReader(InputStream in) Creates an InputStreamReader that uses the default charset.
InputStreamReader(InputStream in, String charsetName) Creates an InputStreamReader that uses the named charset.
InputStreamReader(InputStream in, Charset cs) Creates an InputStreamReader that uses the given charset.
InputStreamReader(InputStream in, CharsetDecoder dec) Creates an InputStreamReader that uses the given charset decoder.

B、BufferedReader的构造函数:

方法 描述
BufferedReader(Reader in) Creates a buffering character-input stream that uses a default-sized input buffer.
BufferedReader(Reader in, int sz) Creates a buffering character-input stream that uses an input buffer of the specified size.

D、PipedInputStream的构造函数:

方法 描述
PipedInputStream() Creates a PipedInputStream so that it is not yet connected.
PipedInputStream(int pipeSize) Creates a PipedInputStream so that it is not yet connected and uses the specified pipe size for the pipe’s buffer.
PipedInputStream(PipedOutputStream src) Creates a PipedInputStream so that it is connected to the piped output stream src.
PipedInputStream(PipedOutputStream src, int pipeSize) Creates a PipedInputStream so that it is connected to the piped output stream src and uses the specified pipe size for the pipe’s buffer.

考点9:

以下代码定义了一个变量,如何输出这个变量的值?
这里有一张图片

1
<bean:define id="stringBean" value="helloWorld"/>
  • A <% String myBean = (String)pageContext.getAttribute("stringBean",PageContext.PAGE_SCOPE); %> <%=myBean%>
  • B <bean:write name="helloworld"/>
  • C <bean:write name="stringBean"/>
  • D <%=stringBean%>

解析

显示答案/隐藏答案正确答案: ACD

—————看完秒懂—————————

  • A选项:
    • 通过 pageContext(PageContext类的实例,提供对JSP页面所有对象以及命名空间的访问) 获取stringBean 的值,赋给 String 类型的变量 myBean,然后通过 Jsp 表达式 处理该值。
  • bean:define
    • 题目中的 Struts 的bean:define 标签定义了一个字符串变量 stringBean ,它的值为 helloworld。
  • bean:write
    • bean:write相当于 <%=request.getAttribute("something")%> 其中 something 是属性的名字。所以 B 错,C对。
  • D选项:
    • 通过Jsp 表达式 获取变量 stringBean 的值

考点10:

下面有关值类型和引用类型描述正确的是()?

  • A 值类型的变量赋值只是进行数据复制,创建一个同值的新对象,而引用类型变量赋值,仅仅是把对象的引用的指针赋值给变量,使它们共用一个内存地址。
  • B 值类型数据是在栈上分配内存空间,它的变量直接包含变量的实例,使用效率相对较高。而引用类型数据是分配在堆上,引用类型的变量通常包含一个指向实例的指针,变量通过指针来引用实例。
  • C 引用类型一般都具有继承性,但是值类型一般都是封装的,因此值类型不能作为其他任何类型的基类。
  • D 值类型变量的作用域主要是在栈上分配内存空间内,而引用类型变量作用域主要在分配的堆上。

解析

显示答案/隐藏答案正确答案: ABC

我的理解(有错麻烦大家指正,谢谢!)

值类型:基本数据类型(int、double、boolean ...)
引用类型:reference类型,通过它可以直接或间接的查找到对象在java堆中数据存放的起始地址或索引(对象在java堆中的哪个位置)

先来两个例子,变量的赋值在内存中是怎么样的:
先上一张运行时数据区的网图
局部变量表、操作数栈在虚拟机栈中

一:基本变量的赋值

public void method() {
int a = 1;
int b = a;
}

该方法的字节码:
0 iconst_1 // 将 int 型 1 推送至操作数栈栈顶
1 istore_1 // 将操作数栈栈顶 int 型值存入第二个本地变量
2 iload_1 // 将第二个int型本地变量推送至操作数栈顶
3 istore_2 // 将操作数栈栈顶 int 型值存入第三个本地变量
4 return // 方法返回

图片说明

二:基本变量的赋值

public void method2() {
Object a = new Object();
Object b = a;
}

该方法的字节码:
0 new #15 <java/lang/Object> // 创建一个对象,并将其引用压入栈顶
3 dup // 复制栈顶引用类型数据并将其值压入栈顶
4 invokespecial #1 <java/lang/Object.<init>> // 执行对象构造方法(使用了栈顶引用类型)
7 astore_1 // 将操作数栈栈顶引用类型数据值存入第二个本地变量 a
8 aload_1 // 将第二个引用类型本地变量推送至栈顶
9 astore_2 // 将栈顶引用类型数值存入第三个本地变量b
10 return // 方法返回

图片说明

再看选项

  • A(✔)值类型的和引用类型的变量赋值就像上面一样,先把局部变量表中 a 的数值存入操作数栈,再取出来放入 b,不过区别在于:

    • 前者在局部变量表中存放的数值是真正意义上的 a 代表的数据,所以说赋值操作是“复制(iload_1、istore_2)”一份出来再给 b
    • 后者在局部变量表中存放的数值不是真正意义上 a 代表的数据,只是指向堆中对象的指针(指向 a 真正代表的数据)。赋值操作只是把 a 中数值即指针复制给 b ,堆中a代表正真的数据即对象(0x11)并没有被复制
  • B(✔)

    • "值类型数据是在栈(指虚拟机栈)上分配内存空间,它的变量直接包含变量的实例,使用效率相对较高。" :局部变量表(在虚拟机栈中)中存放数值的就是真正意义上的数据,不用访问堆,效率较高
    • “而引用类型数据是分配在上,引用类型的变量通常包含一个指向实例(指向堆中对象)的指针,变量通过指针来引用实例。” :局部变量表中存放的数值是指向中数据(对象)的指针
  • C(✔):类可以继承,基本数据类型不能继承

  • D(X):“值类型变量的作用域主要是在栈上分配内存空间内”:如果是跟上诉一致在方法内定义的基本变量,它的作用域就在栈中;如果是在类中定义的成员变量例如 Class A 中有成员变量 int val,这个类的实例在堆中,那么 val 作用域也在堆中


题外话:操作数栈深度在编译期就已经决定

考点1:基本类型的表示范围 float小数初始化 long整数初始化

以下的变量定义语句中,合法的是()

  • A byte=128
  • B boolean=null
  • C long a=123L
  • D double=0.9239d

解析

显示答案/隐藏答案正确答案: C

byte能表示的范围[-128,127]
boolean的取值只能是true或 false
整数默认是int类型,如果要转为long类型,需要在整数后面加上L
小数默认类型是double,如果要转为float类型,需要在小数后面加上字母F

考点2:final类 String

有以下代码片段:

1
2
3
String str1="hello";
String str2="he"+ new String("llo");
System.out.println(str1==str2);

请问输出的结果是:

  • A true
  • B 都不对
  • C null
  • D false

解析

显示答案/隐藏答案正确答案: D

这里的str1指的是方法区中的字符串常量池中的“hello”,编译时期就知道的

String是fina1类,这意味着String不能被继承,在Java中被final修饰的类是不允许被继承的,并且final类的成员方法都默认是final方法.
String类底层是char数组来保存字符串的。

字符串常量池

在class件中有一部分用来存储编译期间生成的字面常量以及符号引用,这部分做class文件常量池

在运行期间对应着方法区的运行时常量池

借鉴之前关于 Stringi拼接的一个总结:1、常量和常量拼接,结果在常量池中且常를池中不存在相同内容的常量。2、只要有一个变星,结果就在堆中。3、如果拼接的结果调用了
tem()方法,返回值会在常量池中。补充一点,还有fna修饰时,拼接也会在常量池中.

考点3:try catch finally

能单独和finally语句一起使用的块是( )

  • A try
  • B catch
  • C throw
  • D throws

解析

显示答案/隐藏答案正确答案: A

注意细节:使用try…catch块捕天时可以没有 catch块,但当没
用 catch块的时候必须得有 finallyt块

使用try…catch捕获异常的时候,若没有catch块时,一定要写上
finally

考点4:transient关键字

以下哪个不能用来处理线程安全

  • A synchronized关键字
  • B volatile关键字
  • C Lock
  • D transient关键字

解析

显示答案/隐藏答案正确答案: D

transient,变量修饰符,如果用 transient声明一个实例变
量,当对象存储时,它的值不需要维持。当一个变量不希望
被持久化的时候,比如说一些账号密码,就可以用transient
关键字来表示亥变量不参与序列化过程

volatile修饰一个变量时,可以保证当前线程对亥变量操作的
可见性。当前线程有改变变量时,其他线程保存的副本将失
效,其他线程会从主内存中重新读取。 volatile只保证对它修
饰的变量的读写操作具有原子性

单纯使用 volatile关键字是不能保证线程安全的
volatile只提供了一种弱的同步机制,用来确保将变量的更新操作通知到其他线程。
volatile语义是禁用CPU缓存,直接从主内存读、写变量。表现为:更新 volatile变量时,JVM会把线程对应的本地内存中的共享变星值刷新到主内存中;读volatile变量时,JVM会把线程对应的本地内存设置为无效,直
接从主内存中读取共享变量.
当把变量声明为 volatile类型后,JM增加内存屏章,禁
止CPU进行指令重。

实现,继承都具有遗传性,实现了serializable的类的子类也实现 serializable
基本类型,包装类, String默认实现serializable。

一个类实现serializable接口时,要保证其成员变量都要实现serializable。

transient修饰成员变量使其不被序列化。

volatile关键字:
1.保证了不同线程对该变量操作的内存可见性(当一个线程修改了变量其他使用次变量的线程可以立即知道
这一修改)。
2.禁止了指令重排序

Lock接口提供了与 synchronized关键字类似的同步功能,但
需要在使用时手动获取锁和释放锁。

transient-关键字简单地说,就是让某些被修饰的成员属性变
量不被序列化

synchrozied关键字称作同步,主要用来给方法、代码块加
锁,被加锁的代码段,同一时间内多线程同时访问同一对象
的加锁方法代码块时,只能有一个线程执行能执行方法代码
块中的代码,其余线程必须等待当前线程执行完以后才执行
该方法代码块。

考点5:ASCII码 向上转型

执行语句”int a= '2'“后,a的值是( )

  • A 2
  • B 50
  • C 49
  • D 0

解析

显示答案/隐藏答案正确答案: B

一个简便的记忆法:0:48,A:65,a:97

48 65 97

考点6:

在JAVA中,假设A有构造方法A(int a),则在类A的其他构造方法中调用该构造方法和语句格式应该为()

  • A this.A(x)
  • B this(x)
  • C super(x)
  • D A(x)

解析

显示答案/隐藏答案正确答案: B

this的作用其中一个就是在一个构造方法中调用另一个构造方
法,格式为this(参数)

考点7:

下面程序运行完之后,t2与t3的关系为()

1
2
3
4
5
6
7
8
9
10
11
12
13
Object obj=new Object();
List aList=new ArrayList();
List bList=new LinkedList();
long t1=System.currentTimeMillis();
for(int i=0;i<50000;i++){
aList.add(0,obj);
}
long t2=System.currentTimeMillis()-t1;
t1=System.currentTimeMillis();
for(int i=0;i<50000;i++){
bList.add(0,obj);
}
long t3=System.currentTimeMillis()-t1;
  • A t2
  • B t2=t3
  • C 不确定
  • D t2>t3

解析

显示答案/隐藏答案正确答案: D

Arraylist内部是动态数组实现,在增加空间时会复制全部数据到扩容后的新数组中。
Linkedlist内部为双向链表,可以按需分配空间,扩展时不需要批量赋值,因此Linkedlist用时少。

Arraylist:增删慢,查询快。

  • 由于是数据组实现,需要连续的内存空间,如果删除数组中间的值,为了保证下标的有效性,需要将后面的数据往前移,所以删除馒。
  • 当插入A对象到B对象的前面时,需要将B对象和B对象之后的所有对象后移一位,再插入A对象。所以插入慢。
  • 数组的大小是固定的,如果数组满了,需要重新分配空间,new一个新数组,然后copy旧数据到新数组中,最后再增加新数据,所以增加慢。
  • 因为是连续内存空间,可以通过下标查询数据,所以查询快。

Linkedlist:增删快,查询慢。

  • 由于是链表实现,当前节点的nex指向下一个节点,prev指向上一个节点,不需要连续的内存空间。增加或删除时只需要修改指针即可,不需要移动。所以增删快
  • 因为不是连续内存空间,所以不能使用下标查询,只能通过next遍历来查找,所以查询馒。

ArrayList容量不够需要扩容,依次扩容1.5倍,并且插入数据需要用到数组的copy,
Linklist不需要扩容,插入仅需要链表擅长的插入操作即可,故Linklisth的操作时间低.

但是如果讲究尾部插入的话,数据量小的情況下可难分伯仲,但是在插入数据量大的倩况下, ArrayList怕的效率是要
高于Linkliste的。
因为,数据量大之后,扩容不是很烦繁,仅需要尾部插入即可,但是Linklist需要每次进行链表节点指针的指向调整操作。
所以大量数据的尾部面入, ArrayList的效率是要高于Linkliste的,下图是数据量较大时的比较。

这里有一张图片

考点8:volatile关键字

volatile关键字的说法错误的是

  • A 能保证线程安全
  • B volatile关键字用在多线程同步中,可保证读取的可见性
  • C JVM保证从主内存加载到线程工作内存的值是最新的
  • D volatile能禁止进行指令重排序

解析

显示答案/隐藏答案正确答案: A

出于运行速率的考虑,java编译器会把经常经常访问的变量放到缓存(严格讲应该是工作内存)中,
读取变量则从缓存中读。
但是在多线程编程中,内存中的值和缓存中的值可能会出现不一致。

volatile用于限定变量只能从内存中读取,保证对所有线程而言,值都是一致的。但是 volatile不能保证原子性,也就不能保证线程安全

1.java的内存模型

java内存模型规定了所有的变量都存储在主内存中,
但是每个线程会有自己的工作内存,
线程的工作内存保存了该线程中使用了的变量(从主内存中拷贝的),
线程对变量的操作都必须在工作内存中进行,
不同线程之间无法直接访问对方工作内存中的变量,
线程间变量值从传递都要经过主内存完成

img

2.什么是原子性

一个操作是不可中断的,要么全部执行成功要么全部执行失败,比如银行转账

3.什么是可见性

当多个线程访问同一变量时,一个线程修改了这个变量的值,其他线程就能够立即看到修改的值。

4.什么是有序性

程序执行的顺序按照代码的先后顺序执行

1
2
int a=0;//1
int b=2;//2

像这2句代码,1会比2先执行,但是JVM在真正执行时不一定是1在2之前,这里渉及一个概念叫做指令重排,

指令重排

处理器为了提高程序运行效率,可能会对输入代码进行优化,它不保证程序中各个语句的执行先后顺序同代码中的顺序一致,但是它会保证程序最终执行结果和代码序执行的结果是一致的。

比如上面的代码语句1和语句2谁先执行对最终的程序结果并没有影响。那么就有可能在执行过程中,语句2先执行而语句1后执行

在指令重排时会考虑指令之间的数据依赖性,比如2依赖了1的数值,那么处理器会保证1在2之前执行。

但是在多线程的情况下,指令重排就会有影响了。

5.volatile到底做了什么

  • 禁止了指令重排
  • 保证了不同线程对这个变量进行操作时的可见性,即一个线程修改了某个变量值,这个新值对其他线程是立即可见的
  • 不保证原子性(线程不安全)

考点9:

以下哪种JAVA的变量表达式使得变量a和变量b具有相同的内存引用地址( )

  • A String a = "hello"; String b = "hello";
  • B Integer a; Integer b = a;
  • C int a = 1; Integer b = new Integer(1);
  • D int a = 1; Integer b = 1;

解析

显示答案/隐藏答案正确答案: AB

1 Integer与int比较时, Integer会有拆箱的过程,我们可以看看拆箱的代码

1
2
3
public int inValue(){
return value;
}

直接返回的就是value,因此int a;与Integer b;以及new Integer(a);进行==比较时结果都是true。

解析混乱,我就不记下来了。