1.以下代码的循环次数是 ( )
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 无限次
这段代码会导致无限循环的原因是在 do-while 循环中,每次迭代都会先执行一次循环体内的代码,然后再进行循环条件的判断。 在这个例子中,初始值 i 被设置为 7。循环体内的代码逐步减少 i 的值,并打印出来。但是注意到每次循环体内都有两次 --i 操作,所以每次循环 i 的值会减少2。 当 i 的值减少到1时,继续进行下一次循环。此时 i 的值变为 -1,不等于0,循环继续。然后又会进行两次 --i 操作,使 i 的值变为 -3。这个过程会一直继续下去,永远不会达到循环结束的条件 i != 0。因此,这段代码会导致无限循环。
2.下面代码的运行结果为:( )
package itemtest;
import java.io.*;
import java.util.*;
public class Test{
public static void main (String[] args){
String s;
System.out.println("s=" + s);
}
}
A代码得到编译,并输出“s=”
B代码得到编译,并输出“s=null”
C由于String s没有初始化,代码不能编译通过
D代码得到编译,但捕获到 NullPointException异常
3.以下程序的输出是:( )
#include <iostream>
using namespace std;
unsigned int f(unsigned int n) {
if (n == 0 || n == 1) {
return 1;
}
return f(n-1) + f(n-2);
}
void count(int n) {
unsigned int tmp = n - ((n >> 1) & 0x33333333) - ((n >> 2) & 0x11111111);
std::cout << ((tmp + (tmp >> 3)) & 0x07070707) % 63 << std::endl;
}
int main() {
count(f(7));
count(f(9));
return 0;
}
改写成Java代码后为:
public class Test{
public static int f(int n) {
if (n == 0 || n == 1) {
return 1;
}
return f(n-1) + f(n-2);
}
public static void count(int n) {
int tmp = n - ((n >> 1) & 0x33333333) - ((n >> 2) & 0x11111111);
System.out.println(((tmp + (tmp >> 3)) & 0x07070707) % 63);
}
public static void main(String[] args) {
count(f(7));
count(f(9));
}
}
其中对于这段代码的理解如下:
public static void count(int n) {
int tmp = n - ((n >> 1) & 0x33333333) - ((n >> 2) & 0x11111111);
System.out.println(((tmp + (tmp >> 3)) & 0x07070707) % 63);
}
这段代码实现了一种高效计算一个整数的二进制表示中有多少个1的方法,即计算整数的“汉明重量”(Hamming Weight)。下面逐步解释这段代码的实现过程: 首先,这段代码接受一个整数 n 作为输入。然后,代码通过位运算来分割 n 的二进制表示。具体来说,它使用了一些掩码(mask)来提取不同位置上的比特位。 0x33333333 掩码用于提取每两位的比特位。 0x11111111 掩码用于提取每四位的比特位。 通过右移操作 (n >> k) 和按位与操作 &,可以将 n 的比特位分割成更小的块。 接下来,通过减法和加法操作,将这些被分割出来的比特位进行累加运算。 (n >> 1) & 0x33333333 表示将 n 的每两位的比特位相加,并将结果存储在 tmp 中。 (n >> 2) & 0x11111111 表示将 n 的每四位的比特位相加,并将结果与 tmp 相减。 这样,tmp 的值就是 n 的二进制表示中每两位和每四位的比特位相加的结果。 最后,通过右移操作 (tmp >> 3) 和按位与操作 &,提取每八位的比特位。 (tmp + (tmp >> 3)) & 0x07070707 表示将 tmp 的每八位的比特位相加,并将结果存储在 tmp 中。 最终结果是 tmp 对 63 取模的值,即 tmp % 63。 0x07070707 掩码用于保留 tmp 的每八位的比特位。 通过以上步骤,这段代码实现了高效计算一个整数二进制表示中1的个数的功能。 请注意,这段代码假设整数为32位。如果你要处理不同位数的整数,需要相应调整掩码的值和最终取模的除数。
在 count 函数中,将传入的数 n 进行一系列位运算操作后得到了一个数字 tmp。此外,在最后输出之前,将 tmp 与 0x07070707 进行按位与操作,并再次取模 63,最终得到的是 tmp 的一个压缩版本。 实际上,这个压缩版本已经足够表征 tmp 的大部分信息了。由于斐波那契数列的增长速度非常快,当 n 较大时,tmp 的值也会变得非常大。因此,通过将 tmp 与 0x07070707 进行按位与操作,可以将其压缩为一个更小的数字。然后,通过对 63 取模,可以确保输出值始终落在 0 到 62 之间,以便更好地控制输出结果的范围。 需要注意的是,0x07070707 所对应的二进制数是 00000111000001110000011100000111,它实际上就是用四个重复的 00000111 来组成,而 00000111 对应的十进制数为 7。因此,0x07070707 等价于十进制数 119304647。根据这个数字,我们可以使用 & 和取模操作来实现 tmp 的压缩和范围限制。
4.执行下列程序的输出结果为()
public class Test {
public static void main(String[] args) {
String s1 = "HelloWorld";
String s2 = new String("HelloWorld");
if (s1 == s2) {
System.out.println("s1 == s2");
} else {
System.out.println("s1 != s2");
}
if (s1.equals(s2)) {
System.out.println("s1 equals s2");
} else {
System.out.println("s1 not equals s2");
}
}
}
在 Java 中,== 运算符用于比较两个对象的引用是否相等,即它们是否指向同一个内存地址。而 equals() 方法则用于比较两个对象的内容是否相等。 在这个例子中,s1 是一个字符串常量(String literal),在编译时已经被赋值,并且在 JVM 内部建立了对应的 String 对象。而 s2 是通过 new 关键字创建的一个新的 String 对象,它的值也是 "HelloWorld"。虽然这两个 String 对象的内容相同,但是它们的引用并不相同,因此 s1 == s2 的结果为 false。 另一方面,equals() 方法比较的是两个对象的内容,它会调用 String 类的 equals() 方法来比较两个字符串的字符序列是否相等。由于 s1 和 s2 的字符序列都是 "HelloWorld",因此 s1.equals(s2) 的结果为 true。
5.下列类定义代码,当用来声明对象car,并用Car car=new Car();实例化后,可以通过car对象直接赋值的字段是()
public class Car {
public String type;
String No;
private int heavy;
double speed;
protected String owner;
public String price;
private String color;
}
A type,No B type,price C heavy,owner D type,owner,price
通过 new Car() 实例化后,可以通过 car 对象直接赋值的字段是:type、owner 和 price。 这是因为这三个字段都是定义为 public 访问修饰符,可以通过对象的引用直接访问和修改。而其他字段的访问修饰符是 private 或 protected,无法直接通过对象的引用访问和修改,需要通过类提供的公共方法或者反射等方式才能访问。 具体举例说明如下:
public class Car {
public String type;
String No;
private int heavy;
double speed;
protected String owner;
public String price;
private String color;
public void setHeavy(int heavy) {
this.heavy = heavy;
}
public void setSpeed(double speed) {
this.speed = speed;
}
public void setColor(String color) {
this.color = color;
}
}
通过以上的 Car 类定义,我们可以实例化一个 Car 对象并进行字段赋值。假设我们创建了一个 Car 对象 car: Car car = new Car(); 我们可以直接使用 car 对象来赋值 type、owner 和 price 字段: car.type = "Sedan"; car.owner = "John"; car.price = "$20000"; 这些字段都是 public 访问修饰符的,因此可以直接通过对象的引用 car 进行赋值操作。 但是对于其他字段,由于它们的访问修饰符是 private 或 protected,我们无法直接通过对象的引用进行赋值。例如,无法直接通过 car.heavy、car.speed 或 car.color 来赋值。 如果我们想要修改这些 private 或 protected 字段的值,我们可以为类提供公共的方法(setter 方法)来间接修改它们。例如,为 heavy、speed 和 color 字段添加相应的 setter 方法:
public void setHeavy(int heavy) {
this.heavy = heavy;
}
public void setSpeed(double speed) {
this.speed = speed;
}
public void setColor(String color) {
this.color = color;
}
然后,我们可以使用这些 setter 方法来修改字段的值:
car.setHeavy(2000);
car.setSpeed(120.5);
car.setColor("Blue");
通过这样的方式,我们可以间接修改 private 或 protected 字段的值。
6.以下程序的执行结果是:( )
package itemtest;
public class Test {
static boolean foo(char c) {
System.out.print(c);
return true;
}
public static void main(String[] args) {
int i = 0;
for (foo('A'); foo('B') && (i < 2); foo('C')) {
i++;
foo('D');
}
}
}
A、ABDCBDCB B、ABCDABCD
C、编译时出错 D、运行时抛出异常
在这个代码中,主要有三部分组成: foo(char c): 这是一个静态方法,它接受一个字符参数 c,并打印该字符并返回 true。 main 方法:这是程序的入口点。它声明了一个整数变量 i,初始值为 0。 循环:使用 for 循环进行迭代。循环的初始化部分调用 foo('A') 方法,并打印字符 'A'。然后,在循环条件部分,调用 foo('B') 方法并打印字符 'B',并检查 i 是否小于 2。如果条件为真,则进入循环体部分。在循环体内, i 的值增加 1,并调用 foo('D') 方法并打印字符 'D'。然后返回到循环条件部分。在循环条件部分调用 foo('C') 方法并打印字符 'C'。如果条件为真,则继续下一次循环。否则,退出循环。 因此,循环将执行两次,输出结果为 "ABDCBDCB"。