Java预习任务

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; // 通过方法初始化
    }
}

第二部分:Java基本概念、命令行运行、Scanner和字符串比较

使用Java能编写哪些类型的程序?试举至少两个例子。

  • Java可以编写多种类型的程序,例如:
    1. 桌面应用程序:使用Swing或JavaFX构建图形用户界面(GUI)程序,如文本编辑器、计算器等。
    2. Web应用程序:使用Java EE或Spring框架构建服务器端Web应用,如电子商务网站、社交网络等。
    3. 移动应用程序:使用Android SDK开发Android应用。
    4. 企业级应用:如客户关系管理系统(CRM)、企业资源规划(ERP)系统。
    5. 嵌入式系统:如智能卡、传感器等。

Java号称“一次编译、处处运行”(Write Once, Run Anywhere!),怎么理解这句话?为使编译好的程序能运行,需先在操作系统安装什么?

  • "一次编译、处处运行"意味着Java代码只需编译一次,生成的字节码(.class文件)可以在任何支持Java虚拟机(JVM)的平台上运行,而不需要重新编译。这是因为JVM充当了字节码和底层操作系统之间的中介,字节码在JVM上执行,JVM负责将字节码翻译成特定平台的机器码。
  • 为使编译好的程序能运行,需要在操作系统上安装Java运行时环境(JRE)或Java开发工具包(JDK),其中包含JVM。

对比c版本的与Java版本HelloWorld代码,有何不同?

C版本的HelloWorld代码:

#include <stdio.h>

int main() {
    printf("Hello, World!\n");
    return 0;
}

Java版本的HelloWorld代码:

public class HelloWorld {
    public static void main(String[] args) {
        System.out.println("Hello, World!");
    }
}

不同点:

  1. 语法结构:C代码使用预处理指令#include,而Java代码使用类定义。
  2. 入口点:C程序的入口点是main函数,返回int类型;Java程序的入口点是main方法,位于类中,返回void,但接受String数组参数。
  3. 输出语句:C使用printf,Java使用System.out.println
  4. 编译和运行:C代码编译成机器码,直接运行;Java代码编译成字节码,在JVM上运行。
  5. 面向对象:Java是面向对象的语言,所以代码必须放在类中;C是过程式语言。

怎么比较两个字符串内容是否相同?可以直接用吗?为什么对基本数据类型可以直接使用?对引用数据类型不行?

  • 比较两个字符串内容是否相同,应该使用equals()方法,例如:str1.equals(str2)
  • 不能直接使用==因为==对于引用类型比较的是引用是否指向同一个对象,而不是内容是否相同。对于基本数据类型,==比较的是值是否相等。
  • 对于基本数据类型(如int、char),==直接比较值,因为变量存储的就是值本身。
  • 对于引用数据类型(如String、Object),变量存储的是对象的引用(地址),所以==比较的是引用是否相同,即是否指向同一个对象。如果要比较内容,需要重写equals()方法。

下面这段代码,本意是要达到什么效果?能运行成功吗?为什么?怎么获得String的trim()方法的说明?

代码:

String x = null;
int length = x.length();
System.out.println("x.length = "+length +", content = "+x.trim());
  • 本意可能是想获取字符串x的长度和修剪后的内容,但x是null。
  • 不能运行成功,因为会抛出NullPointerException。调用x.length()x.trim()时,x是null,所以会尝试在null引用上调用方法,导致异常。
  • 要获得String的trim()方法的说明,可以查看Java官方文档,或使用IDE的文档提示(如Ctrl+Q在IntelliJ IDEA中),或在命令行使用javadoc

阅读如下代码

代码:

Integer x = Integer.valueOf("10");
Integer y = x + 1;
int z = x + y;
  • x是Integer类型,1是int类型,为什么他们可以相加?使用了自动拆箱(autounboxing)技术。当Integer对象与int值相加时,Integer对象自动拆箱为int值,然后进行加法运算。
  • z是int,xy是Integer类型,却可以直接将x + y赋给z,同样使用了自动拆箱技术。在表达式中,Integer对象自动拆箱为int值,所以x + y结果是int类型,可以直接赋值给int变量z
posted @ 2025-09-15 17:13  m0rt1s  阅读(1)  评论(0)    收藏  举报