Java预习任务完成与问题解析

预习任务完成报告

方法相关问题

1.1 changeStr与changeArr的功能各是什么?

  • changeStr 方法接收一个 String 参数 x,并尝试将 x 重新赋值为 "xyz"。但由于 String 是不可变类,且 Java 采用值传递,该方法不会改变原始字符串变量的值。
  • changeArr 方法接收一个 String 数组参数 strs,并遍历数组,将每个元素修改为原始值加上索引号(例如 strs[i] + "" + i)。这会修改数组的内容,因为数组是引用类型,传递的是引用的副本,但通过引用可以修改原始数组的元素。

1.2 main方法的x有没有被改变?为什么?

  • main 方法的 x 没有被改变。因为 changeStr 方法中的参数 x 是局部变量,接收了 main 方法中 x 的值的副本(即引用的副本)。当在 changeStr 中重新赋值时,只是改变了局部变量 x 的引用,而不是原始变量。因此 main 中的 x 仍然指向 "abc"

1.3 main方法的args数组的内容有没有被改变?为什么?

  • main 方法的 args 数组的内容被改变了。因为 changeArr 方法接收的是数组的引用副本,但通过这个引用副本可以直接访问和修改原始数组的元素。因此,当 changeArr 修改数组元素时,原始 args 数组被修改。

1.4 args数组中的值是从哪里来的?要怎么才能给他赋值?

  • args 数组中的值来自命令行参数。当运行 Java 程序时,可以通过命令行传递参数。例如,使用命令 java Main arg1 arg2 arg3,那么 args 数组就会包含 ["arg1", "arg2", "arg3"]。在 IDE(如 IntelliJ IDEA 或 Eclipse)中,可以通过运行配置设置命令行参数。

数组相关问题

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 的引用,因此 arrXarr 指向同一个数组对象。当修改 arr[0] 为 2 时,通过 arrX 访问同一个数组,所以 arrX[0] 也是 2。数组是引用类型,赋值操作共享引用。

2.2 字符串是不可变类,为什么可以对strArr[1]赋值"xx"?

String[] strArr = {"aa","bb","cc"};
strArr[1] = "xx";
System.out.println(Arrays.toString(strArr));
  • 字符串是不可变类,意味着 String 对象一旦创建就不能被修改。但 strArr 是一个数组,数组的元素是 String 引用。当执行 strArr[1] = "xx" 时,并不是修改了原有的 String 对象 "bb",而是将 strArr[1] 这个引用重新指向了一个新的 String 对象 "xx"。因此,这是改变了数组元素存储的引用,而不是修改了 String 对象本身。

2.3 使用int[5][]定义一个二维数组,其第二维到底有多长?尝试补全代码,然后使用foreach或其他循环方法遍历这个二维数组?

  • 使用 int[5][] 定义一个二维数组时,第一维的长度是 5,但第二维的长度没有指定,因此每个第二维数组可以是不同的长度,或者为 null。需要单独初始化每个第二维数组。

补全代码示例:

import java.util.Arrays;

public class TwoDArrayExample {
    public static void main(String[] args) {
        int[][] twoDimArray = new int[5][]; // 第二维未初始化

        // 初始化第二维数组,长度各不相同
        twoDimArray[0] = new int[3];
        twoDimArray[1] = new int[2];
        twoDimArray[2] = new int[4];
        twoDimArray[3] = new int[1];
        twoDimArray[4] = new int[5];

        // 使用foreach遍历
        for (int i = 0; i < twoDimArray.length; i++) {
            int[] innerArray = twoDimArray[i];
            if (innerArray != null) {
                for (int value : innerArray) {
                    System.out.print(value + " ");
                }
                System.out.println();
            } else {
                System.out.println("null");
            }
        }
    }
}

类与对象的区别是什么? Math类有对象吗?String类有什么属性是private的,有什么方法是public的,为什么这样设计(尝试举两例说明)?

  • 类与对象的区别

    • 类是一个模板或蓝图,定义了对象的属性和行为。例如,String 类定义了字符串的属性和方法。
    • 对象是类的实例,是具体的数据。例如,String 对象是具体的字符串值。
  • Math类有对象吗?

    • Math 类没有对象。Math 类中的所有方法和属性都是 static 的,因此不需要创建对象就可以使用。Math 类设计为不可实例化,通常通过类名直接调用方法,如 Math.abs()
  • String类有什么属性是private的,有什么方法是public的,为什么这样设计?

    • String 类内部使用 private 属性来存储字符数据,例如在 Java 8 中,String 类有 private final char value[] 字段来存储字符数组。这些属性是 private 的,以防止外部直接修改,确保 String 的不可变性。
    • String 类提供了许多 public 方法,如 length()charAt()substring() 等,这些方法允许读取字符串的内容而不修改它(因为不可变),或者返回新的字符串。
    • 为什么这样设计?为了封装和不可变性。封装保护了内部数据不被意外修改,不可变性使得字符串在多线程环境下安全,并且可以缓存哈希值等。例如:
      • private 字段 value 被封装,外部不能直接访问,只能通过 public 方法操作。
      • public 方法如 toUpperCase() 返回新字符串,而不是修改原字符串,确保了不可变性。

将类的属性设置为public可以方便其他类访问,但为什么Java中普遍使用setter/getter模式对对象的属性进行访问呢?这与封装性又有什么关系?

  • 使用 setter/getter 模式的主要原因是为了封装。封装是面向对象编程的基本原则之一,它隐藏了对象的内部状态,并通过方法来控制对状态的访问和修改。
  • 好处:
    • 控制访问:可以通过 getter 和 setter 添加验证逻辑。例如,在 setter 中检查输入值是否有效。
    • 灵活性:可以在不改变类的外部接口的情况下修改内部实现。例如,如果将来需要计算某个值而不是直接存储,可以修改 getter 方法。
    • 只读或只写属性:可以通过只提供 getter 或只提供 setter 来实现。
    • 调试和维护:可以在 setter 或 getter 中添加日志或调试代码。
  • 与封装性的关系:封装性要求对象的状态不被直接暴露,而是通过方法间接访问。setter/getter 模式正是实现这种间接访问的标准方式。

对象的属性可在什么时候进行初始化?都有哪些进行初始化的办法?

  • 对象的属性可以在以下时机进行初始化:

    1. 声明时直接初始化:例如 private int age = 0;
    2. 在构造器中初始化:通过构造函数赋值。
    3. 在初始化块中初始化:使用实例初始化块或静态初始化块(对于静态属性)。
    4. 通过 setter 方法初始化:在对象创建后,通过调用 setter 方法设置值。
    5. 懒初始化:在 getter 方法中检查属性是否已初始化,如果没有则初始化。
  • 具体办法示例:

public class Example {
    private int a = 10; // 直接初始化
    private int b;
    private int c;
    
    { // 实例初始化块
        b = 20;
    }
    
    public Example() {
        c = 30; // 构造器初始化
    }
    
    public void setC(int value) {
        c = value; // 通过方法初始化
    }
}
posted @ 2025-09-14 21:56  m0rt1s  阅读(0)  评论(0)    收藏  举报