admin管理员组文章数量:1579953
二【读程序题】(2分 x 10)
21如下程序打印的结果是什么呢?
(注:答案包括编译失败 或运行异常。请说明结果的同时注明原因,下面同上)
String str1 = "hello";
String str2 = “he”;
System.out.println(str1pareTo(str2));
解答:
输出3。
按照String类compareTo的源码,这两个字符串比较的结果应该是str1.length() - str2.length()的结果
22. 如果在同包的某个main方法中运行Father father = new Son(1000),程序的输出结果是什么?
Father和Son定义如下
class Father {
int i = 10;
public Father() {
System.out.println(getI());
}
public int getI() {
return i;
}
}
class Son extends Father {
int i = 100;
public Son(int i) {
this.i = i;
}
public int getI() {
return i;
}
}
解答:
打印结果为0。
父类方法被子类覆盖,即使在父类中调用,调用到的也是子类方法,而此时父类对象还在初始化过程中,子类对象更是还未开始初始化,其成员变量的值还是默认值。
23.如下程序打印的结果是什么呢?
public class InTheLoop {
public static final int END = Integer.MAX_VALUE;
public static final int START = END - 100;
public static void main(String[] args) {
int count = 0;
for (int i = START; i <= END; i++)
count++;
System.out.println(count);
}
}
解答:
程序无限循环
i的值从Integer.MAX_VALUE-100开始,每次自增1,直到Integer.MAX_VALUE
然后继续自增1变成了Integer.MIN_VALUE(溢出),接着继续自增
直到Integer.MAX_VALUE,并重复。
所以打印的值count,从1开始一直到Integer.MAX_VALUE
然后从Integer.MIN_VALUE到Integer.MAX_VALUE
如此周而复始的打印
24. 如下程序打印的结果是什么呢?
public class AnimalFarm{
public static void main(String[] args){
final String pig = "length: 10";
final String dog = "length: " + pig.length();
System.out. println("Animals are equal: " + pig == dog);
}
}
解答:
false
先拼接"Animals are equal: " + pig得到新的字符串,然后再比较==
25. 如下程序打印的结果是什么呢?
public class Bark {
public static void main(String args[]) {
Dog woofer = new Dog();
Dog nipper = new Basenji();
woofer.bark();
nipper.bark();
}
}
class Dog {
public static void bark() {
System.out.print("woof ");
}
}
class Basenji extends Dog {
public static void bark() {
}
}
解答:
woof woof
静态方法不能被覆盖,所以两次方法调用实际上调用的都是父类,Dog类中定义的静态方法,所以输出两次woof
26. 如下程序打印的结果是什么呢?
public class Indecisive {
public static void main(String[] args) {
System.out.println(decision());
}
static boolean decision() {
try {
return true;
} finally {
return false;
}
}
}
解答:
False
a. 执行第一条return语句的时候,首先将待返回的结果,复制到该方法栈帧中的一个特殊位置。
b. 紧接着,执行finally代码块中的return语句,又将该return语句待返回的值,放到栈帧中,用来存放方法返回值的那个特殊位置(将第一个return语句存放的待返回结果覆盖掉)
c. 然后继续执行第二个return语句,结束方法执行,带着存储在栈帧中特殊位置的那个返回值,返回到方法调用处
27. 如下程序打印的结果是什么呢?
public class Test{
public static void main(String[]args) {
int[]x={0,1,2,3};
for(int i=0;i<3;i+=2) {
try{
system.out.println(x[i+2]/x[i]+x[i+1]);
}catch(ArithmeticException e){
System.out.println("errorl");
}catch(Exception e){
System.out.println("error2");
}
}
}
}
解答:
error1
error2
a. 当i值为0时,执行第一次for循环,此时try块中输出语句中输出的计算表达式是在 求 2 / 0 + 1,很显然,发生除0异常,输出error1
b. 紧接着执行第二次循环,此时i值为2,try块的输出语句中计算的是 x[4] / x[2] + x[3], 此时x[4]数组越界,于是输出error2
28. 如下程序打印的结果是什么呢?
public class TestMain {
static {
System.out.println("C");
}
{
System.out.println("B");
}
public TestMain(){
System.out.println("A");
}
public static void main(String[] args) {
TestMain testMain = new TestMain();
}
}
解答:
C
B
A
静态代码块先于构造代码块,构造代码块先于构造方法
29. 如下程序打印的结果是什么呢?
public class Bground extends Thread{
public static void main(String[] args){
Bground bground=new Bground();
bground.run();
}
public void start(){
for (int i = 0; i < 10; i++) {
System.out.println("B ground.start()"+i);
}
}
}
解答:
正常结束没有任何输出
a. 因为在Thread子类中,没有覆盖父类的run方法,而是覆盖了父类的start()方法
b. 所以,在Thread子类对象上调用的run方法,实际是Thread类中定义的run方法
而根据Thread类的run方法源码,什么都不会输出
30. 如下程序打印的结果是什么呢?
public class Reluctant {
private Reluctant internalInstance = new Reluctant();
public Reluctant() throws Exception {
throw new Exception("I'm not coming out");
}
public static void main(String[] args) {
try {
Reluctant b = new Reluctant();
System.out.println("Surprise!");
} catch (Exception ex) {
System.out.println("I told you so");
}
}
}
解答:
Stackoverflow error
a. 首先,执行main方法中的创建对象的语句Reluctant b = new Reluctant();
b. 但是,在创建对象的过程中,会执行成员变量的初始化语句
private Reluctant internalInstance = new Reluctant();
于是又会创建Reluctant对象,于是又执行a,a执行完了,又执行b... 如此周而复始
c. 于是,就出现了一个递归。
三【简答题】(2分 x 10)
31. 引用类型和基本数据类型有何区别?
解答:
基本数据类型包括:byte,short,char, int,long,float,double,boolean
引用数据类型主要包括:类,接口等
基本数据类型的变量存储的是该类型变量的值,而引用数据类型的变量存储的是地址(比如堆中对象的地址)
32. java中父类中定义的哪些方法没有多态效果,为什么?
解答:多态发生的条件是
1)继承
2)方法覆盖
3)父类引用指向子类实例
所以哪些方法(行为),实现不了多态效果——不能在子类中被覆盖的方法
a. 父类中的private方法(不能被子类覆盖)
b. 父类中的构造方法(不能被子类继承)
c. 父类中的静态方法(不能被子类覆盖)
d. 父类中被final修饰的方法(不能被子类覆盖)
33. 如何理解静态上下文无法访问非静态的成员变量和成员方法?
解答:
静态上下文不能访问非静态的成员变量或成员方法其实是指
在静态上下文中,无法访问,当前对象this的成员变量;
或在当前对象this上调用其非静态的成员方法。
因为对于静态上下文而言,静态的东西都是不依赖于对象而存在,所以当静态上下文被访问的时候,当前对象可能并不存在,所以自然无法访问。
34. 方法重载和方法重写的区别。
解答:
重载是指在同一个类中定义同名方法,而这些方法名称相同,但方法签名不同。方法重写,是指在子类中,修改父类中定义的方法的实现。
因此,他们发生的范围是不同的,方法重载发生在一个任意类中,而方法重写,发生在子类中,而且发生方法重写和方法覆盖的条件也不相同(这里不再赘述)
同时,方法重载是编译时多态,而方法重写是运行时多态的前提条件之一
35. "=="和equals方法有何异同?
解答:
== 对于基本数据类型的数据而言,比较的是内容,对于引用数据类型的数据而言,比较的引用变量,所指向的内存地址。equals方法是Object类的方法,其默认实现是比较两个对象的内存地址是否相同
若想要比较量对象的内容是否相同,则需要在子类中覆盖Object的equals方法
36. 字符流和字节流最主要的区别是什么?如何理解字符流=字节流+编码表?
解答:
节流和字符流的流中数据的逻辑单位不同。
字节流中数据的逻辑单位:二进制的字节数据
字符流中数据的逻辑单位:单个字符
a)字符数据在内存中还是以二进制(字符的在编码表中对应的编码值)的形式保存和传输
b)而对于二进制的字节数据的写和读,字节流就已经能够很好的完成了
c) 但为了保证字符流中的数据是一个一个的完整字符,所以字符流在字节流的基础上,添加了编解码器,即在使用底层字节流写数据前,先利用编码器,对字符数据进行编码得到字符数据对应的二进制编码序列,然后利用底层字节流传输它们,同时,在读取数据的时候,先用解码器,将由底层字节流传输的字节数据,解码成一个一个的字符
所以字符流的功能实现是字节流 + 编码表(基于编码表的编解码操作)
37.使用缓冲流是否可以在一定程度改善应用程序的IO的效率?为什么??
解答:
可以从一定程度上改善Java程序的IO效率。因为,IO的底层实现,是要依靠操作系统内核的功能来实现的,而我们的java程序每次请求操作系统内核的功能完成IO的时候,都需要付出额外的代价。既然,每次完成IO操作,都需要付出一次通信代价,那么意味着,一次IO操作如果读写的数据越多,那么平均到每个字节(字符)的数据,所付出的额外代价就会越小。
而缓冲流,本身维护了一个较大的缓冲区,能够在和操作系统内核交互的过程中,一次读写较多的字节(字符)数据,从而在整个数据传输过程中,减少java程序和操作系统内核通信的次数。从而减少了,应用程序为了完成功能,所需要付出的额外代价
38. 同步和异步有何异同,在什么情况下分别使用他们?
解答:
异步:线程之间,各自独立运行,互不影响。线程之间“同时”,在各自做自己的事情,简单来说,就是我走你也走
同步:和异步相对。同步是指线程之间不能再各自为政,自己运行自己的,而是在某些情况下等待其他线程。简单来说,就是我走你不走
线程天生就是异步执行的,而当多线程异步访问同一个共享数据的时候,为了保证共享数据访问的正确性,必须保证同时只有一个线程,能访问并修改共享变量的值,这意味着,如果一个线程正在,访问某共享变量,则其他所有要访问该共享变量的线程都需要等待,直到,该线程访问完毕。
39. Java语言多线程设计中,为什么wait, notify 和 notifyAll这些线程通信的方法不在thread类里面?
解答:
线程通信,其实是依靠锁对象,来完成的(对于wait方法而言,调用wait方法的对象,首先必须被当前线程,作为锁对象持有),而java语言中的锁对象,可以是任意对象,因此这些方法被定义在Object中
40. Java多线程中调用wait() 和 sleep()方法有什么不同?
解答:
sleep方法的唤醒条件是时间,而wait()方法的唤醒条件是,必须被在同一个锁对象上调用notify()或notifyAll()方法。
sleep方法是Thread类的静态方法,而wait()方法是Object类的方法
sleep方法在导致当前线程休眠时,当前线程不会释放所有有的锁,而wait()方法导致当前线程休眠时,当前线程会释放锁对象
四.【编程题】(10分 x 2)
41. 给定一个由 整数 组成的 非空 数组所表示的非负整数,在该数的基础上加一。
最高位数字存放在数组的首位, 数组中每个元素只存储单个数字。
你可以假设除了整数 0 之外,这个整数不会以零开头。
比如,如果数组是[1, 2, 3]则加1之后的结果是[1, 2, 4], 如果数组是[1, 2, 9]加1之后的结果就是[1, 3, 0]
解答:
第一题,给参考代码如下
public class Solution {
public int[] plusOne(int[] digits) {
//从后往前遍历,因为加法运算从右往左加,低位到高位
for (int i = digits.length - 1; i >= 0; i--) {
//对第i位上的数字值+1
digits[i]++;
//求+1之后,该位上的数字
digits[i] = digits[i] % 10;
//若低位没有进位,则高位的数字都不变直接返回
if (digits[i] != 0) {
return digits;
}
}
//否则,意味着 +1 之后,原数多了一位
//此时只有一种情况,就是99...9这种
//+1之后的结果,稚嫩格式最高位为1,其余个位都为0
digits = new int[digits.length + 1];
digits[0] = 1;
return digits;
}
}
该题目,其实有对应的o(n)时间复杂度的实现,即一次遍历,得到结果
这种实现方式只是比较好理解,并非最简
用双重循环,只要能写出代码,也是算正确,不要求所有人掌握
至少必须会用双重循环解这道题(起码能实现基本功能,暴力破解)
核心思想:对于任意一个连续子数组,如果其前面的部分和已经 <0, 那就不用再对该子数组继续向后累加,因为负数 + 后面部分的和只会使得后面部分的和越小
出现子数组和 <0 这种情况,一定是因为刚刚累加用的是负数
因此,新的子数组,从该负数的下一个位置开始计算(因为只要不跳过该负数,那么该负数前面部分的和,跟该负数相加,所得的结果一定还是负数)
42. 输入一个整型数组,数组里面有正数也有负数,数组中连续的一个或多个整数组成子数组,每个子数组都有一个和。求所有子数组的和的最大值。例如,输入的数字为:1,-2,3,10,-4,7,2,-5,则和最大的子数组为3,10,-4,7,2和为18
解答:
public static int maxSequentialSum(int[] array) {
//max存储最大的连续子数组的和
int max = array[0];
//存储当前遍历的连续子数组的和
int currentSum = array[0];
for (int i = 1; i < array.length; i++) {
if (currentSum < 0) {
//如果当前连续子数组的和已经 <0
//那么对于当前子数组而言,再累加下去没有意义
//原因:
// 和一个负数累加,只会使得后面部分的和变小
//因此,这个数组不再计算,取新数组计算
//
//同时,之所以会出现当前子数组之和 <0,一定是上次累加用的是负数
//所以要跳过该负数,然后构建新数组
//新的子数组从第 i 个位置开始,刚才累加的是第 i-1 个位置的元素
currentSum = array[i];
} else {
//否则,继续向后累加当前的连续子数组的和
currentSum += array[i];
}
if (currentSum > max) {
//如果当前子数组之和,比之前存在的最大子数组之和更大
max = currentSum;
}
}
//走到这里遍历完成
//max就是所有子数组和中最大的
return max;
}
版权声明:本文标题:day33周一总结_chap-javase阶段测试_1.加载类概念不清2.线程理解不到位[简答题] 内容由热心网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:https://m.elefans.com/dongtai/1727846380a1133137.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论