1. 方法相关问题
1.1 changeStr与changeArr的功能各是什么?
changeStr
方法尝试修改传入的字符串参数x
,将其赋值为"xyz"
。changeArr
方法遍历传入的字符串数组strs
,并将每个元素修改为自身拼接上其索引值的形式。
1.2 main方法的x有没有被改变?为什么?
main
方法中的x
没有被改变。因为 Java 中的字符串是不可变的,而且changeStr
方法中修改的只是x
的副本(局部变量),而不是原始变量。
1.3 main方法的args数组的内容有没有被改变?为什么?
main
方法中的args
数组的内容被改变了。因为数组是可变的,changeArr
方法直接修改了传入的数组元素。
1.4 args数组中的值是从哪里来的?要怎么才能给他赋值?
args
数组中的值是在运行程序时从命令行传入的参数。可以通过在命令行执行 Java 程序时附加参数来赋值,例如:java Main arg1 arg2 arg3
。
2. 数组相关问题
2.1 这段程序输出结果是什么?为什么?
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, 0]
[2, 1, 0]
arrX
和arr
引用的是同一个数组对象,修改arr
的元素也会反映到arrX
。
2.2 字符串是不可变类,为什么可以对strArr[1]赋值"xx"。
- 虽然字符串本身是不可变的,但是数组
strArr
是可变的。strArr[1] = "xx"
并不是修改了原来的字符串,而是将数组的第二个元素指向了一个新的字符串对象"xx"
。
3. 使用int[5][]定义一个二维数组,其第二维到底有多长?尝试补全代码,然后使用foreach或其他循环方法遍历这个二维数组。
int[][] twoDimArr = new int[5][]; // 第二维长度未指定 | |
// 补全代码,初始化第二维 | |
twoDimArr[0] = new int[2]; | |
twoDimArr[1] = new int[3]; | |
twoDimArr[2] = new int[1]; | |
twoDimArr[3] = new int[4]; | |
twoDimArr[4] = new int[2]; | |
// 使用 foreach 遍历 | |
for (int[] row : twoDimArr) { | |
for (int val : row) { | |
System.out.print(val + " "); | |
} | |
System.out.println(); | |
} | |
// 或者使用嵌套循环遍历 | |
for (int i = 0; i < twoDimArr.length; i++) { | |
for (int j = 0; j < twoDimArr[i].length; j++) { | |
System.out.print(twoDimArr[i][j] + " "); | |
} | |
System.out.println(); | |
} |
4. 类与对象的区别是什么?Math类有对象吗?String类有什么属性是private的,有什么方法是public的,为什么这样设计?
类与对象的区别
- 类是对象的模板或蓝图,而对象是类的实例。
Math类有对象吗?
Math
类中的方法都是静态的,因此不需要创建对象,可以直接通过类名调用。
String类有什么属性是private的,有什么方法是public的,为什么这样设计?
String
类中的value
属性是private
的,它是一个字符数组,存储字符串的内容。public
的方法包括length()
,charAt(int index)
,substring(int beginIndex)
,toLowerCase()
,toUpperCase()
等。- 这样设计是为了封装字符串的内部实现,防止外部直接修改字符串内容,保证字符串的不可变性。
5. 将类的属性设置为public可以方便其他类访问,但为什么Java中普遍使用setter/getter模式对对象的属性进行访问呢?这与封装性又有什么关系?
- 使用
setter/getter
模式可以实现对属性访问的控制,可以在方法中添加额外的逻辑(如验证、日志)。 - 这与封装性密切相关,封装性隐藏了类的内部细节,只暴露必要的接口,提高了代码的安全性和可维护性。
6. 对象的属性可在什么时候进行初始化?都有哪些进行初始化的办法?
对象的属性可以在以下时机进行初始化:
- 定义时初始化:在声明属性时直接赋值。
- 构造器中初始化:在构造器中对属性进行赋值。
- 初始化块:使用初始化块(实例初始化块或静态初始化块)对属性进行初始化。
- 方法内初始化:在某些方法中(如
setter
方法)对属性进行赋值。
示例博客文章:
Java对象属性初始化的几种方式
在Java编程中,初始化对象的属性是一个非常重要的步骤。属性初始化的方式和时机直接影响对象的状态和行为。本文将介绍几种常见的对象属性初始化方法。
1. 定义时初始化
最简单和直接的方式是在声明属性时直接赋值。例如:
public class Person { | |
private String name = "John Doe"; | |
private int age = 30; | |
} |
这种方法的优点是简洁明了,缺点是不够灵活,无法在初始化时根据条件设置不同的值。
2. 构造器中初始化
通过构造器初始化属性,可以在创建对象时根据传入的参数设置属性值。例如:
public class Person { | |
private String name; | |
private int age; | |
public Person(String name, int age) { | |
this.name = name; | |
this.age = age; | |
} | |
} |
构造器初始化允许在对象创建时进行复杂的初始化逻辑,如参数验证、依赖注入等。
3. 初始化块
初始化块包括实例初始化块和静态初始化块,它们分别在创建对象和类加载时执行。例如:
public class Person { | |
private String name; | |
private int age; | |
{ | |
// 实例初始化块 | |
name = "Unknown"; | |
age = 0; | |
} | |
static { | |
// 静态初始化块,通常用于静态属性的初始化 | |
} | |
} |
初始化块在每次创建对象时都会执行,可以用于设置默认值或执行其他初始化逻辑。
4. 方法内初始化
在某些情况下,属性的初始化可能发生在特定的方法中,如 setter
方法。例如:
public class Person { | |
private String name; | |
private int age; | |
public void setName(String name) { | |
this.name = name != null ? name : "Default Name"; | |
} | |
public void setAge(int age) { | |
this.age = age > 0 ? age : 0; | |
} | |
} |
这种方法允许在设置属性值时进行验证和逻辑处理,确保属性的有效性。