课前问题列表
1.方法相关问题
public class Main {static void changeStr(String x) {x = "xyz";}static void changeArr(String[] strs) {for (int i = 0; i < strs.length; i++) {strs[i] = strs[i]+""+i;}}public static void main(String[] args) { String x = "abc";changeStr(x);System.out.println(x);changeArr(args);System.out.println(Arrays.toString(args));}
}
对于如上代码:
1.1 changeStr与changeArr的功能各是什么?
- changeStr方法:接收一个 String 类型参数x,尝试将其赋值为"xyz",但由于 String 的不可变性和参数传递机制,该操作不会影响原变量。
changeArr方法:接收一个 String 数组参数strs,遍历数组并修改每个元素,在原字符串后拼接其索引。
1.2 main方法的x有没有被改变?为什么?
- Java 中方法参数传递是值传递。changeStr方法中的x是形参,是实参x("abc")的副本(复制了引用地址)。在方法内修改形参x的指向(改为"xyz"),不会影响实参x的指向,因此main方法中的x仍为"abc"。
1.3 main方法的args数组的内容有没有被改变?为什么?
- main 方法的 args 数组内容被改变。
- 原因:数组是引用类型,值传递时复制的是引用地址(形参strs和实参args指向同一个数组对象)。changeArr方法中修改的是数组内部的元素(通过索引操作),而非修改引用本身,因此原数组args的内容会被改变。
1.4 args数组中的值是从哪里来的?要怎么才能给他赋值。
- 来源:args数组的值是程序运行时通过命令行参数传递的。
- 赋值方式:运行 Java 程序时,在类名后添加参数。
2.数组相关问题
对于如下程序
int[] arr = new int[3];
arr[0] = 1; arr[1] = 1;
int[] arrX = arr;
arr[0] = 2;
System.out.println(Arrays.toString(arr));
System.out.println(Arrays.toString(arrX));
2.1 这段程序输出结果是什么?为什么?
String[] strArr = {"aa","bb","cc"};
strArr[1] = "xx";
System.out.println(Arrays.toString(strArr));
- 输出结果:
[2, 1, 0]
[2, 1, 0]
- 原因:数组是引用类型,int[] arrX = arr表示arrX和arr指向同一个数组对象。当修改arr[0] = 2时,本质是修改了共享的数组内容,因此arr和arrX打印结果相同。
2.2 字符串是不可变类,为什么可以对strArr[1]赋值"xx"。
- 字符串不可变指的是String 对象本身的内容不能被修改。
- strArr[1] = "xx"操作的是数组的引用,而非修改原字符串对象:原数组元素strArr[1]原本指向"bb"对象,赋值后改为指向"xx"新对象,并未修改"bb"本身,因此合法。
3. 使用int[5][]定义一个二维数组,其第二维到底有多长?尝试补全代码,然后使用foreach获其他循环方法遍历这个二维数组?
- int[5][]是不规则二维数组,第二维(每个一维数组)的长度不确定,可单独初始化不同长度。
import java.util.Arrays;public class Test {public static void main(String[] args) {int[][] arr = new int[5][];arr[0] = new int[2]; arr[1] = new int[3]; arr[2] = new int[1]; arr[3] = new int[4]; arr[4] = new int[0]; // 用foreach遍历System.out.println("二维数组遍历结果:");for (int[] row : arr) { System.out.print(Arrays.toString(row) + " ");}}
}
4. 类与对象的区别是什么? Math类有对象吗?String类有什么属性是private的,有什么方法是public的,为什么这样设计(尝试举两例说明)?
- 类:是抽象的模板,定义了对象的属性(数据)和方法(行为),不占用内存。例如Person类定义了 “人” 的特征(姓名、年龄)和行为(吃饭、睡觉)。
- 对象:是类的具体实例,占用内存,具有类定义的属性和方法。例如new Person()创建的 “张三” 是一个对象。
- Math类没有对象:Math类的构造方法是private的,且所有方法都是static(静态方法),无需实例化即可使用。
String 类的 private 属性与 public 方法:
- private 属性:例如private final char[] value(存储字符串的字符序列),确保字符串内容不可被外部直接修改(保证不可变性)。
- public 方法:例如public int length()(返回字符串长度)、public char charAt(int index)(返回指定位置字符)。
- 设计原因:通过private隐藏内部实现(如value数组),避免外部随意修改;通过public方法提供安全的访问接口,保证字符串的不可变性和操作安全性。
5. 将类的属性设置为public可以方便其他类访问,但为什么Java中普遍使用setter/getter模式对对象的属性进行访问呢?这与封装性又有什么关系?
- 必要性:public属性允许外部直接修改,可能导致数据不合法(如年龄为负数)。setter 方法可添加验证逻辑(如if (age < 0) throw ...),控制赋值合法性;getter 方法可控制返回数据的方式(如返回副本避免外部修改)。
- 与封装性的关系:封装性要求 “隐藏内部细节,只暴露必要接口”。setter/getter 将属性隐藏(private),仅通过方法交互,符合封装原则,保证数据安全和可控性。
6. 对象的属性可在什么时候进行初始化?都有哪些进行初始化的办法?
- 对象属性可在类加载时(静态属性)、对象创建时(声明时、实例初始化块、构造方法)及对象创建后(setter 方法)初始化。
- 具体办法有静态初始化(静态声明赋值、静态代码块)、实例初始化(声明赋值、实例代码块、构造方法)和 setter 方法赋值。