当前位置: 首页 > news >正文

第2周-预习作业

Java 相关问题解答

1. 方法相关问题

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

  • changeStr功能:该方法接收一个String参数x,并尝试将x赋值为"xyz"。但由于String是不可变类,且Java采用值传递,所以该方法不会改变原始字符串的值。它只会修改方法内部局部变量x的引用,对调用方的变量无影响。

  • changeArr功能:该方法接收一个String数组参数strs,并遍历数组,将每个元素拼接上其索引值(例如,strs[i]变为strs[i] + "" + i)。由于数组是对象,传递的是引用值的副本,但副本和原始引用指向同一数组对象,因此该方法会实际修改数组的内容。

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

  • 没有改变。原因如下:
    • Java中方法参数传递是值传递(pass-by-value)。当调用changeStr(x)时,传递的是变量x的值的副本(即指向字符串"abc"的引用的副本)。
    • changeStr方法内部,参数x被重新赋值为指向"xyz",但这只影响方法内的局部变量,不会改变main方法中x的引用。main方法中的x仍然指向原始的字符串"abc"。
    • String的不可变性也确保了字符串内容不会被修改。

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

  • 被改变了。原因如下:
    • 当调用changeArr(args)时,传递的是args数组的引用值的副本,但该副本和原始引用都指向同一个数组对象。
    • changeArr方法中,通过引用修改了数组元素的值(例如,将每个元素拼接索引值),这些修改会反映到原始数组上,因为操作的是同一对象。

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

  • 来源:args数组中的值来自命令行参数(command-line arguments)。当运行Java程序时,可以通过命令行输入参数。

  • 赋值方法

    • 命令行方式:使用java Main arg1 arg2 arg3运行程序,其中arg1arg2arg3会被传入args数组(args[0]="arg1", args[1]="arg2", 等等)。
    • IDE方式:在IDE(如Eclipse、IntelliJ IDEA)中,可以通过运行配置(Run Configuration)设置程序参数(Program arguments)来赋值。
    • 示例:如果在命令行中运行java Main hello world,则args[0]="hello", args[1]="world"。

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]
    
  • 原因

    • int[] arrX = arr; 将arrX指向了同一个数组对象作为arr。因此,arr和arrX是同一个数组的两个引用。
    • 当执行arr[0] = 2;时,修改了数组的第一个元素,由于arr和arrX共享同一数组,所以通过arrX访问时也能看到修改后的值。
    • 数组初始化为int[3]时,元素默认值为0,所以arr[2]为0。

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

String[] strArr = {"aa","bb","cc"};
strArr[1] = "xx";
System.out.println(Arrays.toString(strArr));
  • 原因
    • 字符串不可变是指String对象本身的内容不能被修改(例如,不能改变"bb"的内部字符数组)。
    • 但是,strArr是一个String数组,其元素是String类型的引用。执行strArr[1] = "xx";并不是修改已有的String对象"bb",而是将strArr[1]的引用从指向"bb"改为指向一个新的String对象"xx"。
    • 因此,这是改变数组元素的引用值,而不是修改String对象的内容,所以是允许的。

3. 二维数组问题

使用int[5][]定义一个二维数组,其第二维的长度最初未指定(即为null),需要单独初始化。第二维的长度可以各不相同。

补全代码示例:

// 定义二维数组,第一维长度为5,第二维未初始化
int[][] twoDArray = new int[5][];// 初始化第二维数组,这里假设第二维长度均为3(也可以设置不同长度)
for (int i = 0; i < twoDArray.length; i++) {twoDArray[i] = new int[3]; // 每个第二维数组长度为3
}// 使用foreach循环遍历二维数组
for (int[] innerArray : twoDArray) {for (int value : innerArray) {System.out.print(value + " ");}System.out.println();
}
  • 第二维的长度:在初始化之前,第二维的每个元素都是null。初始化后,第二维的长度由代码决定(如上例中均为3),但也可以设置不同长度,例如:
    twoDArray[0] = new int[2];
    twoDArray[1] = new int[4];
    // ...
    

4. 类与对象问题

类与对象的区别是什么?

  • :是对象的蓝图或模板,定义了对象的属性(字段)和方法(行为)。它是一个抽象概念,例如String类、Math类。
  • 对象:是类的实例,是具体的数据结构,占用内存空间。例如,通过new String("abc")创建的字符串对象。

Math类有对象吗?

  • Math类没有对象(实例)。因为Math类被设计为工具类,所有方法都是static的,并且构造函数是private的,防止实例化。直接通过类名调用方法,如Math.abs(-5)

String类有什么属性是private的,有什么方法是public的,为什么这样设计?

  • private属性:String类内部使用private final数组存储字符数据,例如在Java 8及之前是private final char[] value,在Java 9及之后是private final byte[] value。这些属性是private的,以防止外部直接访问和修改。

  • public方法:String类提供了许多public方法用于操作字符串,例如:

    • public int length():返回字符串长度。
    • public char charAt(int index):返回指定索引处的字符。
    • public String substring(int beginIndex):返回子字符串。
  • 为什么这样设计

    • 封装性:通过将属性设为private,控制对内部数据的访问,确保字符串的不可变性。外部代码不能直接修改内部数组,从而保证字符串内容一致性和线程安全。
    • 安全性:防止恶意修改字符串内容,例如在安全敏感的上下文中。
    • 灵活性:可以在内部改变实现而不影响外部代码(例如从char数组改为byte数组以节省空间)。
    • 示例:substring方法返回新字符串,而不是修改原字符串,这得益于不可变设计。

5. setter/getter模式与封装性

为什么Java中普遍使用setter/getter模式?

  • 原因
    • 封装性:setter/getter模式是封装的具体体现。通过将属性设为private,然后提供public的setter和getter方法,可以控制对属性的访问。
    • 优点
      • 数据验证:在setter方法中检查输入值的有效性(例如,年龄不能为负数)。
      • 延迟初始化或计算:在getter中可以实现延迟加载或计算属性值。
      • 修改内部实现:以后可以改变属性的存储方式而不影响外部代码(例如,将直接存储改为计算得出)。
      • 添加额外逻辑:可以在setter/getter中添加日志、通知或同步代码。
    • 与封装性的关系:封装隐藏了对象的内部状态,只暴露必要的操作接口(setter/getter),从而降低耦合度,提高代码的可维护性和安全性。如果属性直接public,外部代码可以随意修改,可能导致对象状态不一致。

6. 对象属性的初始化时机和方法

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

  1. 声明时直接初始化:在定义属性时直接赋值。

    private int x = 10;
    private String name = "default";
    
  2. 构造器中初始化:在构造函数中赋值。

    public MyClass() {this.x = 10;this.name = "default";
    }
    
  3. 初始化块中初始化

    • 实例初始化块:在类中使用{}块,每次创建对象时执行。
      {x = 10;name = "default";
      }
      
    • 静态初始化块:使用static{}块,用于初始化静态属性,在类加载时执行一次。
  4. 通过方法初始化:在对象创建后,通过setter方法或其他方法初始化。

    MyClass obj = new MyClass();
    obj.setX(10);
    
  5. 延迟初始化:在第一次访问属性时初始化,通常结合null检查。

    private String data;
    public String getData() {if (data == null) {data = loadData(); // 加载数据}return data;
    }
    

这些方法可以根据需要组合使用,以确保属性在对象使用前被正确初始化。

http://www.wxhsa.cn/company.asp?id=4930

相关文章:

  • P12546 [UOI 2025] Convex Array
  • 一个新词:测试可靠性
  • CF827F Dirty Arkadys Kitchen
  • P2839 [国家集训队] middle
  • wuti
  • 友链
  • 向量化存储与知识图谱的比较
  • 力扣17题 电话号码的字母组合
  • 萤火虫文旅年票、为什么能做到低至4.2元一张景区门票、还能高达50%的毛利润?
  • ubuntu服务器docker容器安装nacos
  • PWN手的成长之路-02-r3m4ke
  • SAP 采购订单税率及含税金额取数
  • 深入解析:Linux x86 stability和coredump
  • 9.15更新linux命令
  • Jenkins 容器和 Kubernetes Agent
  • LGP7916 [CSP-S 2021] 交通规划 学习笔记
  • 详细介绍:【Kubernetes】常见面试题汇总(十四)
  • 萤火虫文旅年票、为何能成为撬动万亿文旅市场的利器
  • 教育行业API安全最佳实践:全知科技以国家标准引领数据防护新范式
  • Codecademy Pro是否值得?2023年深度评测与技术特性解析
  • Qt处理USB摄像头开发说明与QtMultimedia与V4L2融合应用
  • 实用指南:【性能优化需要关注的参数——Batches】
  • 禁止指定软件联网
  • 详细介绍:C++(静态函数)
  • 2025.9.15日软件工程学习日志
  • RocketMQ快速实战及核心概念
  • 【南方科技大学主办】第五届电气工程与机电一体化手艺国际学术会议(ICEEMT 2025)
  • 为什么不建议在 Docker 中跑 MySQL?
  • reLeetCode 热题 100-1 指针283. 移动零 - MKT
  • 解决c# DocX生成的word文档wps打开排版外边距错乱微软office正常问题