第一部分:数组
1. 数组的基本概念
Q: 什么是数组?数组与变量有什么区别?
A: 数组是一个数据容器,可用来存储一批同类型的数据。
| 特性 | 变量 | 数组 |
|---|---|---|
| 存储数量 | 单个数据 | 多个同类型数据 |
| 定义方式 | int a = 10; |
int[] arr = {10, 20, 30}; |
| 适用场景 | 零散数据 | 批量数据(如全班成绩、图片像素) |
// 变量:只能存一个值
int score1 = 85;
int score2 = 90;
int score3 = 78;
// ... 需要60个变量存全班成绩,太繁琐!
// 数组:一个容器存多个值
int[] scores = {85, 90, 78, 92, 88, 95}; // 一行代码搞定
System.out.println("第1个学生成绩:" + scores[0]); // 85
System.out.println("第3个学生成绩:" + scores[2]); // 78
2. 数组的静态初始化
Q: 数组静态初始化的语法格式是什么?有几种写法?
A: 静态初始化:声明数组的同时直接赋值。
三种写法:
| 写法 | 语法 | 推荐度 |
|---|---|---|
| 标准写法 | int[] arr = new int[]{1, 2, 3}; |
⭐⭐⭐ |
| 简化写法1 | int[] arr = {1, 2, 3}; |
⭐⭐⭐⭐⭐(最常用) |
| 简化写法2 | int arr[] = {1, 2, 3}; |
⭐⭐(不推荐) |
public class ArrayStaticInit {
public static void main(String[] args) {
// 方式1:标准写法
int[] ages1 = new int[]{12, 24, 36};
// 方式2:简化写法(推荐!)
int[] ages2 = {12, 24, 36};
// 方式3:C语言风格(不推荐)
int ages3[] = {12, 24, 36};
// 其他类型数组
double[] moneys = {666.66, 999.99, 534.0, 687.6};
String[] names = {"张三", "李四", "王五"};
// 注意:数组一旦创建,长度固定,类型固定
// ages2 = {1, 2, 3, 4}; // 编译报错!不能重新赋值简化写法
ages2 = new int[]{1, 2, 3, 4}; // 正确:标准写法可以重新赋值
}
}
3. 数组的动态初始化
Q: 什么是数组的动态初始化?与静态初始化有什么区别?
A: 动态初始化:先指定数组长度,后续再赋值。
| 特性 | 静态初始化 | 动态初始化 |
|---|---|---|
| 时机 | 创建时就知道具体数据 | 创建时不知道具体数据,只知道长度 |
| 语法 | int[] arr = {1, 2, 3}; |
int[] arr = new int[3]; |
| 初始值 | 指定的值 | 默认值(0, 0.0, false, null) |
默认值规则:
| 数据类型 | 默认值 |
|---|---|
byte/short/int/long |
0 |
float/double |
0.0 |
char |
'\u0000'(空字符) |
boolean |
false |
| 引用类型(String等) | null |
import java.util.Scanner;
public class ArrayDynamicInit {
public static void main(String[] args) {
// 场景:录入4名学生的成绩,事先不知道具体分数
// 1. 动态初始化:指定长度4
double[] scores = new double[4];
// 查看默认值
System.out.println(scores[0]); // 0.0
System.out.println(scores[1]); // 0.0
// 2. 后续赋值(通过键盘录入)
Scanner sc = new Scanner(System.in);
for (int i = 0; i < scores.length; i++) {
System.out.print("请输入第" + (i+1) + "名学生成绩:");
scores[i] = sc.nextDouble(); // 逐个赋值
}
// 3. 打印结果
for (int i = 0; i < scores.length; i++) {
System.out.println("第" + (i+1) + "名成绩:" + scores[i]);
}
}
}
4. 数组的访问与长度
Q: 如何访问数组元素?数组的长度如何获取?最大索引是多少?
A:
| 操作 | 语法 | 示例 |
|---|---|---|
| 访问元素 | 数组名[索引] |
arr[0] 获取第1个元素 |
| 修改元素 | 数组名[索引] = 值 |
arr[0] = 100 |
| 获取长度 | 数组名.length |
arr.length |
| 最大索引 | 数组名.length - 1 |
最后一个元素的索引 |
public class ArrayAccess {
public static void main(String[] args) {
int[] arr = {10, 20, 30, 40, 50};
// 访问元素(索引从0开始)
System.out.println(arr[0]); // 10
System.out.println(arr[2]); // 30
System.out.println(arr[4]); // 50(最后一个元素)
// 修改元素
arr[2] = 300;
System.out.println(arr[2]); // 300
// 获取长度
System.out.println("数组长度:" + arr.length); // 5
// 最大索引 = 长度 - 1
System.out.println("最大索引:" + (arr.length - 1)); // 4
// 常见错误:索引越界
// System.out.println(arr[5]);
// ArrayIndexOutOfBoundsException:索引5超出范围(0-4)
// 安全访问:先判断索引是否合法
int index = 5;
if (index >= 0 && index < arr.length) {
System.out.println(arr[index]);
} else {
System.out.println("索引" + index + "不合法!");
}
}
}
5. 数组的遍历
Q: 什么是数组遍历?如何实现?
A: 数组遍历:将数组中的元素逐个取出进行处理。
实现方式:
// 标准for循环遍历(最常用)
for (int i = 0; i < arr.length; i++) {
System.out.println(arr[i]);
}
// 增强for循环(foreach,后续学习)
for (int num : arr) {
System.out.println(num);
}
public class ArrayTraversal {
public static void main(String[] args) {
int[] arr = {100, 19, 99, 88, 200};
// 基础遍历
System.out.println("=== 基础遍历 ===");
for (int i = 0; i < arr.length; i++) {
System.out.println("索引" + i + "的值:" + arr[i]);
}
// 遍历应用1:求和
int sum = 0;
for (int i = 0; i < arr.length; i++) {
sum += arr[i];
}
System.out.println("总和:" + sum); // 506
// 遍历应用2:查找元素索引
int target = 88;
int index = -1; // -1表示未找到
for (int i = 0; i < arr.length; i++) {
if (arr[i] == target) {
index = i;
break; // 找到后立即退出
}
}
System.out.println(target + "的索引:" + index); // 3
// 遍历应用3:求最大值和最小值
int max = arr[0]; // 假设第一个最大
int min = arr[0]; // 假设第一个最小
for (int i = 1; i < arr.length; i++) {
if (arr[i] > max) max = arr[i]; // 发现更大的
if (arr[i] < min) min = arr[i]; // 发现更小的
}
System.out.println("最大值:" + max); // 200
System.out.println("最小值:" + min); // 19
}
}
6. 数组工具类Arrays
Q: 如何快速打印数组内容?Arrays工具类有什么常用方法?
A: Arrays是Java提供的数组工具类,位于 java.util包。
| 方法 | 作用 | 示例 |
|---|---|---|
Arrays.toString(arr) |
将数组转为字符串 | [1, 2, 3] |
Arrays.sort(arr) |
对数组排序 | 升序排列 |
Arrays.binarySearch(arr, key) |
二分查找 | 返回索引或负数 |
import java.util.Arrays;
public class ArraysDemo {
public static void main(String[] args) {
double[] moneys = {666.66, 999.99, 534.0, 687.6};
// 直接打印数组:输出地址值
System.out.println(moneys); // [D@4eec7777(无意义)
// Arrays.toString():美观打印数组
System.out.println(Arrays.toString(moneys));
// [666.66, 999.99, 534.0, 687.6]
// 其他常用方法
int[] arr = {3, 1, 4, 1, 5, 9, 2, 6};
// 排序
Arrays.sort(arr);
System.out.println(Arrays.toString(arr)); // [1, 1, 2, 3, 4, 5, 6, 9]
// 二分查找(必须先排序)
int index = Arrays.binarySearch(arr, 5);
System.out.println("5的索引:" + index); // 5
}
}
7. 数组作为方法参数和返回值
Q: 数组可以作为方法参数吗?可以作为返回值吗?
A: 可以! 数组是引用数据类型,作为参数传递的是地址,作为返回值也是返回地址。
import java.util.Arrays;
import java.util.Random;
public class ArrayMethod {
public static void main(String[] args) {
// 1. 数组作为参数
int[] scores = {85, 90, 78, 92, 88};
int total = sum(scores); // 传入数组
System.out.println("总分:" + total); // 433
// 2. 数组作为返回值
int[] randomArray = generateRandomArray(5); // 返回数组
System.out.println("随机数组:" + Arrays.toString(randomArray));
}
// 数组作为参数:求和
public static int sum(int[] arr) {
int sum = 0;
for (int i = 0; i < arr.length; i++) {
sum += arr[i];
}
return sum;
}
// 数组作为返回值:生成指定长度的随机数组
public static int[] generateRandomArray(int n) {
int[] arr = new int[n];
Random r = new Random();
for (int i = 0; i < arr.length; i++) {
arr[i] = r.nextInt(100) + 1; // 1-100随机数
}
return arr; // 返回数组
}
}
第二部分:面向对象快速入门
8. 类与对象的基本概念
Q: 什么是类?什么是对象?类和对象的关系是什么?
A:
| 概念 | 说明 | 类比 |
|---|---|---|
| 类(Class) | 对象的设计图/模板,定义对象有哪些属性和行为 | 汽车设计图纸 |
| 对象(Object) | 类的具体实例,根据类创建出来的实体 | 一辆具体的汽车 |
| 属性 | 对象的数据(特征) | 颜色、品牌、价格 |
| 方法 | 对象的行为(功能) | 启动、加速、刹车 |
关系:类是对象的模板,对象是类的实例。一个类可以创建多个对象。
// 第一步:定义类(设计图)
public class Star {
// 属性(成员变量):描述对象的特征
String name; // 姓名
int age; // 年龄
double height; // 身高
double weight; // 体重
// 方法(成员方法):描述对象的行为
public void sayHello() {
System.out.println("大家好,我是" + name);
}
}
// 第二步:创建对象(根据设计图造汽车)
public class Test {
public static void main(String[] args) {
// 创建第一个明星对象
Star s1 = new Star(); // new关键字创建对象
s1.name = "赵丽颖"; // 给属性赋值
s1.age = 36;
s1.height = 165.0;
s1.weight = 44.6;
s1.sayHello(); // 调用方法:大家好,我是赵丽颖
// 创建第二个明星对象(同一个类,不同对象)
Star s2 = new Star();
s2.name = "杨幂";
s2.age = 37;
s2.height = 166.5;
s2.weight = 45.0;
s2.sayHello(); // 大家好,我是杨幂
}
}
9. 对象的内存存储原理
Q: 对象在内存中是如何存储的?为什么直接打印对象名显示的是地址?
A: JVM内存区域:
| 区域 | 存储内容 |
|---|---|
| 方法区 | 类的字节码(.class文件) |
| 栈内存 | 局部变量、方法执行 |
| 堆内存 | new出来的对象 |
对象存储原理:
new Star()在堆内存中创建对象,分配空间- 对象在堆中有唯一的地址值
Star s1是栈内存中的变量,存储的是堆中对象的地址- 直接打印
s1,打印的是地址值(如Star@6d06d69c)
public class MemoryDemo {
public static void main(String[] args) {
// 1. 加载Star类到方法区
// 2. new Star()在堆内存创建对象,包含name,age,height,weight
// 3. s1是栈内存变量,存储堆中对象的地址
Star s1 = new Star();
System.out.println(s1); // Star@6d06d69c(地址值)
// 通过地址找到堆中的对象,修改属性
s1.name = "赵丽颖";
s1.age = 36;
// s2是另一个对象,在堆中有独立的空间
Star s2 = new Star();
System.out.println(s2); // Star@7852e922(不同地址)
// s1和s2互不影响
s2.name = "杨幂";
System.out.println(s1.name); // 赵丽颖
System.out.println(s2.name); // 杨幂
}
}
内存示意图:
栈内存(变量) 堆内存(对象)
s1 ──────────────→ Star对象1(name="赵丽颖", age=36...)
地址:0x6d06d69c
s2 ──────────────→ Star对象2(name="杨幂", age=37...)
地址:0x7852e922
10. 面向对象封装数据与方法
Q: 如何在类中封装数据和对数据的操作?有什么好处?
A: 封装:将数据(属性)和操作数据的方法放在同一个类中。
好处:
- 代码复用:方法可以被多个对象调用
- 逻辑清晰:数据和相关操作在一起
- 易于维护:修改只需改一处
// 未封装:数据和操作分离(不好)
public class StudentBad {
String name;
double chinese;
double math;
}
// 每次都要在外部计算,代码重复
StudentBad s1 = new StudentBad();
s1.name = "播妞";
s1.chinese = 100;
s1.math = 100;
System.out.println(s1.name + "总分:" + (s1.chinese + s1.math)); // 重复代码
System.out.println(s1.name + "平均分:" + (s1.chinese + s1.math) / 2);
// 封装后:数据和操作在一起(好)
public class Student {
// 数据
String name;
double chinese;
double math;
// 操作数据的方法
public void printTotalScore() {
System.out.println(name + "的总成绩:" + (chinese + math));
}
public void printAverageScore() {
System.out.println(name + "的平均成绩:" + (chinese + math) / 2);
}
}
// 使用:简洁,无重复代码
Student s1 = new Student();
s1.name = "播妞";
s1.chinese = 100;
s1.math = 100;
s1.printTotalScore(); // 直接调用方法
s1.printAverageScore();
Student s2 = new Student();
s2.name = "播仔";
s2.chinese = 59;
s2.math = 99;
s2.printTotalScore(); // 同样的方法,不同对象调用
s2.printAverageScore();
11. 面向对象编程的注意事项
Q: 使用对象时有哪些重要注意事项?
A:
| 注意事项 | 说明 | 代码示例 |
|---|---|---|
| 打印对象显示地址 | 直接打印对象名显示内存地址 | System.out.println(s1); // Star@6d06d69c |
| 属性有默认值 | 未赋值时JVM自动给默认值 | int默认 0,String默认 null |
| 各对象独立 | 一个类创建的多个对象,属性互不影响 | 修改 s1.name不影响 s2.name |
| 类不是必须有所有成员 | 根据需求定义属性和方法 | 可以只有属性,或只有方法 |
public class ObjectNotice {
public static void main(String[] args) {
Star s1 = new Star();
// 1. 直接打印对象:显示地址值
System.out.println(s1); // com.itheima.Star@6d06d69c
// 2. 属性未赋值时有默认值
System.out.println(s1.name); // null(String默认值)
System.out.println(s1.age); // 0(int默认值)
System.out.println(s1.height); // 0.0(double默认值)
// 3. 各对象相互独立
s1.name = "赵丽颖";
s1.age = 36;
Star s2 = new Star();
s2.name = "杨幂";
s2.age = 37;
System.out.println(s1.name); // 赵丽颖(不受影响)
System.out.println(s2.name); // 杨幂
// 4. 可以只定义需要的属性和方法
// 有些类可能只有属性(如DTO数据传输对象)
// 有些类可能只有方法(如工具类)
}
}
12. 面向对象编程的本质
Q: 什么是面向对象编程(OOP)?其核心思想是什么?
A: 面向对象编程(Object-Oriented Programming, OOP):
- 将现实世界的事物抽象为程序中的对象
- 万物皆对象:人、动物、汽车、手机等都是对象
- 谁的数据谁存储:相关数据封装在对应的类中
核心思想:
- 抽象:从现实事物中提取特征(属性)和行为(方法)
- 封装:数据和方法封装在类中
- 复用:通过创建多个对象复用代码
// 现实世界:手机
// 特征:品牌、价格、颜色
// 行为:打电话、拍照、上网
// 程序中:手机类
public class Phone {
// 属性(特征)
String brand; // 品牌
double price; // 价格
String color; // 颜色
// 方法(行为)
public void call(String number) {
System.out.println(brand + "手机正在拨打:" + number);
}
public void takePhoto() {
System.out.println(brand + "手机正在拍照");
}
}
// 使用:创建多个手机对象
public class PhoneTest {
public static void main(String[] args) {
Phone p1 = new Phone();
p1.brand = "iPhone";
p1.price = 9999.0;
p1.color = "黑色";
p1.call("13800138000"); // iPhone手机正在拨打:13800138000
Phone p2 = new Phone();
p2.brand = "华为";
p2.price = 6999.0;
p2.color = "白色";
p2.takePhoto(); // 华为手机正在拍照
}
}