考点1:java常识

下列描述中,错误的是( )

  • A java要求编程者管理内存
  • B java的安全性体现在多个层次上
  • C java中没有指针机制
  • D java有多线程机制

解析

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

Java与C++的区别在于:Java去除了指针的概念,使用引用,并且Java的内存管理不需要程序员来管理,由Java虚拟机来完成对内存的管理

考点2:abstract final static native

若在某一个类定义中定义有如下的方法: abstract void performDial( ); 该方法属于()

  • A 本地方法
  • B 最终方法
  • C 解态方法
  • D 抽象方法

解析

显示答案/隐藏答案正确答案: D
  • 本地方法:简单地讲,一个native Method就是一个java调用非java代码的接口;native方法表示该方法要用另外一种依赖平台的编程语言实现。
  • 最终方法final void B(){},这样定义的方法就是最终方法,最终方法在子类中不可以被重写,也就是说,如果有个子类继承了这个最终方法所在的类,那么这个子类中不能出现void B(){}这样的方法。
  • 最终类:**final class A {},**这样定义的类就是最终类,最终类不能被继承。
  • abstract修饰抽象类

A.vJAVA中有两种方法:JAVA方法和本地方法。 JAVA方法是由JAVA编写的,编译成字节码,存储在class文件中; 本地方法是由其它语言编写的,编译成和处理器相关的机器代码,本地方法保存在动态链接库中,即.dll(windows系统)文件中,格式是各个平台专有的。
JAVA方法是与平台无关的,但是本地方法不是。
B.final void A() {},这样定义的方法就是最终方法,最终方法在子类中不可以被重写。 也就是说,如果有个子类继承这个最终方法所在的类,那么这个子类中就不能再出现void A() {}这样的方法了。
C.不存在解态方法这种东西,应该是笔误打错了,是静态方法。 静态方法的使用完全独立于该类的任何对象。 在类中使用static修饰的静态方随着类的定义而被分配和装载入内存中;而非静态方法属于对象的具体实例,只有在类的对象创建时在对象的内存中才有这个方法的代码段。

考点3:GUI

在委托事件模型中,源生成事件并把它发送给一个或多个监听器,每个监听器必须向事件源注册。

  • A T
  • B F

解析

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

考点4:实例变量 局部变量 final变量

下面有关java实例变量,局部变量,类变量和final变量的说法,错误的是?

  • A 实例变量指的是类中定义的变量,即成员变量,如果没有初始化,会有默认值。
  • B 局部变量指的是在方法中定义的变量,如果没有初始化,会有默认值
  • C 类变量指的是用static修饰的属性
  • D final变量指的是用final 修饰的变量

解析

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

局部变量必须初始化

定义在类中的变量是类的成员变量,可以不进行初始化,Java会自动进行初始化,如果是引用类型默认初始化为null,如果是基本类型例如int则会默认初始化为0
局部变量是定义在方法中的变量,必须要进行初始化,否则不同通过编译
被static关键字修饰的变量是静态的,静态变量随着类的加载而加载,所以也被称为类变量
被final修饰发变量是常量

为什么局部变量不会默认初始化

局部变量是指类方法中的变量,必须初始化。局部变量运行时被分配在栈中,量大,生命周期短,如果虚拟机给每个局部变量都初始化一下,是一笔很大的开销,但变量不初始化为默认值就使用是不安全的。出于速度和安全性两个方面的综合考虑,解决方案就是虚拟机不初始化,但要求编写者一定要在使用前给变量赋值。

变量分类

image-20210904224728900

考点5:集合 Collection和Collections

对Collection和Collections描述正确的是

  • A Collectionjava.util下的类,它包含有各种有关集合操作的静态方法
  • B Collectionjava.util下的接口,它是各种集合结构的父接口
  • C Collectionsjava.util下的接口,它是各种集合结构的父接口
  • D Collectionsjava.util下的类,它包含有各种有关集合操作的静态方法

解析

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

java.util.Collection
是一个集合接口。它提供了对集合对象进行基本操作的通用接口方法。Collection接口在Java
类库中有很多具体的实现。Collection接口的意义是为各种具体的集合提供了最大化的统一操作方式

  • Collection是单列集合的顶层接口,
  • Map是双列集合的顶层接口
  • Collections是一个集合的工具类,提供了排序、查找等操作集合的一些常用方法

考点6:java构造函数

下列有关java构造函数叙述正确的是()

  • A 构造器的返回值为void类型
  • B 如果一个源文件中有多个类,那么构造器必须与公共类同名
  • C 构造器可以有0个,1个或一个以上的参数
  • D 每个类可以有一个以上的构造器

解析

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

考点7:has-a is-a 子类通过继承得到父类的成员

Gadget has-a Sprocket and Gadget has-a Spring and Gadget is-a Widget and Widget has-
a Sprocket

以下哪两段代码可以表示这个关系? (选择两项) ( )

  • A
    1
    2
    class Widget { Sprocket s; }
    class Gadget extends Widget { Spring s; }
  • B
    1
    2
    class Widget { }
    class Gadget extends Widget { Spring s1; Sprocket s2; }
  • C
    1
    2
    class Widget { Sprocket s1; Spring s2; }
    class Gadget extends Widget { }
  • D
    1
    2
    class Gadget { Spring s; }
    class Widget extends Gadget{ Sprocket s; }

解析

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

is-a表示继承:Gadget is-a Widget就表示Gadget 继承 Widget;
has-a表示从属:Gadget has-a Sprocket就表示Gadget中有Sprocket的引用,Sprocket是Gadget的组成部分;
like-a表示组合:如果A like-a B,那么B就是A的接口

从题目中可以得出以下几个结论:

  • Gadget中有对Sprocket的引用。

  • Gadget中有对Spring的引用。

  • Gadget继承了Widget。

  • Widget中有对Sprocket的引用。

  • A

    class Widget { Sprocket s; }
    class Gadget extends Widget { Spring s; }
    完全符合要求,这里的结论1虽然没有明确表明,但是因为结论3(Gadget继承了Widget)的存在,即父类中的非私有成员(Sprocket)子类都默认拥有。故结论都成立。

  • B

    class Widget { }
    class Gadget extends Widget { Spring s1; Sprocket s2; }
    结论123成立,但是没有表明结论4。

  • C

    class Widget { Sprocket s1; Spring s2; }
    class Gadget extends Widget { }
    完全符合要求,这里的结论12虽然没有明确表明,但是因为结论3(Gadget继承了Widget)的存在,即父类中的非私有成员(Sprocket和Spring)子类都默认拥有。故结论都成立。

  • D

    class Gadget { Spring s; }
    class Widget extends Gadget{ Sprocket s; }
    结论24成立,但是结论13没有表明。这里只是表明了Widget继承了Gadget,并且Widget具有对Spring的引用。

这道题主要考查我们的Java类与类之间的关系。 类与类之间有三种关系:
(1)is-a 包括了继承(类)和实现(接口)关系;
(2)has-a包括了关联、聚合、组合关系;
(3)use-a包括了依赖关系;

考点8:JVM垃圾回收算法

以下哪些jvm的垃圾回收方式采用的是复制算法回收

  • A 新生代串行收集器
  • B 老年代串行收集器
  • C 并行收集器
  • D 新生代并行回收收集器
  • E 老年代并行回收收集器
  • F cms收集器

解析

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

两个最基本的java回收算法:复制算法和标记清理算法
复制算法:两个区域A和B,初始对象在A,继续存活的对象被转移到B。此为新生代最常用的算法
标记清理:一块区域,标记可达对象(可达性分析),然后回收不可达对象,会出现碎片,那么引出
标记-整理算法:多了碎片整理,整理出更大的内存放更大的对象
两个概念:新生代和年老代
新生代:初始对象,生命周期短的
永久代:长时间存在的对象
整个java的垃圾回收是新生代和年老代的协作,这种叫做分代回收。
P.S:Serial New收集器是针对新生代的收集器,采用的是复制算法
Parallel New(并行)收集器,新生代采用复制算法,老年代采用标记整理
Parallel Scavenge(并行)收集器,针对新生代,采用复制收集算法
Serial Old(串行)收集器,新生代采用复制,老年代采用标记整理
Parallel Old(并行)收集器,针对老年代,标记整理 CMS收集器,基于标记清理
G1收集器:整体上是基于标记 整理 ,局部采用复制

综上:新生代基本采用复制算法,老年代采用标记整理算法。cms采用标记清理。

考点9:super关键字 this关键字

在使用super和this关键字时,以下描述错误的是()

  • A 在子类构造方法中使用super()显示调用父类的构造方法,super()必须写在子类构造方法的第一行,否则编译不通过
  • B super()this()不一定要放在构造方法内第一行
  • C this()super()可以同时出现在一个构造函数中
  • D this()super()可以在static环境中使用,包括static方法和static语句块

解析

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

1、super()表示调用父类构造函数、this()调用自己的构造函数,而自己的构造函数第一行默认会使用super()调用父类的构造函数,所以这俩不能在一个构造函数中会出现重复引用的情况
2、super()和this()必须在构造函数第一行,所以这一点也表明他俩不能在一个构造函数中
3、this()和super()都指的是对象,所以,均不可以在static环境中使用。包括:static变量,static方法,static语句块(里面不能使用非static类型的)。

super()和this()不能同时在构造方法中使用,因为会导致重复实例化两次,而且这俩函数也不能放入static中,因为静态中不能操作实例对象

在构造器B中,使用this()调用其他构造器A时,构造器A的第一行会默认调用super()。

假设this()和super()能同时放在一起,则super()会被调用两次,初始化父类两次。
现实中父类只需要初始化一次就够了,所以this()和super()不能同时出现。

考点1:左移运算符

代码int i=3;i<<=4;i的值等于多少?()

  • A 40
  • B 110000(二进制)
  • C 12
  • D -48

解析

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

<<是左移运算符的意思,左移运算符是用来将一个数的各二进制位全部左移若干位。
这里可以理解为把3化为2进制,然后统一左移4位。

比如3的二进制 0000 0011 左移4位 0011 0000 = 48

考点2:循环条件

下面的程序中, int32_t表示一个有符号的 32 位整数,程序的入口是 main 函数,问最终 res 的结果是多少?

1
2
3
4
5
6
7
8
9
10
int32_t f(int32_t a,int32_t b){
while(a+b>0){
a=a+1;
b=b-1;
}
return a+b;
}
int32_t main(){
int32_t res=f(1,0);
}
  • A –(2^31+2^30+…+2^2+2^1+2^0)
  • B 0
  • C -1
  • D 程序会死循环

解析

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

考点3:C语言指针 内存图

下列代码段将打印出 ().

1
2
3
4
5
6
7
8
9
10
#include <stdio.h>
int main (void)
{
int a=2,*p1,**p2;
p2=&p1;
p1=&a;
a++;
printf("%d,%d,%d\n",a,*p1,**p2);
return 0;
}
  • A 3,2,3
  • B 2,2,2
  • C 3,3,3
  • D 3,3,2

解析

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

首先经过a++,a变成了3;
p1是指向a的地址的,因此*p1就是a的值,即为3;
p2是指向p1的地址的,因此*p2就是p1的值,即a的地址,那么**p2就是a的值,也就是3

考点4:自增运算

i=2,(i++)/3的结果是()

  • A 0
  • B 2
  • C 0.67
  • D 1

解析

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

后++,先取值,再加一

因为i++操作是在i/3完成之后,再对i进行加1操作的,所以结果是2/3,又因为2个int型相除,所以结果是0;

验证

1
2
3
int i = 2, b = (i++) / 3;
System.out.println(i);
System.out.println(b);

运行结果:

1
2
3
0

考点5:重载要求:参数列表不同

下面哪个方法是 public void example(){...} 的重载方法? ( )

  • A public void Example( int m){...}
  • B public int example(){...}
  • C public void example2(){...}
  • D public int example ( int m, float f){...}

解析

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

两同一不同

  • 在同一个类中
  • 方法名相同
  • 参数列表不同
    • 参数类型不同
    • 参数位置不同
    • 参数个数不同

考点6:二进制的表示范围

中国人口数量在10亿~20亿,如果用二进制记录人口数量,则至少需要_____位的长度。

  • A 30
  • B 31
  • C 33
  • D 63
  • E 64
  • F 65

解析

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

$2^{32}=42 9496 7295$约等于42亿
$2^{31}=21 4748 3647$约等于21亿

10个亿就是1 000 000 000
20个亿就是2 000 000 000
要求:「如果用二进制记录人口数量,则至少需要_____位的长度」
给出的四个选项中
A.$2^{30}=10 7374 1824$ 满足了10个亿但是显然不满足20亿
B.$2^{31}=21 4748 3648$ 满足20个亿完全符合题意。所以选B

C.D.E.F嫌大

考点7:计算机的存储系统一般指

计算机的存储系统一般指( )

  • A ROM
  • B 内存(主存)
  • C RAM
  • D 外存(辅存)
  • E 控制器

解析

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

内存:包括随机存储器(RAM),只读存储器(ROM),以及高速缓存(CACHE)。
外存:磁盘、光盘、固态存储器等等。

考点1:局部变量没有默认值,必须初始化

下列代码中的错误原因是()

1
2
3
4
5
6
7
8
(1)   public class Test
(2) {
(3) public static void main(String [] args)
(4) {
(5) int i;
(6) i+=1;
(7) }
(8) }
  • A 非法的表达式 i+=1
  • B 找不到符号i
  • C 类不应为public
  • D 尚未初始化变量i
显示答案/隐藏答案正确答案: D

成员变量的基本数据类型可以不初始化,有默认值
局部变量的基本数据类型必须初始化,没有默认值

考点2:String常量

针对下面的代码块,哪个equal为true:()

1
2
3
String s1 = "xiaopeng" ;
String s2 = "xiaopeng" ;
String s3 =new String (s1);
  • A s1 == s2
  • B s1 = s2
  • C s2 == s3
  • D 都不正确
显示答案/隐藏答案正确答案: A

string是final修饰的,会将创建的变量放入字符串常量池,当再创建同样的字符串时,发现常量池中有则直接使用

考点3:成员变量有默认初始值,可以不初始化

当你编译和运行下面的代码时,会出现下面选项中的哪种情况?

1
2
3
4
5
6
public class Pvf{
static boolean Paddy;
public static void main(String args[]){
System.out.println(Paddy);
}
}
  • A 编译时错误
  • B 编译通过并输出结果false
  • C 编译通过并输出结果true
  • D 编译通过并输出结果null
显示答案/隐藏答案正确答案: B

类中声明的变量有默认初始值;方法中声明的变量没有默认初始值,必须在定义时初始化,否则在访问该变量时会出错。
boolean类型默认值是false。

考点4:HashMap添加元素时key相同新value覆盖旧value

以下java程序代码,执行后的结果是()

1
2
3
4
java.util.HashMap map=new java.util.HashMap();
map.put("name",null);
map.put("name","Jack");
System.out.println(map.size());
  • A 0
  • B null
  • C 1
  • D 2
显示答案/隐藏答案正确答案: C

HashMap可以插入null的key或value,插入的时候,检查是否已经存在相同的key,如果不存在,则直接插入,如果存在,则用新的value替换旧的value,在本题中,第一条put语句,会将key/value对插入HashMap,而第二条put,因为已经存在一个key为name的项,所以会用新的value替换旧的vaue,因此,两条put之后,HashMap中只有一个key/value键值对。那就是(name,jack)。所以,size为1.

考点5:访问控制符

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

  • A 正确
  • B 错误
显示答案/隐藏答案正确答案: A

考点6:TreeSet的subSet方法

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

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

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

考点7:Object方法

下面有关java object默认的基本方法,说法错误的是?

  • A equals(Object obj) 指示某个其他对象是否与此对象“相等”
  • B copy() 创建并返回此对象的一个副本
  • C wait() 导致当前的线程等待,直到其他线程调用此对象的 notify() 方法或 notifyAll() 方法
  • D toString() 返回该对象的字符串表示
显示答案/隐藏答案正确答案: B

Object中没有copy方法
Object的其中clone()创建并返回此对象的一个副本。没有copy()这个方法。
Object默认9方法:getClass(),hashCode(), equals(), clone(), toString(),notify(), notifyAll()wait(), finalize()。

方法 描述
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.

考点8:ASCII码和ANSI码

关于ASCII码和ANSI码,以下说法不正确的是()?

  • A 标准ASCII只使用7个bit
  • B 在简体中文的Windows系统中,ANSI就是GB2312
  • C ASCII码是ANSI码的子集
  • D ASCII码都是可打印字符
显示答案/隐藏答案正确答案: D

A、标准ASCII只使用7个bit,扩展的ASCII使用8个bit。
B、ANSI通常使用 0x000x7f 范围的1 个字节来表示 1 个英文字符。超出此范围的使用0x800xFFFF来编码,即扩展的ASCII编码。不同 ANSI 编码之间互不兼容。在简体中文Windows操作系统中,ANSI 编码代表 GBK 编码;在繁体中文Windows操作系统中,ANSI编码代表Big5;在日文Windows操作系统中,ANSI 编码代表 Shift_JIS 编码。
C、ANSI通常使用 0x00~0x7f 范围的1 个字节来表示 1 个英文字符,即ASCII码
D、ASCII码包含一些特殊空字符

ASCII表上的数字 0–31 分配给了控制字符,用于控制像打印机等一些外围设备。

我看下面一些评论对ANSI编码解释都有些许错误,现在解释一下ANSI编码:不同的国家和地区制定了不同的标准,由此产生了 GB2312、GBK、Big5、Shift_JIS 等各自的编码标准。这些使用 1 至 4 个字节来代表一个字符的各种汉字延伸编码方式,称为 ANSI 编码。在简体中文Windows操作系统中,ANSI 编码代表 GBK 编码;在日文Windows操作系统中,ANSI 编码代表 Shift_JIS 编码。 不同 ANSI 编码之间互不兼容,当信息在国际间交流时,无法将属于两种语言的文字,存储在同一段 ANSI 编码的文本中。 当然对于ANSI编码而言,0x00~0x7F之间的字符,依旧是1个字节代表1个字符。这一点是ANSI编码与Unicode编码之间最大也最明显的区别。

考点9:Java标识符规则

下列可作为java语言标识符的是()

  • A a1
  • B $1
  • C _1
  • D 11
显示答案/隐藏答案正确答案: ABC

Java标识符由数字,字母和下划线(_),美元符号($)或人民币符号(¥)组成。在Java中是区分大小写的,而且还要求首位不能是数字。最重要的是,Java关键字不能当作Java标识符。

  1. 标识符的组成元素是字母(a-zA-Z),数字(0~9),下划线(_)和美元符号($)。
  2. 标识符不能以数字开头。
  3. java的标识符是严格区分大小写的。
  4. 标识符的长度可以是任意的。
  5. 关键字以及引用类型常量null、boolean常量true、false不能用于自定义的标识符。

考点10:+=会自动类型转换(自动装箱)=不会自动类型转换

以下那些代码段能正确执行

  • A
    1
    2
    3
    4
    5
    6
    public static void main(String args[]) {
    byte a = 3;
    byte b = 2;
    b = a + b;
    System.out.println(b);
    }
  • B
    1
    2
    3
    4
    5
    6
    public static void main(String args[]) {
    byte a = 127;
    byte b = 126;
    b = a + b;
    System.out.println(b);
    }
  • C
    1
    2
    3
    4
    5
    6
    public static void main(String args[]) {
    byte a = 3;
    byte b = 2;
    a+=b;
    System.out.println(b);
    }
  • D
    1
    2
    3
    4
    5
    6
    public static void main(String args[]) {
    byte a = 127;
    byte b = 127;
    a+=b;
    System.out.println(b);
    }
    显示答案/隐藏答案正确答案: CD

char、byte、short相加时会自动转换为int类型,所以:
A、B选项需要加强转(byte)
C、D选项中的+=会自动进行强转,相当于加了(byte);
D选项中的越界问题,由于byte的最大值与最小值是首尾相接的(不知道这样描述准不准确,byte范围是-128-127,也就是说byte b1=(byte)128;System.out.println(b1);打印出来的实际是-128),由于加了强转,所以不会受到越界的影响。
有错误之处欢迎指出!

考点1:赋值运算符左值必须是变量

下面语句正确的是()

  • A x+1=5
  • B i++=1
  • C a++b=1
  • D x+=1
显示答案/隐藏答案正确答案: D

赋值运算符 左值必须是变量

首先赋值运算符“=”右值可以是任何常数、变量或者表达式(只要能生成一个值就行)。但左值必须是一个明确的、已命名的变量

常用的双元运算符:+=-=*=/=

解析:
A:x+1=5,赋值运算符左边是表达式,不对;
B:i++=1,从左到右运算是i=i+1=1,赋值运算符左边是表达式,错误;
C:a++b=1,赋值运算符左边为表达式,错误。
D:x+=1,既x=x+1,正确。

注意背一下各个运算符的先后顺序。

考点2:负数求余运算

以下代码段执行后的输出结果为

1
2
3
4
5
6
7
public class Test {
public static void main(String args[]) {
int x = -5;
int y = -12;
System.out.println(y % x);
}
}
  • A -1
  • B 2
  • C 1
  • D -2
显示答案/隐藏答案正确答案: D

换个角度去理解,y%x算得是y在除以x后还剩多少。这里显然是还剩-2没有除。

验算:

1
不论正负,都是a%b=a-a/b*b
1
2
3
4
5
-2=-12 - (-12/-5)*(-5)
=-12 - (2)*(-5)
=-12 - (-10)
=-12 + 10
=-2

在java中,求余运算,a%b,结果的符号和被除数a的符号一致。

1
2
3
4
System.out.println("-12 % -5= " + (-12 % -5));
System.out.println("-12 % +5= " + (-12 % +5));
System.out.println("+12 % -5= " + (12 % -5));
System.out.println("+12 % +5= " + (12 % +5));

运行结果:

1
2
3
4
-12 % -5= -2
-12 % +5= -2
+12 % -5= 2
+12 % +5= 2

当a为-12时,无论b是+5,还是-5。a%b的结果都是-2
当a为+12时,无论b是+5,还是-5。a%b的结果都是+2

1
2
3
4
System.out.println("-17 % -5= " + (-17 % -5));
System.out.println("-17 % +5= " + (-17 % +5));
System.out.println("+17 % -5= " + (17 % -5));
System.out.println("+17 % +5= " + (17 % +5));

运行结果:

1
2
3
4
-17 % -5= -2
-17 % +5= -2
+17 % -5= 2
+17 % +5= 2

考点3:使用迭代器遍历集合时,不可改变集合

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

1
2
3
4
5
6
7
8
9
10
11
Iterator it = list.iterator();
int index = 0;
while (it.hasNext())
{
Object obj = it.next();
if (needDelete(obj))//needDelete返回boolean,决定是否要删除
{
//todo delete
}
index ++;
}
  • A it.remove();
  • B list.remove(obj);
  • C list.remove(index);
  • D list.remove(obj,index);
显示答案/隐藏答案正确答案: A

迭代器遍历集合时 不可调用集合对象的remove方法或add方法

如果你想在循环语句中删除集合中的某个元素,就要用迭代器iterator的remove()方法,因为它的remove()方法不仅会删除元素,还会维护一个标志,用来记录目前是不是可删除状态,例如,你不能连续两次调用它的remove()方法,调用之前至少有一次next()方法的调用。

通过for循环遍历集合时,如何调用集合的remove方法删除元素,又不报错

1
2
3
4
for(int i=0;i<list.size();i++){
list.remove(i);
i--;
}

迭代器在迭代过程中要注意的事项:
1.迭代器在迭代过程中不允许使用集合对象改变集合的元素个数。否则会报出:ConcurrentModificationException,即并发修改异常。
2.在迭代过程中如果需要改变集合中的元素个数,只能使用迭代器的方法去改变。如add()方法和remove()方法。

不使用迭代器时,可以通过集合对象remove和add

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
ArrayList<Integer> list = new ArrayList<Integer>();
list.add(0);
list.add(1);
list.add(2);
list.add(3);
list.add(4);
list.add(5);
System.out.println(list);

for (int i = 0; i < list.size(); i++) {
if (i == 2) {
// list.remove(2);
list.remove(1);
}
}
System.out.println(list);

运行结果:

1
2
[0, 1, 2, 3, 4, 5]
[0, 2, 3, 4, 5]

使用迭代器遍历集合时,不可调用集合对象remove方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
ArrayList<Integer> list = new ArrayList<Integer>();
list.add(0);
list.add(1);
list.add(2);
list.add(3);
list.add(4);
list.add(5);
System.out.println(list);
Iterator<Integer> iterator = list.iterator();
while (iterator.hasNext()) {
Integer i = iterator.next();
if (i == 2) {
// 报错:java.util.ConcurrentModificationException
list.remove(2);
// 报错:java.util.ConcurrentModificationException
// list.add(5);
// 正确做法
// iterator.remove();
}
}
System.out.println(list);

运行结果:

1
2
3
4
5
[0, 1, 2, 3, 4, 5]
Exception in thread "main" java.util.ConcurrentModificationException
at java.util.ArrayList$Itr.checkForComodification(ArrayList.java:909)
at java.util.ArrayList$Itr.next(ArrayList.java:859)
at base.QiuYu.main(QiuYu.java:35)

使用迭代器遍历集合是不可调用集合对象的add方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
ArrayList<Integer> list = new ArrayList<Integer>();
list.add(0);
list.add(1);
list.add(2);
list.add(3);
list.add(4);
list.add(5);
System.out.println(list);

Iterator<Integer> iterator = list.iterator();
while (iterator.hasNext()) {
Integer i = iterator.next();
if (i == 2) {
// 报错:java.util.ConcurrentModificationException
// list.remove(2);
// 报错:java.util.ConcurrentModificationException
list.add(5);
// 正确做法
// iterator.remove();
}
}
System.out.println(list);

运行结果:

1
2
3
4
5
[0, 1, 2, 3, 4, 5]
Exception in thread "main" java.util.ConcurrentModificationException
at java.util.ArrayList$Itr.checkForComodification(ArrayList.java:909)
at java.util.ArrayList$Itr.next(ArrayList.java:859)
at base.QiuYu.main(QiuYu.java:27)

迭代器遍历集合时,如果要删除集合中的元素,只能调用迭代器对象的remove方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
ArrayList<Integer> list = new ArrayList<Integer>();
list.add(0);
list.add(1);
list.add(2);
list.add(3);
list.add(4);
list.add(5);
System.out.println(list);
Iterator<Integer> iterator = list.iterator();
while (iterator.hasNext()) {
Integer i = iterator.next();
if (i == 2) {
// 报错:java.util.ConcurrentModificationException
// list.remove(2);
// 报错:java.util.ConcurrentModificationException
// list.add(5);
// 正确做法
iterator.remove();
}
}
System.out.println(list);

运行结果:

1
2
[0, 1, 2, 3, 4, 5]
[0, 1, 3, 4, 5]

考点4:不同的Map的key和value是否能为null

在Java中,关于HashMap类的描述,以下正确的是 ()

  • A HashMap使用键/值得形式保存数据
  • B HashMap 能够保证其中元素的顺序
  • C HashMap允许将null用作键
  • D HashMap允许将null用作值
显示答案/隐藏答案正确答案: ACD
Map集合类 key value
HashMap 允许为null 允许为null
TreeMap 不允许为null 允许为null
ConcurrentMap 不允许为null 不允许为null
HashTable 不允许为null 不允许为null

考点5:对象序列化

以下关于对象序列化描述正确的是

  • A 使用FileOutputStream可以将对象进行传输
  • B 使用PrintWriter可以将对象进行传输
  • C 使用transient修饰的变量不会被序列化
  • D 对象序列化的所属类需要实现Serializable接口
显示答案/隐藏答案正确答案: CD

static和transient的成员变量不能对象序列化

使用ObjectOutputStream和ObjectInputStream可以将对象进行传输.
声明为static和transient类型的成员数据不能被串行化。
因为static代表类的状态, transient代表对象的临时数据。

考点7:正则表达式

正则表达式语法中 \d 匹配的是?()

  • A 数字
  • B 非数字
  • C 字母
  • D 空白字符
显示答案/隐藏答案正确答案: A
正则表达式 描述
\d 匹配一个数字字符。等价于 [0-9]
\D 匹配一个非数字字符。等价于 [^0-9]
\f 匹配一个换页符。等价于 \x0c\cL
\n 匹配一个换行符。等价于 \x0a\cJ
\r 匹配一个回车符。等价于 \x0d\cM
\s 匹配任何空白字符,包括空格、制表符、换页符等等。等价于 [ \f\n\r\t\v]
\S 匹配任何非空白字符。等价于 [^ \f\n\r\t\v]
\t 匹配一个制表符。等价于 \x09\cI
\v 匹配一个垂直制表符。等价于 \x0b\cK
\w 匹配字母、数字、下划线。等价于’[A-Za-z0-9_]‘。
\W 匹配非字母、数字、下划线。等价于 ‘[^A-Za-z0-9_]‘。

考点6:数组的下标

已知声明并初始化二维数组

1
int arr[][]={{1,2},{3,4},{5,6}}

,则的arr[1][1]值为()

  • A 1
  • B 2
  • C 4
  • D 5
显示答案/隐藏答案正确答案: C

一定要记住数组中以0下标开始

考点8:List和Set的异同

列表(List)和集合(Set)下面说法正确的是?( )

  • A Set中至多只能有一个空元素
  • B List中至多只能有一个空元素
  • C List和Set都可以包含重复元素的有序集合
  • D List和Set都是有序集合
显示答案/隐藏答案正确答案: A

java里面讲的有序无序,指的是你按照顺序存进去数据,然后再按照顺序取出来,两者是一样的。比如List(0)我放的是“a”,那么我list.get(0)取出来也是“a”。并不代表我存了打乱顺序存1到10十个数,它会自己给按照升序或者降序给你排好序。

list有序有重;set无序无重

考点9:Servlet过滤器

在J2EE中,使用Servlet过滤器,需要在web.xml中配置()元素

  • A <filter>
  • B <filter-mapping>
  • C <servlet-filter>
  • D <filter-config>
显示答案/隐藏答案正确答案: AB

答案:AB
Servlet过滤器的配置包括两部分:
第一部分是过滤器在Web应用中的定义,由<filter>元素表示,包括<filter-name><filter-class>两个必需的子元素
第二部分是过滤器映射的定义,由<filter-mapping>元素表示,可以将一个过滤器映射到一个或者多个Servlet或JSP文件,也可以采用url-pattern将过滤器映射到任意特征的URL

字符编码过滤器示例

举个例子,如下图:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<!-- 字符编码过滤器 -->
<filter>
<filter-name>CharacterEncodingFilter</filter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
<async-supported>true</async-supported>
<init-param>
<param-name>encoding</param-name>
<param-value>UTF-8</param-value>
</init-param>
<init-param>
<param-name>forceEncoding</param-name>
<param-value>true</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>CharacterEncodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>

没有<servlet-filter><filter-config>

考点10:反序列化 clone不调用构造器,new,反射newInstance调用构造器

下面的对象创建方法中哪些会调用构造方法 ()?

  • A new语句创建对象
  • B 调用Java.io.ObjectInputStream的readObject方法
  • C java反射机制使用java.lang.Class或java.lang.reflect.Constructor的newInstance()方法
  • D 调用对象的clone()方法
显示答案/隐藏答案正确答案: AC

readObject方法只是从文件中还原对象,clone只是一种复制拷贝对象。

7020520_1564402470654_E2A51A5DD194A70AC60F152482E33E06

考点11:String 基本类型转String

java中 String str = "hello world"下列语句错误的是?

  • A str+=' a'
  • B int strlen = str.length
  • C str=100
  • D str=str+100
显示答案/隐藏答案正确答案: ABC

A选项,单引号中不能有两个字符,
B选项,String对象没有.length属性,只有.length()方法
C选项,int类型的数据不能赋值给String类型的变量str

考点1:垃圾回收机制

1
2
3
4
5
6
static String str0="0123456789";
static String str1="0123456789";
String str2=str1.substring(5);
String str3=new String(str2);
String str4=new String(str3.toCharArray());
str0=null;

假定str0,…,str4后序代码都是只读引用。
Java 7中,以上述代码为基础,在发生过一次FullGC后,上述代码在Heap空间(不包括PermGen)保留的字符数为()

  • A 5
  • B 10
  • C 15
  • D 20
显示答案/隐藏答案正确答案: C

常量池是PermGen的

这是一个关于java的垃圾回收机制的题目。垃圾回收主要针对的是堆区的回收,因为栈区的内存是随着线程而释放的。
堆区分为三个区:

  • 年轻代(Young Generation)、

  • 年老代(Old Generation)、

  • 永久代(Permanent Generation,也就是方法区)。

  • 年轻代:对象被创建时(new)的对象通常被放在Young(除了一些占据内存比较大的对象),经过一定的Minor GC(针对年轻代的内存回收)还活着的对象会被移动到年老代(一些具体的移动细节省略)。

  • 年老代:就是上述年轻代移动过来的和一些比较大的对象。Minor GC(FullGC)是针对年老代的回收

  • 永久代:存储的是final常量,static变量,常量池。

str3,str4都是直接new的对象,而substring的源代码其实也是new一个string对象返回。:

java/lang/String.java
1
2
3
4
5
6
7
8
9
10
public String substring(int beginIndex) {
if (beginIndex < 0) {
throw new StringIndexOutOfBoundsException(beginIndex);
}
int subLen = value.length - beginIndex;
if (subLen < 0) {
throw new StringIndexOutOfBoundsException(subLen);
}
return (beginIndex == 0) ? this : new String(value, beginIndex, subLen);
}

经过fullgc之后,年老区的内存回收,则年轻区的占了15个,不算PermGen。所以答案选C

考点2:递归

下面这段程序的输出结果是()

1
2
3
4
5
6
7
8
9
10
11
12
public class Main {
public static void main(String[] args) {
split(12);
}
public static int split(int number) {
if (number > 1) {
if (number % 2 != 0) System.out.print(split((number + 1) / 2));
System.out.print(split(number / 2));
}
return number;
}
}
  • A 12136
  • B 63121
  • C 61213
  • D 11236
显示答案/隐藏答案正确答案: A

这种题目还考眼力,代码不规范,格式化后的代码如下:

1
2
3
4
5
6
7
8
public static int split(int number) {
if (number > 1) {
if (number % 2 != 0)
System.out.print(split((number + 1) / 2));
System.out.print(split(number / 2));
}
return number;
}

split(12);

12>1,true,进入外层if

12%2!=0,false,不进入内层if.

执行System.out.print(split(12 / 2));也就是System.out.print(split(6));

先执行split(6)

6>1,进入外层if
6 % 2 != 0,false,不进入内层if,

执行System.out.print(split(6 / 2));也就是执行System.out.print(split(3));

先执行split(3)

3>1,true,进入外层if

3 % 2 != 0,true,进入内层if

执行System.out.print(split((3 + 1) / 2));也就是执行System.out.print(split(2));

先执行split(2)
2>1,true,进入外层if
2 % 2 != 0,false,不进入内层if
执行System.out.print(split(2 / 2));也就是执行System.out.print(split(1));

先执行split(1)
1>1,false,不进入外层if,return 1,也就是split(1)=1

执行System.out.print(split(1)),也就是System.out.print(1);,输出1,
执行sprint(2)的返回语句,返回2
执行System.out.print(split(2));也就是执行System.out.print(2);,输出2

退出内层if

执行System.out.print(split(3 / 2));,也就是执行System.out.print(split(1));

先执行split(1)
1>1,false,不进入外层if,返回1,split(1)=1

执行System.out.print(split(1));也就是执行执行System.out.print(1);,输出1

退出外层if,返回3,split(3)=3

执行System.out.print(split(3));也就是执行执行System.out.print(3);输出3

执行split(6)的返回语句,返回6,

执行System.out.print(split(6));也就是执行System.out.print(6);输出6

退出split(12)的外层if

split(12)返回12

考察方法进栈与出栈的顺序。先进后出
有个知识点,方法在出栈的时候,执行的是return语句。因为出栈就意味着方法结束并销毁,如果没有return语句,那么方法出栈的时候什么都不执行,就直接销毁。

1.执行split(12)时,执行代码System.out.print(split(number / 2))
split(12/2)进栈,此时number=6;
2.执行split(6)时,执行代码System.out.print(split(number / 2))
split(6/2)进栈,此时number=3;
3.执行split(3)时,

1
2
3
1if (number % 2 != 0)
2行 System.out.print(split((number + 1) / 2));
3行 System.out.print(split(number / 2));

按照顺序执行
先执行第2行
首先split((3+1)/2)进栈,此时number=2,
再执行split(2),那么split(2/2)进栈,此时number=1, 最后return 1,
注意此时第2行代码还没有结束
此时
split(2/2)出栈,输出1;
split((3+1)/2)出栈,输出2;
第二行代码结束,再执行第三行,此时number=3,执行System.out.print(split(number / 2))
split(3/2)进栈,number=1,return,那么就需要出栈了
split(3/2)出栈,输出1
split(6/2)出栈,输出3
split(12/2)出栈,输出6;
最终结果12136;

split(number)方法,最终返回的是number这个值,所以split(n)出栈的输出结果就是n

整理:

1
2
3
4
5
6
7
8
9
10
11
split(12/2)进栈
split(6/2)进栈
split((3+1)/2)进栈
split(2/2)进栈
split(2/2)出栈,输出1
split((3+1)/2)出栈,输出2

split(2/2)进栈
split(2/2)出栈,输出1
split(6/2)出栈,输出3
split(12/2)出栈,输出6

考点3:JVM内存配置参数

对于JVM内存配置参数:
-Xmx10240m -Xms10240m -Xmn5120m -XXSurvivorRatio=3
,其最小内存值和Survivor区总大小分别是()

  • A 5120m,1024m
  • B 5120m,2048m
  • C 10240m,1024m
  • D 10240m,2048m
显示答案/隐藏答案正确答案: D
参数 描述
-Xmx: 最大堆大小
-Xms: 初始堆大小
-Xmn: 年轻代大小
-XXSurvivorRatio: 年轻代中Eden区与Survivor的一个区的大小比值,Survivor有两个区

-Xms10240m,初始堆大小即最小内存值为10240m
-Xmn5120m,表示年轻代大小5120m

-XXSurvivorRatio=3表示Eden:S0:S1=3:1:1
Survivor区总大小=(5120/(3+1+1))*(1+1)=(5120/5)*2=1024*2=2048

考点4:Servlet ServletContext参数值

如何获取ServletContext设置的参数值?

  • A context.getParameter()
  • B context.getInitParameter()
  • C context.getAttribute()
  • D context.getRequestDispatcher()
显示答案/隐藏答案正确答案: B

getParameter()是获取POST/GET传递的参数值;
getInitParameter获取Tomcat的server.xml中设置Context的初始化参数
getAttribute()是获取对象容器中的数据值;
getRequestDispatcher是请求转发。

考点5:线程 InterruptedException

下面哪个行为被打断不会导致InterruptedException:( )?

  • A Thread.join
  • B Thread.sleep
  • C Object.wait
  • D CyclicBarrier.await
  • E Thread.suspend
显示答案/隐藏答案正确答案: E

抛InterruptedException的代表方法有:
java.lang.Object 类的 wait 方法
java.lang.Thread 类的 sleep 方法
java.lang.Thread 类的 join 方法

Thread只有sleep​和join这两个方法抛出InterruptedException

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

1
2
3
4
5
public static void sleep​(long millis) throws InterruptedException
public static void sleep​(long millis, int nanos) throws InterruptedException
public final void join​(long millis) throws InterruptedException
public final void join​(long millis, int nanos) throws InterruptedException
public final void join() throws InterruptedException

Thread的suspend方法

https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/lang/Thread.html#suspend()

文档中描述如下

@Deprecated(since="1.2") public final void suspend()
Deprecated.
This method has been deprecated, as it is inherently deadlock-prone. If the target thread holds a lock on the monitor protecting a critical system resource when it is suspended, no thread can access this resource until the target thread is resumed. If the thread that would resume the target thread attempts to lock this monitor prior to calling resume, deadlock results. Such deadlocks typically manifest themselves as “frozen” processes. For more information, see Why are Thread.stop, Thread.suspend and Thread.resume Deprecated?.
Suspends this thread.
First, the checkAccess method of this thread is called with no arguments. This may result in throwing a SecurityException (in the current thread).
If the thread is alive, it is suspended and makes no further progress unless and until it is resumed.
Throws:
SecurityException - if the current thread cannot modify this thread.
See Also:
checkAccess()

没看到有抛出InterruptedException异常

Object类中只有wait方法抛出InterruptedException

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

1
2
3
public final void wait() throws InterruptedException
public final void wait​(long timeoutMillis) throws InterruptedException
public final void wait​(long timeoutMillis, int nanos) throws InterruptedException

考点6:网路编程 URL类

URL u =new URL("http://www.123.com");。如果www.123.com不存在,则返回______

  • A http://www.123.com
  • B ””
  • C null
  • D 抛出异常
显示答案/隐藏答案正确答案: A

new URL只检查URL的格式是否正确

new URL()时必须捕获检查异常,但这个异常是由于字符串格式和URL不符导致的,与网址是否存在无关。URL的toString方法返回字符串,无论网址是否存在。

示例

1
2
3
4
5
6
7
8
9
10
11
public class URLtest {
public static void main(String[] args) {
try {
// URL u =new URL("http://www.123.com");
URL u =new URL("http://www.agaeww123fjaoufoaufoajquroquroqj223453uuiu.com");
System.out.println(u);
} catch (MalformedURLException e) {
e.printStackTrace();
}
}
}

运行结果:

1
http://www.agaeww123fjaoufoaufoajquroquroqj223453uuiu.com
1
2
3
4
5
6
7
8
9
10
11
12
public class URLtest {
public static void main(String[] args) {
try {
// URL u =new URL("http://www.123.com");
// URL u =new URL("http://www.agaeww123fjaoufoaufoajquroquroqj223453uuiu.com");
URL u =new URL("hello_world://www.nihao.com");
System.out.println(u);
} catch (MalformedURLException e) {
e.printStackTrace();
}
}
}

运行结果:

1
2
3
4
5
java.net.MalformedURLException: no protocol: hello_world://www.nihao.com
at java.net.URL.<init>(URL.java:600)
at java.net.URL.<init>(URL.java:497)
at java.net.URL.<init>(URL.java:446)
at base.net.URLtest.main(URLtest.java:11)

URL文档

https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/net/URL.html#%3Cinit%3E(java.lang.String)

public URL​(String spec)
throws MalformedURLException
Creates a URL object from the String representation.
This constructor is equivalent to a call to the two-argument constructor with a null first argument.
Parameters:
spec - the String to parse as a URL.
Throws:
MalformedURLException - if no protocol is specified, or an unknown protocol is found, or spec is null, or the parsed URL fails to comply with the specific syntax of the associated protocol.
See Also:
URL(java.net.URL, java.lang.String)

考点7:异常基础知识

下面哪些情况可以引发异常:

  • A 数组越界
  • B 指定URL不存在
  • C 使用throw语句抛出
  • D 使用throws语句
显示答案/隐藏答案正确答案: ABC

throws 和 throw:
throws出现在方法头,表示可能会出现异常;
throw是在方法体,抛出了异常,执行throw则一定抛出了某种异常

两者都是消极的异常处理方式,只是抛出或者可能抛出异常,是不会由函数处理,真正的处理异常由它的上层调用处理。

考点8:异常基础知识

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

  • A 异常的继承结构:基类为 Throwable,Error 和 Exception 。实现 Throwable, RuntimeException 和 IOException 等继承 Exception
  • B 非 RuntimeException 一般是外部错误(不考虑Error的情况下),其可以在当前类被 try{}catch 语句块所捕获
  • C Error 类体系描述了 Java 运行系统中的内部错误以及资源耗尽的情形,Error 不需要捕捉
  • D RuntimeException 体系包括错误的类型转换、数组越界访问和试图访问空指针等等,必须 被 try{}catch 语句块所捕获
显示答案/隐藏答案正确答案: ABC

image-20210924162953709

image-20210924163133318

考点9:CMS垃圾收集器

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

  • A 初始标记
  • B 并发标记
  • C 重新标记
  • D 并发清理
显示答案/隐藏答案正确答案: AC

带并发的都是与用户线程一起执行的
这里有一张图片
3.5.6 CMS收集器

考点10:线程基础知识

以下说法错误的是()

  • A 其他选项均不正确
  • B java线程类优先级相同
  • C Thread和Runnable接口没有区别
  • D 如果一个类继承了某个类,只能使用Runnable实现线程
显示答案/隐藏答案正确答案: BCD

Thread和Runable有区别
Thread是一个类,Runable是一个接口。
Runable只有一个run方法,
而Thread除了有run方法,还有从Object继承来的方法,以及Thread中定义的start,sleep等方法。

1
2
3
public class Thread
extends Object
implements Runnable

https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/lang/Thread.html#method.summary
https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/lang/Runnable.html#method.summary

实现线程的方式

  • 继承Thread,然后调用Thread子类的start()方法启动线程
  • 实现Runable接口,然后new Thread(new Runable实现类).start()
  • 实现Callable接口,c=new Callable实现类,f=new FutureTask(c),new Thread(f).start()。然后通过f.get()获得线程的返回值。

考点1:JVM内存镜像命令

运用下列哪个命令能够获取JVM的内存映像

  • A jinfo
  • B jmap
  • C jhat
  • D jstat
显示答案/隐藏答案正确答案: B

1、jps:查看本机java进程信息。
2、jstack:打印线程的信息,制作线程dump文件。
3、jmap:打印内存映射,制作dump文件
4、jstat:性能监控工具
5、jhat:内存分析工具
6、jconsole:简易的可视化控制台
7、jvisualvm:功能强大的控制台

4.2.1 jps:虚拟机进程状况工具
4.2.2 jstat:虚拟机统计信息监视工具
4.2.3 jinfo:Java配置信息工具
4.2.4 jmap:Java内存映像工具
4.2.5 jhat:虚拟机堆转储快照分析工具
4.2.6 jstack:Java堆栈跟踪工具

考点2:自增运算符 自加运算符

有变量int i = 0; int a = i++; int b = ++a; int c = a+b; int d = (a == 1)?b:c; 请问a和d的值分别是多少?( )。

  • A 2,4
  • B 1, 4
  • C 1, 2
  • D 1,1
显示答案/隐藏答案正确答案: D

自加运算

考点3:Spring事务传播特性

下面有关SPRING的事务传播特性,说法错误的是?

  • A PROPAGATION_SUPPORTS:支持当前事务,如果当前没有事务,就以非事务方式执行
  • B PROPAGATION_REQUIRED:支持当前事务,如果当前没有事务,就抛出异常
  • C PROPAGATION_REQUIRES_NEW:新建事务,如果当前存在事务,把当前事务挂起
  • D PROPAGATION_NESTED:支持当前事务,新增Savepoint点,与当前事务同步提交或回滚
显示答案/隐藏答案正确答案: B

Spring的API设计很不错,基本上根据英文翻译就能知道作用:
Required:必须的。说明必须要有事物,没有就新建事物。
supports:支持。说明仅仅是支持事务,没有事务就非事务方式执行。
mandatory:强制的。说明一定要有事务,没有事务就抛出异常。
required_new:必须新建事物。如果当前存在事物就挂起。
not_supported:不支持事物,如果存在事物就挂起。
never:绝不有事务。如果存在事物就抛出异常

事务属性的种类:传播行为、隔离级别、只读和事务超时

a) 传播行为定义了被调用方法的事务边界。

传播行为 意义
PROPERGATION_MANDATORY 表示方法必须运行在一个事务中,如果当前事务不存在,就抛出异常
PROPAGATION_NESTED 表示如果当前事务存在,则方法应该运行在一个嵌套事务中。否则,它看起来和PROPAGATION_REQUIRED看起来没什么俩样
PROPAGATION_NEVER 表示方法不能运行在一个事务中,否则抛出异常
PROPAGATION_NOT_SUPPORTED 表示方法不能运行在一个事务中,如果当前存在一个事务,则该方法将被挂起
PROPAGATION_REQUIRED 表示当前方法必须运行在一个事务中,如果当前存在一个事务,那么该方法运行在这个事务中,否则,将创建一个新的事务
PROPAGATION_REQUIRES_NEW 表示当前方法必须运行在自己的事务中,如果当前存在一个事务,那么这个事务将在该方法运行期间被挂起
PROPAGATION_SUPPORTS 表示当前方法不需要运行在一个是事务中,但如果有一个事务已经存在,该方法也可以运行在这个事务中

b) 隔离级别

在操作数据时可能带来 3 个副作用,分别是脏读、不可重复读、幻读。为了避免这 3 中副作用的发生,在标准的 SQL 语句中定义了 4 种隔离级别,分别是未提交读、已提交读、可重复读、可序列化。而在 spring 事务中提供了 5 种隔离级别来对应在 SQL 中定义的 4 种隔离级别,如下:

隔离级别 意义
ISOLATION_DEFAULT 使用后端数据库默认的隔离级别
ISOLATION_READ_UNCOMMITTED 允许读取未提交的数据(对应未提交读),可能导致脏读、不可重复读、幻读
ISOLATION_READ_COMMITTED 允许在一个事务中读取另一个已经提交的事务中的数据(对应已提交读)。可以避免脏读,但是无法避免不可重复读和幻读
ISOLATION_REPEATABLE_READ 一个事务不可能更新由另一个事务修改但尚未提交(回滚)的数据(对应可重复读)。可以避免脏读和不可重复读,但无法避免幻读
ISOLATION_SERIALIZABLE 这种隔离级别是所有的事务都在一个执行队列中,依次顺序执行,而不是并行(对应可序列化)。可以避免脏读、不可重复读、幻读。但是这种隔离级别效率很低,因此,除非必须,否则不建议使用。

c) 只读

如果在一个事务中所有关于数据库的操作都是只读的,也就是说,这些操作只读取数据库中的数据,而并不更新数据,那么应将事务设为只读模式( READ_ONLY_MARKER ) , 这样更有利于数据库进行优化 。

因为只读的优化措施是事务启动后由数据库实施的,因此,只有将那些具有可能启动新事务的传播行为 (PROPAGATION_NESTED 、 PROPAGATION_REQUIRED 、 PROPAGATION_REQUIRED_NEW) 的方法的事务标记成只读才有意义。

如果使用 Hibernate 作为持久化机制,那么将事务标记为只读后,会将 Hibernate 的 flush 模式设置为 FULSH_NEVER, 以告诉 Hibernate 避免和数据库之间进行不必要的同步,并将所有更新延迟到事务结束。

d) 事务超时

如果一个事务长时间运行,这时为了尽量避免浪费系统资源,应为这个事务设置一个有效时间,使其等待数秒后自动回滚。与设

置“只读”属性一样,事务有效属性也需要给那些具有可能启动新事物的传播行为的方法的事务标记成只读才有意义。

考点4:异常 英语

下面哪个不对?

  • A RuntimeException is the superclass of those exceptions that can be thrown during the normal operation of the Java Virtual Machine.
  • B A method is not required to declare in its throws clause any subclasses of RuntimeExeption that might be thrown during the execution of the method but not caught
  • C An RuntimeException is a subclass of Throwable that indicates serious problems that a reasonable application should not try to catch.
  • D NullPointerException is one kind of RuntimeException
显示答案/隐藏答案正确答案: C

a.虚拟机会自己抛出RuntimeException异常
b.RuntimeException异常不需要声明抛出或者被捕获
c.subclass:子类, RuntimeException不是Throable子类,是Exception的子类
意思:RuntimeException 是Throable并表明他是一个严重的问题,应该合理的被tracatch捕获
d:空指针异常(NullPointException)是 RuntimeException

C选项也是把Error的定义换成了RuntimeException,但这里的”indicates serious problems”不应该用在RuntimeException上,Error才表示严重的错误,RuntimeException并不是.

考点5:Servlet ServeltConfig

ServletConfig接口默认是哪里实现的?

  • A Servlet
  • B GenericServlet
  • C HttpServlet
  • D 用户自定义servlet
显示答案/隐藏答案正确答案: B
1
public interface ServletConfig
1
public abstract class GenericServlet extends Object implements Servlet, ServletConfig, Serializable
1
public abstract class HttpServlet extends GenericServlet

https://docs.oracle.com/javaee/7/api/javax/servlet/GenericServlet.html

image-20211111121601854

考点6:二维数组声明

下面哪几个语句正确的声明一个整型的二维数组()

  • A int a[][]=new int[][]
  • B int b[10][10]=new int[][]
  • C int c[][]=new int[10][10]
  • D int []d[]=new int[10][10]
显示答案/隐藏答案正确答案: CD

定义二维数组

1
2
3
int a[][]=new int [10] [10];
int []a[]=new int [10] [10];
int [][]a=new int [10] [10];

三种方式均可,一维,三维,四维以此类推。

考点7:自动类型转换

针对以下代码,哪些选项执行后是true的:()
class CompareReference{
public static void main(String [] args){
float f=42.0f;
float f1[]=new float[2];
float f2[]=new float[2];
float[] f3=f1;
long x=42;
f1[0]=42.0f;
}
}

  • A f1==f2
  • B x==f1[0]
  • C f1==f3
  • D f2==f1[1]
显示答案/隐藏答案正确答案: BC

自动类型转换按从低到高的顺序转换。不同类型数据间的优先关系如下:

1
2
3
4
低 ---------------------------------------> 高
char

byte→short→int→long→float→double

选项B中,long型会向float型转换,再运算

考点8:java关键字 字面量

(不定项选择题)
如下哪些是 java 中有效的关键字()

  • A native
  • B NULL
  • C false
  • D this
显示答案/隐藏答案正确答案: AD

3.2.3 Java关键字
true、false和null是直接量,而不是

img

考点9:线程局部变量

对于线程局部存储TLS(thread local storage),以下表述正确的是

  • A 解决多线程中的对同一变量的访问冲突的一种技术
  • B TLS会为每一个线程维护一个和该线程绑定的变量的副本
  • C 每一个线程都拥有自己的变量副本,从而也就没有必要对该变量进行同步了
  • D Java平台的java.lang.ThreadLocal是TLS技术的一种实现
显示答案/隐藏答案正确答案: ABD

对于同一全局变量或者静态变量,每个线程访问的是同一变量,多个线程同时访存同一全局变量或者静态变量时会导致冲突,尤其是多个线程同时需要修改这一变量时,通过TLS机制,为每一个使用该全局变量的线程都提供一个变量值的副本,每一个线程均可以独立地改变自己的副本,而不会和其它线程的副本冲突。

线程局部变量(ThreadLocal)的功用其实非常简单,就是为每一个使用该变量的线程都提供一个变量值的副本,使每一个线程都可以独立地改变自己的副本,而不会和其他线程的副本冲突。从线程的角度看,就好像每一个线程都完全拥有该变量一样

每个线程完全拥有自己的ThreadLocal变量,这就是ThreadLocal的用途

http://localhost:4003/JavaReadingNotes/a8a61bd3/

如果是静态变量是共享的话,那必须同步,否则尽管有副本,还是会出错,故C错

考点10:线程安全的Servlet

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

  • A
    1
    2
    3
    4
    5
    6
    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
    11
    12
    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
    6
    7
    8
    9
    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
    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:没有成员(没有共享资源),线程安全;
B:假设存在线程1和线程2,count初始值为0,当线程1执行count++中count+1(此时未写回最终计算值),这时线程2执行count++中读取count,发生数据错误,导致线程1线程2的结果都为1,而不是线程1的结果为1,线程2的结果为2,线程不安全;
C:成员私有,对成员的set get方法都加重量级锁,线程安全;
D:volatile有两个作用:
可见性(volatile变量的改变能使其他线程立即可见,但它不是线程安全的,参考B)和禁止重排序;这里是可见性的应用,类中方法对volatile修饰的变量只有赋值,线程安全;

自定义Servlet时尽量不要定义成员变量,多线程环境下定义的成员变量会成为线程共享变量,导致数据不一致问题

考点1:

有这样一段程序:

1
2
3
4
5
6
7
8
9
10
11
12
13
public class Test{ 
public static void main(String [] args){
List list=new ArrayList();
list.add("a");
list.add("b");
list.add("a");
Set set=new HashSet();
set.add("a");
set.add("b");
set.add("a");
System.out.println(list.size()+","+set.size());
}
}

请问运行主要的程序会打印出的是什么()

  • A 2,2
  • B 2,3
  • C 3,2
  • D 3,3
显示答案/隐藏答案正确答案: C

list有序可重复,set无序不可重复

考点2:

根据下面的程序代码,哪些选项的值返回true?

1
2
3
4
5
6
7
8
9
10
11
12
13
public class Square {  
long width;
public Square(long l) {
width = l;
}
public static void main(String arg[]) {
Square a, b, c;
a = new Square(42L);
b = new Square(42L);
c = b;
long s = 42L;
}
}
  • A a == b
  • B s == a
  • C b == c
  • D a.equals(s)
显示答案/隐藏答案正确答案: C

考点3:

下面代码运行结果是()

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public class Test{    
public int add(int a,int b){
try {
return a+b;
}
catch (Exception e) {
System.out.println("catch语句块");
}
finally{
System.out.println("finally语句块");
}
return 0;
}
public static void main(String argv[]){
Test test =new Test();
System.out.println("和是:"+test.add(9, 34));
}
}
  • A
    1
    2
    catch语句块 
    和是:43
  • B 编译异常
  • C
    1
    2
    finally语句块 
    和是:43
  • D
    1
    2
    和是:43
    finally语句块
显示答案/隐藏答案正确答案: C

考点4:

要导入java/awt/event下面的所有类,叙述正确的是?()

  • A import java.awt.*import java.awt.event.*都可以
  • B 只能是import java.awt.*
  • C 只能是import java.awt.event.*
  • D import java.awt.*import java.awt.event.*都不可以
显示答案/隐藏答案正确答案: C

导包只可以导到当前层,不可以再导入包里面的包中的类

考点5:

以下代码的输出结果是?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public class B
{
public static B t1 = new B();
public static B t2 = new B();
{
System.out.println("构造块");
}
static
{
System.out.println("静态块");
}
public static void main(String[] args)
{
B t = new B();
}
}
  • A 静态块 构造块 构造块 构造块
  • B 构造块 静态块 构造块 构造块
  • C 构造块 构造块 静态块 构造块
  • D 构造块 构造块 构造块 静态块
显示答案/隐藏答案正确答案: C

静态成员最先初始化,静态成员包括,静态成员变量,和静态成员方法。
如果有多个静态成员,按其从上到下定义的顺序,进行初始化。

考点6:

String与StringBuffer的区别是?

  • A String是不可变的对象,StringBuffer是可以再编辑的
  • B 字符串是常量,StringBuffer是变量
  • C String是可变的对象,StringBuffer是不可以再编辑的
  • D 以上说法都不正确
显示答案/隐藏答案正确答案: AB

考点7:

final、finally、finalize三个关键字的区别是()

  • A final是修饰符(关键字)可以修饰类、方法、变量
  • B finally在异常处理的时候使用,提供finally块来执行任何清除操作
  • C finalize是方法名,在垃圾收入集器将对象从内存中清除出去之前做必要的清理工作
  • D finally和finalize一样都是用于异常处理的方法
显示答案/隐藏答案正确答案: ABC

考点8:

对 Map 的用法,正确的有:

  • 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 );
显示答案/隐藏答案正确答案: CD

Map和SortedMap是接口,不能直接new

1
public interface Map<K,​V>
1
public interface SortedMap<K,​V> extends Map<K,​V>
1
public class HashMap<K,​V> extends AbstractMap<K,​V> implements Map<K,​V>, Cloneable, Serializable
1
public class TreeMap<K,​V> extends AbstractMap<K,​V> implements NavigableMap<K,​V>, Cloneable, Serializable

考点9:可以作为switch条件表达式的类型

下面的switch语句中,x可以是哪些类型的数据:()

1
2
3
4
5
switch(x)
{
default:
System.out.println("Hello");
}
  • A long
  • B char
  • C float
  • D byte
  • E double
  • F Object
显示答案/隐藏答案正确答案: BD
  • jdk1.7之前byte,short ,int ,char
  • jdk1.7之后加入String
  • java8,switch支持10种类型:
    • 基本类型:byte char short int
    • 包装类 :Byte,Short,Character,Integer String enum

实际只支持int类型 Java实际只能支持int类型的switch语句,那其他的类型时如何支持的

  • a、基本类型byte char short
    • 原因:这些基本数字类型可自动向上转为int, 实际还是用的int。
  • b、基本类型包装类Byte,Short,Character,Integer
    • 原因:java的自动拆箱机制 可看这些对象自动转为基本类型
  • c、String 类型
    • 原因:实际switch比较的string.hashCode值,它是一个int类型
  • d、enum类型
    • 原因 :实际比较的是enum的ordinal值(表示枚举值的顺序),它也是一个int类型 所以也可以说 switch语句只支持int类型

考点10:

Java是一门支持反射的语言,基于反射为Java提供了丰富的动态性支持,下面关于Java反射的描述,哪些是错误的:( )

  • A Java反射主要涉及的类如Class, Method, Filed,等,他们都在java.lang.reflet包下
  • B 通过反射可以动态的实现一个接口,形成一个新的类,并可以用这个类创建对象,调用对象方法
  • C 通过反射,可以突破Java语言提供的对象成员、类成员的保护机制,访问一般方式不能访问的成员
  • D Java反射机制提供了字节码修改的技术,可以动态的修剪一个类
  • E Java的反射机制会给内存带来额外的开销。例如对永生堆的要求比不通过反射要求的更多
  • F Java反射机制一般会带来效率问题,效率问题主要发生在查找类的方法和字段对象,因此通过缓存需要反射类的字段和方法就能达到与之间调用类的方法和访问类的字段一样的效率
显示答案/隐藏答案正确答案: ADF
1
2
3
java.lang.Class<T>
java.lang.reflect.Method
java.lang.reflect.Field

A Class类在java.lang包
B 动态代理技术可以动态创建一个代理对象,反射不行
C 反射访问私有成员时,Field调用setAccessible可解除访问符限制
D CGLIB实现了字节码修改,反射不行
E 反射会动态创建额外的对象,比如每个成员方法只有一个Method对象作为root,他不胡直接暴露给用户。调用时会返回一个Method的包装类
F 反射带来的效率问题主要是动态解析类,JVM没法对反射代码优化。

考点1:GUI

在委托事件模型中,源生成事件并把它发送给一个或多个监听器,每个监听器必须向事件源注册。

  • A T
  • B F
显示答案/隐藏答案正确答案: A

考点2:快速排序

下面程序的输出结果是什么。

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
public class A2{ 
public static void main(String[] args){
int[] a={2,4,6,8,3,6,9,12};
doSomething(a,0,a.length-1);
for(int i=0;i<=a.length-1;i++)
System.out.print(a[i]+" ");
}
private static void doSomething(int[] a,int start,int end){
if(start<end){
int p=core(a,start,end);
doSomething(a,start,p-1);
doSomething(a,p+1,end);
}
}
private static int core(int[] a,int start,int end)
{
int x=a[end];
int i=start;
for(int j=start;j<=end-1;j++){
if(a[j]>=x){
swap(a,i,j);
i++;
}
}
swap(a,i,end);
return i;
}

private static void swap(int[] a,int i,int j)
{
int tmp=a[i];
a[i]=a[j];
a[j]=tmp;
}
}
  • A 找到最大值
  • B 找到最小值
  • C 从大到小的排序
  • D 从小到大的排序
显示答案/隐藏答案正确答案: C

这道题目的核心思想是:根据交换的次数,决定存储的位置,交换0次,存在第一位,代表最大,交换1次,存在第二位,代表次大,以此类推…..结果可以拿一个有序的递增序列进行验证,这样比较直观,而且简单粗暴

快速排序,比较经常使用的方式可以参照下面两个网址。
介绍:http://blog.csdn.net/morewindows/article/details/6684558
演示:http://www.tyut.edu.cn/kecheng1/site01/suanfayanshi/quick_sort.asp

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
//看我的注释这种快排的思路就很清晰了,这是只从一个方向遍历的快排
public class A2 {
public static void main(String[] args) {
int[] a = { 2, 4, 6, 8, 3, 6, 9, 12 };
quickSort(a, 0, a.length - 1);
for (int i = 0; i <= a.length - 1; i++)
System.out.print(a[i] + " ");
}
private static void quickSort(int[] a, int start, int end) {
if (start < end) {
int p = core(a, start, end);
quickSort(a, start, p - 1);
quickSort(a, p + 1, end);
}
}
private static int core(int[] a, int start, int end) {
int x = a[end];
//记录遍历完后最后一个数应该放在的位置,初始就是start,因为如果前面没有数比最后一个数大,那么下面遍历完后最后一个数就应该放在start的位置
int i = start;
//遍历的目的是把参与排序的这轮数中比最后一个数大的数都放到最后一个数前面
for (int j = start; j <= end - 1; j++) {
if (a[j] &gt;= x) {
swap(a, i, j);
//每遇到一个比最后一个数大的数,最后一个数应该放的位置就+1
i++;
}
}
//这里一交换后就把最后一个数放在了正确的位置,这样左边的数都比最后一个数大,右边的数都比最后一个数小
swap(a, i, end);
return i;
}
private static void swap(int[] a, int i, int j) {
int tmp = a[i];
a[i] = a[j];
a[j] = tmp;
}
}

是快速排序的另一种实现。严蔚敏的教材上是选择第一个元素作为中枢,从两侧向中间扫描逼近,最后确定枢轴应该在的位置;而上面这种解法则是算法导论上的,选择最后一个元素作为枢轴,然后单侧扫描逼近,最后确定枢轴应该在的位置(根据用变量i记录的交换的次数决定最后一个元素是第i大,然后把它放在第i个位置)。每次确定枢轴应该在的位置这一点是相同的,不同的是确定枢轴位置的过程。

考点3:JVM参数配置

假如某个JAVA进程的JVM参数配置如下:

1
-Xms1G -Xmx2G -Xmn500M -XX:MaxPermSize=64M -XX:+UseConcMarkSweepGC -XX:SurvivorRatio=3,

请问eden区最终分配的大小是多少?

  • A 64M
  • B 500M
  • C 300M
  • D 100M
显示答案/隐藏答案正确答案: C

这是网易2016年在线笔试题中的一道选择题。
先分析一下里面各个参数的含义:
-Xms:1G , 就是说初始堆大小为1G
-Xmx:2G , 就是说最大堆大小为2G
-Xmn:500M ,就是说年轻代大小是500M(包括一个Eden和两个Survivor)
-XX:MaxPermSize:64M , 就是说设置持久代最大值为64M
-XX:+UseConcMarkSweepGC , 就是说使用使用CMS内存收集算法
-XX:SurvivorRatio=3 , 就是说Eden区与Survivor区的大小比值为3:1:1
题目中所问的Eden区的大小是指年轻代的大小,直接根据-Xmn:500M和-XX:SurvivorRatio=3可以直接计算得出
500M*(3/(3+1+1))
=500M(3/5)
=500M
0.6
=300M
所以Eden区域的大小为300M。

Xms 起始内存
Xmx 最大内存
Xmn 新生代内存
Xss 栈大小。 就是创建线程后,分配给每一个线程的内存大小
-XX:NewRatio=n:设置年轻代和年老代的比值。如:为3,表示年轻代与年老代比值为1:3,年轻代占整个年轻代年老代和的1/4
-XX:SurvivorRatio=n:年轻代中Eden区与两个Survivor区的比值。注意Survivor区有两个。如:3,表示Eden:Survivor=3:2,一个Survivor区占整个年轻代的1/5
-XX:MaxPermSize=n:设置持久代大小
收集器设置
-XX:+UseSerialGC:设置串行收集器
-XX:+UseParallelGC:设置并行收集器
-XX:+UseParalledlOldGC:设置并行年老代收集器
-XX:+UseConcMarkSweepGC:设置并发收集器
垃圾回收统计信息
-XX:+PrintGC
-XX:+PrintGCDetails
-XX:+PrintGCTimeStamps
-Xloggc:filename
并行收集器设置
-XX:ParallelGCThreads=n:设置并行收集器收集时使用的CPU数。并行收集线程数。
-XX:MaxGCPauseMillis=n:设置并行收集最大暂停时间
-XX:GCTimeRatio=n:设置垃圾回收时间占程序运行时间的百分比。公式为1/(1+n)
并发收集器设置
-XX:+CMSIncrementalMode:设置为增量模式。适用于单CPU情况。
-XX:ParallelGCThreads=n:设置并发收集器年轻代收集方式为并行收集时,使用的CPU数。并行收集线程数。

考点4:泛型无法提升性能

在开发中使用泛型取代非泛型的数据类型(比如用ArrayList取代ArrayList),程序的运行时性能会变得更好。()

  • A 正确
  • B 错误
显示答案/隐藏答案正确答案: B

使用泛型的好处

1,类型安全。 泛型的主要目标是提高 Java 程序的类型安全。通过知道使用泛型定义的变量的类型限制,编译器可以在一个高得多的程度上验证类型假设。没有泛型,这些假设就只存在于程序员的头脑中(或者如果幸运的话,还存在于代码注释中)。

2,消除强制类型转换。 泛型的一个附带好处是,消除源代码中的许多强制类型转换。这使得代码更加可读,并且减少了出错机会。

3,潜在的性能收益。 泛型为较大的优化带来可能。在泛型的初始实现中,编译器将强制类型转换(没有泛型的话,程序员会指定这些强制类型转换)插入生成的字节码中。但是更多类型信息可用于编译器这一事实,为未来版本的 JVM 的优化带来可能。由于泛型的实现方式,支持泛型(几乎)不需要 JVM 或类文件更改。所有工作都在编译器中完成,编译器生成类似于没有泛型(和强制类型转换)时所写的代码,只是更能确保类型安全而已。

所以泛型只是提高了数据传输安全性,并没有改变程序运行的性能

考点5:正则表达式

以下代码将打印出

1
2
3
4
public static void main (String[] args) { 
String classFile = "com.jd.".replaceAll(".", "/") + "MyClass.class";
System.out.println(classFile);
}
  • A com. jd
  • B com/jd/MyClass.class
  • C ///////MyClass.class
  • D com.jd.MyClass
显示答案/隐藏答案正确答案: C

C。由于replaceAll方法的第一个参数是一个正则表达式,而”.“在正则表达式中表示任何字符,所以会把前面字符串的所有字符都替换成”/“。如果想替换的只是”.“,那么久要写成”\\.“。

考点6:自动类型提升

代码片段:

1
2
3
4
5
byte b1=1,b2=2,b3,b6;  
final byte b4=4,b5=6;
b6=b4+b5;
b3=(b1+b2);
System.out.println(b3+b6);

关于上面代码片段叙述正确的是()

  • A 输出结果:13
  • B 语句:b6=b4+b5编译出错
  • C 语句:b3=b1+b2编译出错
  • D 运行期抛出异常
显示答案/隐藏答案正确答案: C

byte,short,char计算时自动提升为int

被final修饰的变量是常量,这里的b6=b4+b5可以看成是b6=10;在编译时就已经变为b6=10

而b1和b2是byte类型,java中进行计算时候将他们提升为int类型,再进行计算,b1+b2计算后已经是int类型,赋值给b3,b3是byte类型,类型不匹配,编译不会通过,需要进行强制转换。

Java中的byte,short,char进行计算时都会提升为int类型。
这里有一张图片

考点7:排序算法对比

在各自最优条件下,对N个数进行排序,哪个算法复杂度最低的是? ()

  • A 插入排序
  • B 快速排序
  • C 堆排序
  • D 归并排序
显示答案/隐藏答案正确答案: A

img

img

考点8:反射机制能实现的功能

JAVA反射机制主要提供了以下哪些功能?

  • A 在运行时判断一个对象所属的类
  • B 在运行时构造一个类的对象
  • C 在运行时判断一个类所具有的成员变量和方法
  • D 在运行时调用一个对象的方法
显示答案/隐藏答案正确答案: ABCD

考点9:会话跟踪实现技术

下面哪项技术可以用在WEB开发中实现会话跟踪实现?

  • A session
  • B Cookie
  • C 地址重写
  • D 隐藏域
显示答案/隐藏答案正确答案: ABCD

考点10:

character流和byte流的区别不包括()

  • A 每次读入的字节数不同
  • B 前者带有缓冲,后者没有。
  • C 前者是字符读入,后者是字节读入。
  • D 二者没有区别,可以互换。
显示答案/隐藏答案正确答案: ABD

NC110 旋转数组

描述

一个数组A中存有 n 个整数,在不允许使用另外数组的前提下,将每个整数循环向右移 $M$( $M>=0$)个位置,即将A中的数据由
$$
A_0 , A_1, \cdots , A_{N-1}
$$

变换为
$$
A_{N-M},\cdots,A_{N-1},A_0,A_1,\cdots ,A_{N-M-1}
$$

(最后 M 个数循环移至最前面的 M 个位置)。如果需要考虑程序移动数据的次数尽量少,要如何设计移动的方法?

数据范围:$0<n \leq 10$,$0 \leq m \leq 1000$
进阶:空间复杂度 $O(1)$,时间复杂度 $O(n)$

示例1

输入:

1
6,2,[1,2,3,4,5,6]

返回值:

1
[5,6,1,2,3,4]

示例2

输入:

1
4,0,[1,2,3,4]

返回值:

1
[1,2,3,4]

备注:

1
(1<=N<=100,M>=0)

我的题解

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
import java.util.*;

public class Solution {
/**
* 旋转数组
* @param n int整型 数组长度
* @param m int整型 右移距离
* @param a int整型一维数组 给定数组
* @return int整型一维数组
*/
public int[] solve (int n, int m, int[] a) {
int temp;
// 每次循环可以把数组最后一个元素循环移动到数组的第一个元素
// 循环m次即可把数组循环右移m个位置
for (int j = 0; j < m; j++) {
// 缓存最后一个元素
temp = a[a.length - 1];
// 从后向前遍历
for (int i = a.length - 1; i > 0; i--) {
// 把前一格元素移动到后一格
a[i] = a[i - 1];
}
// 把最后一个元素放到第一格
a[0] = temp;
}
return a;
}
}

根据题目可以值n就是数组的长度,所以可以把上面的a.length替换成n:

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
import java.util.*;

public class Solution {
/**
* 旋转数组
* @param n int整型 数组长度
* @param m int整型 右移距离
* @param a int整型一维数组 给定数组
* @return int整型一维数组
*/
public int[] solve (int n, int m, int[] a) {
int temp;
for (int j = 0; j < m; j++) {
// 缓存最后一个元素
temp = a[n - 1];
// 从后向前遍历
for (int i = n - 1; i > 0; i--) {
// 把前一格元素移动到后一格
a[i] = a[i - 1];
}
// 把最后一个元素放到第一格
a[0] = temp;
}
return a;
}
}

大神题解

三次翻转
假设 n=7且 k=3

描述 数组状态
原始数组 1 2 3 4 5 6 7
反转所有数字后 7 6 5 4 3 2 1
反转前 k=3 个数字后 5 6 7_4 3 2 1
反转后 n-k=4 个数字后 5 6 7_1 2 3 4 –> 结果
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
import java.util.*;
public class Solution {
public int[] solve (int n, int m, int[] a) {
int k=m%n;
reverse(a,0,n-1);
reverse(a,0,k-1);
reverse(a,k,n-1);
return a;
}

public void reverse(int[] a,int start,int end){
while (start<end){
int temp=a[start];
a[start]=a[end];
a[end]=temp;
start++;
end--;
}
}
}

数组翻转

链接:https://www.nowcoder.com/questionTerminal/e19927a8fd5d477794dac67096862042?answerType=1&f=discussion
来源:牛客网

解题思路:

该方法基于如下的事实:将数组的元素向右移动 k 次后,尾部 m mod n 个元素会移动至数组头部,其余元素向后移动 m mod n 个位置。
该方法为数组的翻转:翻转算法参考 反转链表中的双指针方法 https://blog.nowcoder.net/n/d259b250747b4085bc7975f102d248c4

1、可以先将所有元素翻转,这样尾部的 m mod n 个元素就被移至数组头部,

2、然后再翻转 [0,m mod n−1] 区间的元素

3、 最后翻转[m mod n,n−1] 区间的元素即能得到最后的答案。

实例:
以 n=7,m=3 为例进行如下展示:

操作 结果
原始数据 【1,2,3,4,5,6,7】
翻转所有元素 【7,6,5,4,3,2,1】
翻转 [0,m mod n −1] 区间的元素 【5,6,7,4,3,2,1】
翻转 [m mod n, n −1] 区间的元素 【5,6,7,1,2,3,4】

最后返回:【5,6,7,1,2,3,4】

复杂度分析

时间复杂度:O(N),其中 N 为数组的长度。每个元素被翻转两次,一共 N 个元素,因此总时间复杂度为 O(2N)=O(N)。
空间复杂度:O(1)。使用常数级空间变量