2021年09月05日 java1
考点1:子类能访问父类的那些成员
C#、JAVA)扩展方法能访问被扩展对象的public成员
- A 能
- B 不能
解析
显示答案/隐藏答案
正确答案: A翻译一下,子类方法是否能够访问父类中的public成员。
考点2:构造方法
以下有关构造方法的说法,正确的是:()
- A 一个类的构造方法可以有多个
- B 构造方法在类定义时被调用
- C 构造方法只能由对象中的其他方法调用
- D 构造方法可以和类同名,也可以和类名不同
解析
显示答案/隐藏答案
正确答案: AA 一个类有多个构造方法便是重载的表现。重载参数列表不同。所以A是正确的。
B 构造方法是在对象创建时就被调用,用于初始化。
C 构造方法是给与之对应的对象进行初始化,初始化的动作只执行一次。
D 构造方法必须与所在类的名称同名。
B、构造器在对象被实例化的时候调用
C、构造方法不能由对象中的其他方法调用。都是new出来或者利用了反射。
D、构造方法必须与类同名,且没有返回值(不同于void)。
考点3:线程执行体run() 启动线程start()
以下哪个方法用于定义线程的执行体?
- A
start()
- B
init()
- C
run()
- D
synchronized()
解析
显示答案/隐藏答案
正确答案: Crun()用于定义线程执行体,
start()用于启动线程
考点4:重载
对于同一类中的两个方法 , 在判断它们是不是重载方法时 , 肯定不考虑( )
- A 参数个数
- B 参数类型
- C 返回值类型
- D 参数顺序
解析
显示答案/隐藏答案
正确答案: C方法重写的注意事项:
构造方法不能被重写,不要问为什么?因为构造方法名必须和类名相同
private修饰的成员方法不能被重写
static修饰的方法不能被重写
final修饰的方法不能被重写
当子类重写了父类中的方法后,子类对象调用该方法时调用的是子类重写后的方法
子类的实例方法不能重写父类的静态方法
1 | package extendstest; |
子类的staticMethod方法报错如下:
Multiple markers at this line - This instance method cannot override the static method from Father - overrides extendstest.Father.canYouSeeStatic - The method canYouSeeStatic() of type Son must override or implement a supertype method
意思是子类的实例方法不能重写父类的静态方法
给子类中的staticMethod加上static修饰符:
// 子类无法重写父类的static方法 @Override public static void staticMethod() { System.out.println("Static method in parent class"); }
还是不可以重写,报错如下:
The method staticMethod() of type Son must override or implement a supertype method
子类的finalMethod方法报错如下:
Multiple markers at this line - Cannot override the final method from Parent - overrides extendstest.Parent.finalMethod
可以定义与父类同名的Static方法
去掉子类的staticMethod()方法上面的@Override
,则不会报错。
这不是重写,无法实现多态。
1 | package extendstest; |
运行效果:
1 | Static method in parent class |
重写描述的是子类实例方法和父类实例方法的关系
static定义的方法时类方法,通过类名调用。
上面的parent.staticMethod();
调用实际上还是类名.staticMethod();
也就是Parent.staticMethod();
.所以不会去调用Son类中的同名方法。
如果非要调用子类的同名静态方法的话,需要改成:Son.staticMethod()
。
static方法如何实现”多态”
使用子类来调用覆盖的static方法,如果子类中有该静态方法,则执行子类的静态方法。
如果子类没有该静态方法,则去父类中查找静态方法,如果有则执行父类的静态方法:
1 | package extendstest; |
运行效果:
1 | Static method in parent class |
此时Son类中重写了父类的静态方法,调用的是重写后的。
如果把Son类中的staticMethod方法注释掉。:
1 | package extendstest; |
运行效果:
1 | Static method in parent class |
可以看到,此时调用了从父类继承得到的静态方法。
static方法可以被继承 可以被覆盖 不能被重写
重写,说的是根据运行时
的对象类型来决定调用哪个方法,而不是编译时类型。
因为无法使用@Override
修饰,所以不是重写。
对于静态方法,我们不应该尝试去重写,而且调用时应该以类进行调用,而不是对象进行调用。
问 static方法可以被重写吗?
答,static方法可以被子类继承,子类可以覆盖继承到的static方法。但是这不叫重写。
因为如果你在同名的static方法上写上@Override注解,编译器会报错。
重写是为了实现多态,多态是在运行的时候根据对象的类型来调用方法的。
如果使用了静态方法,那么在编译期间,就知道调用的是那个静态方法了,这不符合多态的定义。
https://www.jianshu.com/p/df43f5500ea3
静态方法从程序开始运行后就已经分配了内存,也就是说已经写死了。所有引用到该方法的对象(父类的对象也好子类的对象也好)所指向的都是同一块内存中的数据,也就是该静态方法。子类中如果定义了相同名称的静态方法,并不会重写,而应该是在内存中又分配了一块给子类的静态方法,没有重写这一说。
考点5:不懂的点:JVM
off-heap是指那种内存()
- A
JVM GC
能管理的内存 - B
JVM
进程管理的内存 - C 在
JVM
老年代内存区 - D 在
JVM
新生代内存
解析
显示答案/隐藏答案
正确答案: B堆外内存
off-heap叫做堆外内存,将你的对象从堆中脱离出来序列化,然后存储在一大块内存中,这就像它存储到磁盘上一样,但它仍然在RAM中。
对象在这种状态下不能直接使用,它们必须首先反序列化,也不受垃圾收集。
序列化和反序列化将会影响部分性能(所以可以考虑使用FST-serialization)使用堆外内存能够降低GC导致的暂停。
堆外内存不受垃圾收集器管理,也不属于老年代,新生代。
堆外内存意味着把内存对象分配在Java虚拟机的堆以外的内存,这些内存直接受操作系统管理(而不是虚拟机)。不属于老年代和新生代。
JVM GC回收堆和方法区,排除法选择 B
这样做的结果就是能保持一个较小的堆,以减少垃圾收集对应用的影响。
使用堆外内存能够降低GC导致的暂停。
堆外内存,它和内存池一样,也能缩短垃圾回收时间,但是它适用的对象和内存池完全相反。
内存池往往适用于生命期较短的可变对象,而生命期中等或较长的对象,正是堆外内存要解决的。
堆外内存的特点
https://blog.csdn.net/universe_ant/article/details/52145450
堆外内存有以下特点:
- 对于大内存有良好的伸缩性
- 对垃圾回收停顿的改善可以明显感觉到
- 在进程间可以共享,减少虚拟机间的复制
当然堆外内存也有它自己的问题,
- 最大的问题就是你的数据结构变得不那么直观,如果数据结构比较复杂,就要对它进行串行化(serialization),而串行化本身也会影响性能。
- 另一个问题是由于你可以使用更大的内存,你可能开始担心虚拟内存(即硬盘)的速度对你的影响了。
1)程序计数器
几乎不占有内存。用于取下一条执行的指令。
2)堆
所有通过new创建的对象的内存都在堆中分配,其大小可以通过-Xmx和-Xms来控制。
堆被划分为新生代和旧生代,
新生代又被进一步划分为Eden和Survivor区,最后Survivor由FromSpace和ToSpace组成,结构图如下所示:
新生代。新建的对象都是用新生代分配内存,Eden空间不足的时候,会把存活的对象转移到Survivor中,新生代大小可以由-Xmn来控制,也可以用-XX:SurvivorRatio来控制Eden和Survivor的比例旧生代。用于存放新生代中经过多次垃圾回收仍然存活的对象。
3)栈
每个线程执行每个方法的时候都会在栈中申请一个栈帧,每个栈帧包括局部变量区和操作数栈,用于存放此次方法调用过程中的临时变量、参数和中间结果。
4)本地方法栈
用于支持native方法的执行,存储了每个native方法调用的状态
5)方法区
存放了要加载的类信息、静态变量、final类型的常量、属性和方法信息。
JVM用永久代(PermanetGeneration)来存放方法区,(在JDK的HotSpot虚拟机中,可以认为方法区就是永久代,但是在其他类型的虚拟机中,没有永久代的概念,有关信息可以看周志明的书)可通过-XX:PermSize和-XX:MaxPermSize来指定最小值和最大值。
考点6:异常处理机制
java关于异常处理机制的叙述哪些正确
- A
catch
部分捕捉到异常情况时,才会执行finally
部分 - B 当
try
区段的程序发生异常时,才会执行catch
区段的程序 - C 在
try
区段不论程序是否发生异常及捕获到异常,都会执行finally
部分 - D 以上都是
解析
显示答案/隐藏答案
正确答案: BCfinally不执行情况
try块执行时,finally表示总是执行。但是
- 在try中调用System.exit(0),强制退出了程序,finally块不执行。
- 在进入try块前,出现了异常,此时try没有执行,finally块不执行。
考点7:面向对象三大特性
面向对象的程序设计语言具有()等共同特性。
- A 封装性
- B 多态性
- C 简单性
- D 复杂性
- E 继承性
解析
显示答案/隐藏答案
正确答案: ABE面向对象OOP三大特性:
- 继承
- 封装
- 多态
准确来说,基于对象和面向对象是有区别的。
基于对象是封装和继承。
面向对象是封装、继承和多态。
详见 https://blog.csdn.net/jiaruitao777/article/details/99098027
考点8:IO流 字符流字节流
下面哪个流类不属于面向字符的流()
- A
BufferedWriter
- B
FileInputStream
- C
ObjectInputStream
- D
InputStreamReader
解析
显示答案/隐藏答案
正确答案: BC既然是字符流,那么一般是reader和writer结尾。
Stream结尾的是字节,Reader结尾的是字符
面向字符的输入流类都是Reader的子类,
面向字符的输出流都是类 Writer 的子类
考点9:堆存放对象 栈存放程序
程序中常采用变量表示数据,变量具有名、地址、值、作用域、生存期等属性。关于变量的叙述,()是正确的。
- A 根据作用域规则,在函数中定义的变量只能在函数中引用
- B 在函数中定义的变量,其生存期为整个程序执行期间
- C 在函数中定义的变量不能与其所在函数的形参同名
- D 在函数中定义的变量,其存储单元在内存的栈区
解析
显示答案/隐藏答案
正确答案: ACD这里主要说明D为什么是对的
首先说明栈内存和堆内存里存放的是什么
- 栈内存中存放函数中定义的一些基本类型的变量和对象的引用变量;
- 堆内存中存放new创建的对象和数组。
简单的来说,堆主要是用来存放对象的,栈主要是用来执行程序的
这么做是因为
- 栈的存取速度快,栈数据可以共享,但是栈中的数据大小和生存期必须确定,缺乏灵活性中存放一些基本类型的对象和对象句柄
- 堆是操作系统分配给自己内存,由于从操作系统管理的内存分配,所以再分配和销毁时都需要占用时间,因此用堆的效率非常低,但是优点在于编译器不需要指导从堆里分配多少存储控件,也不需要知道存储的数据要再堆里停留多长事件,因此用堆保存数据时会得到更大的灵活性
参考链接:https://blog.csdn.net/wangbo1998/article/details/80379016
D选项不太严谨,如果定义的是引用类型变量,且没有通过逃逸分析,则可能会被分配到堆中,逃逸分析是jdk1.8默认开启的
D选项我给大家说明一下,我觉得题出的不严谨,如果方法中有引用类型的变量,那么存储是在堆中,引用在栈中
考点10:身份证号的正则表达式
多选题
关于身份证号,以下正确的正则表达式为( )
- A
isIDCard=/^[1-9]\d{7}((0\d)|(1[0-2]))(([0|1|2]\d)|3[0-1])\d{3}$/;
- B
isIDCard=/^[1-9]\d{7}((9\d)|(1[0-2]))(([0|1|2]\d)|3[9-1])\d{3}$/;
- C
isIDCard=/^[1-9]\d{5}[1-9]\d{3}((0\d)|(1[0-2]))(([0|1|2]\d)|3[0-1])\d{4}$/;
- D
isIDCard=/^[1-9]\d{5}[1-9]\d{3}((9\d)|(1[9-2]))(([0|1|2]\d)|3[9-1])\d{4}$/;
解析
显示答案/隐藏答案
正确答案: AC身份证构成
15位身份证的构成:六位出生地区码+六位出身日期码+三位顺序码
18位身份证的构成:六位出生地区码+八位出生日期码+三位顺序码+一位校验码
A选项
^[1-9]\d{7}((0\d)|(1[0-2]))(([0|1|2]\d)|3[0-1])\d{3}$
[1-9]\d{7}
,有8位,其中前六位是地址码,后两位是年份,00~99年。((0\d)|(1[0-2]))
,有两位,表示月份,第一个括号范围位0009,第二个括号的范围位1012,综合得到00~12,符合月份的定义。(([0|1|2]\d)|3[0-1])
,有两位,表示日期,第一个括号的范围位0009或者1019或者2029,第2个括号的范围位3031,综合得到00~31,符合月份的定义。这个其实也不严谨,例如2月份,只有28天,或29天。\d{3}
有三位,表示顺序码
B选项
^[1-9]\d{7}((9\d)|(1[0-2]))(([0|1|2]\d)|3[9-1])\d{3}$
[1-9]\d{7}
,有8位,其中前六位是地址码,后两位是年份,00~99年。((9\d)|(1[0-2]))
,有两位,表示月份,第一个括号的范围位90~99,一年只有12个月份,没有90月份,更没有99月份,B选项排除。
C选项的
^[1-9]\d{5}[1-9]\d{3}((0\d)|(1[0-2]))(([0|1|2]\d)|3[0-1])\d{4}$
[1-9]\d{5}
这六位,表示六位出生地码,- ^[1-9]\d{5}[1-9]\d{3}((0\d)|(1[0-2]))(([0|1|2]\d)|3[0-1])\d{4}$
[1-9]\d{3}
这四位,表示年- ^[1-9]\d{5}[1-9]\d{3}((0\d)|(1[0-2]))(([0|1|2]\d)|3[0-1])\d{4}$
((0\d)|(1[0-2]))
这两位表示,月份,从第一个括号匹配00~09
。第二个括号匹配10~12
。- ^[1-9]\d{5}[1-9]\d{3}((0\d)|(1[0-2]))(([0|1|2]\d)|3[0-1])\d{4}$
- 所以月份共计匹配范围:
00~12
符合月份00~12的定义。
(([0|1|2]\d)|3[0-1])
这两位表示日期,第一个括号匹配0009,1019,2029。第二个括号匹配3031。- ^[1-9]\d{5}[1-9]\d{3}((0\d)|(1[0-2]))(([0|1|2]\d)|3[0-1])\d{4}$
- 所以日期总计匹配范围:00~31,符合日期的定义。
\d{4}
,表示匹配三位顺序吗+一位校验码。校验码有字母,这里显然不能完全匹配,勉强认为校验码都是数字吧。- ^[1-9]\d{5}[1-9]\d{3}((0\d)|(1[0-2]))(([0|1|2]\d)|3[0-1])\d{4}$
D选项
^[1-9]\d{5}[1-9]\d{3}((9\d)|(1[9-2]))(([0|1|2]\d)|3[9-1])\d{4}$
[1-9]\d{5}
,六位地址码[1-9]\d{3}
,四位年,1000~9999((9\d)|(1[9-2]))
,表示月份,9\d
的范围位90~99
,一年最多有12个月,没有90个月,更没有99个月。所以D选项错误。