第02周 预习、实验与作业:Java基础语法2、面向对象入门(JAVA预习作业)
-
课前问题列表
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的功能各是什么? 1.2 main方法的x有没有被改变?为什么? 1.3 main方法的args数组的内容有没有被改变?为什么? 1.4 args数组中的值是从哪里来的?要怎么才能给他赋值。-
1.1 changeStr与changeArr的功能各是什么?
changeStr 函数接受一个字符串参数 x,并尝试将 x 的值更改为 "xyz"。
changeArr 函数接受一个字符串数组 strs 作为参数,并遍历数组,将每个元素的值更改为原始值后跟其索引。 -
1.2 main方法的x有没有被改变?为什么?
x 的值没有被改变。在 changeStr 函数中,尽管 x 被赋予了新的值 "xyz",但由于 Java 中的参数传递是按值传递的,这意味着 x 在 changeStr 函数中的变化不会影响到 main 函数中 x 的值。
-
1.3 main方法的args数组的内容有没有被改变?为什么?
args 数组的内容被改变了。changeArr 函数遍历 args 数组,并且对每个元素进行了修改,将每个元素的值更改为原始值后跟其索引。由于数组是可变的,所以这些更改会影响到 main 函数中 args 数组的内容
-
1.4 args数组中的值是从哪里来的?要怎么才能给他赋值。
args 数组中的值来自于程序启动时传递给 main 方法的命令行参数。当你从命令行运行 Java 程序时,你可以传递一系列参数,这些参数将被存储在 args 数组中。
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] [aa, xx, cc]String[] strArr = {"aa","bb","cc"}; 创建了一个字符串数组,并初始化了三个元素。
strArr[1] = "xx"; 将数组的第二个元素更改为 "xx"。
打印 strArr 时,输出了数组的内容,显示了更改后的第二个元素。 -
2.2 字符串是不可变类,为什么可以对strArr[1]赋值"xx"。
数组中的每个元素都是一个引用,你可以更改这个引用指向的对象。在 strArr[1] = "xx"; 这行代码中,你实际上是在更改数组第二个位置的引用,使其指向一个新的字符串对象 "xx",而不是更改原来数组中引用的字符串对象。即使字符串本身是不可变的,仍然可以更改数组中的引用,使其指向一个新的字符串对象。
3.使用int[5][]定义一个二维数组,其第二维到底有多长?尝试补全代码,然后使用foreach获其他循环方法遍历这个二维数组?
public class Main { public static void main(String[] args) { // 定义一个二维数组,第一维长度为 5,第二维长度可变 int[5][] array = new int[5][]; // 为每一行分配不同长度的数组 array[0] = new int[2]; // 第一行有 2 个元素 array[1] = new int[3]; // 第二行有 3 个元素 array[2] = new int[1]; // 第三行有 1 个元素 array[3] = new int[4]; // 第四行有 4 个元素 array[4] = new int[5]; // 第五行有 5 个元素 // 使用 foreach 循环遍历二维数组 for (int[] row : array) { for (int value : row) { System.out.print(value + " "); } System.out.println(); } // 使用传统 for 循环遍历二维数组 for (int i = 0; i < array.length; i++) { for (int j = 0; j < array[i].length; j++) { System.out.print(array[i][j] + " "); } System.out.println(); } } }4.类与对象的区别是什么? Math类有对象吗?String类有什么属性是private的,有什么方法是public的,为什么这样设计(尝试举两例说明)?
类与对象的区别:
类:类是定义对象属性和方法的模板或蓝图,它是一种抽象概念,不占用内存空间。
对象:对象是根据类创建的具体实例,每个对象都占用内存空间,并具有类定义的属性和方法。Math 类:
Math 是一个包含静态方法的实用工具类,用于执行数学计算。由于所有方法都是静态的,不需要创建对象即可使用。String 类的设计:
属性:String 类的大部分属性都是私有的,以保护内部数据并提供封装。
公共方法:如 length()、charAt()、substring()、equals() 和 toString(),这些方法提供了对字符串操作的接口。私有属性和公共方法的设计是为了确保字符串的不可变性和安全性。不可变性意味着一旦字符串被创建,它的内容就不能被改变,这有助于保证线程安全和数据一致性。公共方法允许安全地访问和操作字符串数据,而不需要暴露内部实现细节。
5.将类的属性设置为public可以方便其他类访问,但为什么Java中普遍使用setter/getter模式对对象的属性进行访问呢?这与封装性又有什么关系?
在 Java 中,尽管可以将类的属性设置为 public 以便于直接访问,但这种做法通常不被推荐,因为它违反了封装原则。封装是面向对象编程的核心概念之一,它要求将数据(属性)和操作这些数据的方法(行为)封装在一起,同时对外隐藏内部实现细节。以下是使用 setter/getter 方法访问属性而不是直接公开属性的几个主要原因:
数据保护:setter 方法可以在设置属性值之前进行验证,确保数据的有效性和对象状态的一致性。
灵活性和维护性:如果属性的实现细节需要改变,只需修改对应的 setter/getter 方法,而不需要修改所有直接访问属性的代码。
增加行为:在 setter/getter 方法中可以添加额外的逻辑,例如通知其他对象属性值的变化或执行必要的操作。
延迟加载:getter 方法可以实现延迟加载,即仅在需要时才计算或加载属性值,从而提高应用程序的性能。
安全性:封装可以防止外部代码直接修改内部状态,减少错误和不一致的风险。因此,setter/getter 模式有助于实现更好的封装,使得代码更加健壮、灵活和易于维护。这也是为什么在 Java 中普遍采用这种方式来访问对象属性的原因。
6.对象的属性可在什么时候进行初始化?都有哪些进行初始化的办法?
对象的属性可以在以下时机进行初始化:
声明时初始化:在对象属性被声明的同时直接赋予初始值。class Person { String name = "John"; int age = 30; }构造函数中初始化:在创建对象时,通过构造函数为属性赋予初始值。
class Person { String name; int age; Person(String name, int age) { this.name = name; this.age = age; } }实例初始化块:在类中使用实例初始化块为属性赋予初始值,这在创建对象时执行。
class Person { String name; int age; { name = "John"; age = 30; } }静态初始化块:用于静态属性的初始化,这在类被加载到 JVM 时执行。
class Person { static String staticName = "John"; static { staticName = "Jane"; } }进行初始化的方法包括:
直接赋值:在声明属性时直接赋予一个值。
构造函数:通过构造函数参数为对象的属性提供值。
初始化块:使用代码块为对象的属性提供值,这些代码块在对象创建时执行。
工厂方法:在静态工厂方法中创建对象并初始化属性,然后返回对象。
属性设置器(setter 方法):在对象创建后,通过公共的 setter 方法为属性赋值。
通常,推荐使用构造函数来初始化对象的属性,因为这样可以在创建对象时立即为属性赋予有意义的值,并且可以在构造函数中添加验证逻辑。对于静态属性,可以使用静态初始化块或直接在声明时赋值。实例初始化块和工厂方法则用于更复杂的初始化场景。 -

浙公网安备 33010602011771号