Java中的包、类、方法、重载、数组、封装等难点知识点(含例子)

(一)主程序中String[] args的用法

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

第一行是“public class HelloWorld {”。这里,“public”是访问修饰符,表示这个类是公开的;“class”是关键字,用于声明一个类;“HelloWorld”是类名,符合Java的命名规则,拼写时单词AaaaBbbb首字母大写。然后花括号开始类的主体。

第二行是“public static void main(String[] args) {”。这里,“public”同样是访问修饰符,“static”表示这个方法属于类而不是实例,“void”是返回类型,说明main方法不返回任何值。“main”是方法名,这是一个特殊的方法,作为程序的入口点。参数部分“String[] args”是一个字符串数组,用来接收命令行参数。这里的方括号可能写成“String args[]”也是可以的,但用户代码中是“String[ ] args”,两种写法都对,只是风格不同。

第三行是“System.out.println("Hello, World");”。这里,“System”是一个类,属于java.lang包,不需要导入;“out”是System类中的一个静态成员变量,类型是PrintStream;“println”是PrintStream类的方法,用于输出字符串并换行。字符串“Hello, World!”用双引号括起来,是字符串字面量。

第四行是闭合花括号“}”,结束main方法。第五行是另一个闭合花括号,结束类定义。

“static”表示这个方法属于类而不是实例

1. static 方法属于类,而非实例

  • 类级别存在​:当一个方法被声明为 static 时,它属于类本身,而不是类的某个具体对象(实例)。
  • 无需创建对象​:即使没有创建类的实例,也可以直接通过类名调用该方法。

2. 为何能直接通过类名调用?​

  • 内存分配时机​:static 方法在类加载时就被分配内存空间,因此无需依赖对象实例即可访问。
  • 直接访问​:调用时只需写类名 + 方法名,例如 ClassName.staticMethod()

结合代码示例解释

在你的代码中:

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

  • main 方法被声明为 static,因此 JVM(Java 虚拟机)可以直接通过类名 HelloWorld 调用它,无需创建 HelloWorld 的实例。
  • 如果没有 static 修饰,JVM 就无法直接调用 main 方法(因为需要先创建对象,但此时还没有任何对象存在)。

一、​对比实例方法

  • 非静态方法​:属于类的实例,必须通过对象调用。例如:
  • public class MyClass {
        public void instanceMethod() { 
            // 需要先创建对象才能调用
        }
    }
    
    // 调用方式:
    MyClass obj = new MyClass();
    obj.instanceMethod();

    静态方法​:直接通过类名调用。例如:

  • public class MathUtils {
        public static int add(int a, int b) {
            return a + b;
        }
    }
    
    // 调用方式:
    MathUtils.add(3, 5); // 无需创建 MathUtils 对象

    关键区别总结

因此Java 程序的 main 方法必须是静态的。希望这个解释能帮你理解 static 方法的核心意义!

参数部分“String[] args”是一个字符串数组,用来接收命令行参数?

二、参数 String[] args 在主程序中的作用

String[] args 是 Java 程序 main 方法的形参,用于接收命令行输入的参数。它的核心作用是让程序在启动时能够接收并处理用户通过命令行传递的数据。

1. 参数的作用
  • 接收命令行输入​:
    当用户在命令行中运行 Java 程序时,可以在程序名后追加参数,例如:

  • java HelloWorld Alice Bob 123

这些参数会被自动存入 args 数组中:

  • args[0] = "Alice"
  • args[1] = "Bob"
  • args[2] = "123"

  • 程序与外界交互的桥梁​:
    通过 args,程序可以动态响应外部输入(例如配置文件路径、操作类型等),无需修改代码重新编译。

2. 语法形式
  • 标准写法​:String[] args
    最常见的形式,明确表示 args 是一个字符串数组。

  • 等价写法​:String args[]
    语法上与 String[] args 完全等价,但更接近 C/C++ 风格,可读性稍弱。

  • 可变参数写法​:String... args
    Java 5+ 支持的可变参数语法,本质仍是数组,但允许更灵活的调用方式(例如 main("A", "B"))。
    注意​:在 main 方法中,三种写法均合法,但通常优先使用 String[] args

3. 如何使用参数
  • 访问参数​:
    通过数组下标访问,例如 args[0] 表示第一个参数。

  • public class HelloWorld {
        public static void main(String[] args) {
            if (args.length > 0) {
                System.out.println("第一个参数是:" + args[0]);
            } else {
                System.out.println("没有传入参数!");
            }
        }
    }

    遍历所有参数​:
    使用循环处理多个参数:

  • for (int i = 0; i < args.length; i++) {
        System.out.println("参数 " + i + ": " + args[i]);
    }
    4. 关键注意事项
  • 参数长度可能为 0​:
    如果用户未输入任何参数,args 数组长度为 0(args.length == 0),需避免直接访问 args[0] 导致 ArrayIndexOutOfBoundsException

  • 参数类型固定为字符串​:
    所有输入参数均以字符串形式传递,若需数值类型需手动转换(例如 Integer.parseInt(args[0]))。

  • 参数命名灵活性​:
    参数名可以是任意合法标识符(如 String[] input),但 args 是约定俗成的名称。

  • 5. 与程序入口的关系
  • ​**main 方法的特殊性**​:
    Java 虚拟机(JVM)规定,程序的唯一入口必须是 public static void main(String[] args)

    • static:无需创建对象即可调用。
    • String[] args:提供命令行参数的入口。
  • 无参数时的处理​:
    如果程序不需要参数,仍需保留 String[] args 声明,但可以忽略它。

这里,“System”是一个类,属于java.lang包,不需要导入;“out”是System类中的一个静态成员变量,类型是PrintStream;

三、包(Package)在Java中的含义和作用

1.包的定义和作用 
  • 包的定义​:
    包是Java中组织类和接口的机制,类似于文件夹的层级结构。例如:

    • java.lang:包含基础类(如 StringSystem)。
    • java.util:包含工具类(如 ArrayListDate)。
  • 包的作用​:

    • 避免命名冲突​:不同包中可以有同名类(如 com.example.MyClass 和 com.another.MyClass)。
    • 访问控制​:通过包权限修饰符(如 package-private)限制类的可见性。
    • 代码分类管理​:便于大型项目的模块化组织。
  • ​**java.lang 包的特殊性**​:

    • 自动导入​:Java编译器会默认导入 java.lang 包中的所有类(如 SystemString),因此无需手动编写 import java.lang.System;
    • 基础类集中地​:包含Java程序运行的核心类。
2. System 是 java.lang 包中的类
  • 类的归属​:
    System 类是 java.lang 包的一部分,定义在 java.lang.System 路径下。

    • 即使不显式导入,编译器也会自动识别它。
  • 为什么不需要导入?​
    因为 java.lang 是默认导入包,编译器会隐式添加该包的导入语句。

    • 若类在其他包中(如 java.util.Scanner),则需手动导入(import java.util.Scanner;)。
3. out 是 System 类的静态成员变量
  • 静态成员变量的特性​:

    • 属于类,而非实例​:无需创建 System 对象,可直接通过类名访问。
    • 生命周期​:随类加载而初始化,程序结束时销毁。
    • 共享性​:所有代码共享同一个 out 变量。
  • ​**out 的类型**​:
    out 的类型是 PrintStream,它是Java中处理控制台输出的类,提供了 print()println() 等方法。

  • 代码示例​:

  • // 直接通过类名访问静态变量
    PrintStream myOut = System.out; // 等价于 System.out
    myOut.println("Hello"); // 输出 Hello
    4. 结合代码 System.out.println("Hello, World"); 分析
  • ​**System 类**​:

    • 来自 java.lang 包,无需导入。
    • 提供与系统相关的功能(如标准输入、输出、错误流)。
  • ​**out 静态变量**​:

    • System 类中定义的静态成员变量,类型为 PrintStream
    • 代表“标准输出流”(控制台输出)。
  • ​**println() 方法**​:

    • PrintStream 类的方法,用于输出内容并换行。
    • 等价于 System.out.print("Hello, World") + 换行符

四、关键知识点总结

五、类比理解

  • 包 ≈ 文件夹​:
    将相关类放在同一文件夹中,便于管理。例如:

    • java.lang 文件夹 → 存放 System.javaString.java 等基础类。
  • 静态变量 ≈ 共享工具​:
    像“教室里的投影仪”:所有人(线程)共用同一台设备,无需为每个人单独准备。

六、常见问题

  1. 如果我要使用其他包的类怎么办?​
    需要手动导入,例如:

    import java.util.Scanner; // 导入 java.util 包中的 Scanner 类
  2. ​**static 变量和实例变量的区别?​**​

    • 静态变量​:通过类名访问(如 System.out),所有对象共享。
    • 实例变量​:通过对象访问(如 person.name),每个对象独立拥有。
  3. 为什么 java.lang 包默认导入?​
    这是Java语言规范的设计,因为这些类是编程的基础,频繁使用,省略导入简化了代码。

(二)数组的用法

以下是Java中数组的用法和语法的详细说明,并附有相关示例:

一、数组的基本概念

  • 定义​:数组是存储相同类型数据的有序集合,所有元素在内存中连续存放。
  • 特点​:
    • 长度固定(声明时确定,不可动态扩展)。
    • 通过索引​(从0开始)访问元素。
    • 支持多维数组(如二维数组、三维数组)。

二、数组的声明与初始化

1. 声明方式
// 方式1:类型[] 数组名
int[] numbers;

// 方式2:类型 数组名[]
String names[];

2. 初始化方式
​(1) 静态初始化(直接赋值)​
// 声明并初始化
int[] arr1 = {1, 2, 3, 4}; 

// 显式指定类型
String[] arr2 = new String[] {"A", "B", "C"};
(2) 动态初始化(指定长度)
// 先声明后初始化
double[] prices = new double[5]; // 创建长度为5的数组,默认值为0.0

// 声明时初始化
char[] chars = new char[3];
chars[0] = 'H';
chars[1] = 'i';
chars[2] = '!';

三、数组的访问与操作

1. 访问元素
int[] scores = {90, 85, 95};
System.out.println(scores[0]); // 输出第1个元素:90
System.out.println(scores.length); // 输出数组长度:3
2. 遍历数组
// 方式1:for循环
for (int i = 0; i < scores.length; i++) {
    System.out.print(scores[i] + " "); // 输出:90 85 95
}

// 方式2:增强for循环(for-each)
for (int score : scores) {
    System.out.print(score + " "); // 输出:90 85 95
}

四、多维数组

1. 二维数组的声明与初始化
// 声明并初始化
int[][] matrix = {
    {1, 2, 3},
    {4, 5, 6},
    {7, 8, 9}
};

// 动态初始化(3行,每行4列)
int[][] matrix2 = new int[3][4];
2. 遍历二维数组
for (int i = 0; i < matrix.length; i++) {
    for (int j = 0; j < matrix[i].length; j++) {
        System.out.print(matrix[i][j] + " ");
    }
    System.out.println(); // 换行
}
// 输出:
// 1 2 3 
// 4 5 6 
// 7 8 9 

五、数组的常用方法

Java提供了java.util.Arrays工具类来操作数组:

import java.util.Arrays;

int[] arr = {5, 3, 1, 4, 2};

// 1. 排序
Arrays.sort(arr); // arr变为 [1, 2, 3, 4, 5]

// 2. 填充
Arrays.fill(arr, 0); // arr变为 [0, 0, 0, 0, 0]

// 3. 拷贝
int[] copyArr = Arrays.copyOf(arr, 3); // 复制前3个元素

// 4. 二分查找(需先排序)
int index = Arrays.binarySearch(arr, 3); // 返回索引2

六、命令行参数与数组

main方法的参数String[] args是一个字符串数组:

public class CommandLineArgs {
    public static void main(String[] args) {
        for (int i = 0; i < args.length; i++) {
            System.out.println("参数" + i + ": " + args[i]);
        }
    }
}

运行命令:

java CommandLineArgs Hello World 123
# 输出:
# 参数0: Hello
# 参数1: World
# 参数2: 123

七、注意事项

  1. 索引越界​:访问不存在的索引会抛出ArrayIndexOutOfBoundsException

    int[] arr = {1, 2};
    System.out.println(arr[2]); // 抛出异常!

  2. 空指针异常​:未初始化的数组引用会导致NullPointerException

    int[] arr = null;
    System.out.println(arr.length); // 抛出异常!

八、总结

(三)Java中的方法定义与调用

一、方法的定义

1. 语法结构
[访问修饰符] [返回类型] 方法名([参数列表]) {
    // 方法体
    // 执行逻辑
    [return 返回值;] // 如果返回类型非void
}
  • 访问修饰符​:控制方法的可见性(如 publicprivate、默认)。
  • 返回类型​:方法返回的数据类型(如 intString),若无返回值则用 void
  • 方法名​:遵循标识符命名规则(驼峰式,如 calculateSum)。
  • 参数列表​:方法接收的输入数据,多个参数用逗号分隔。
  • 方法体​:包含具体逻辑的代码块。
2. 示例:不同类型的方法
​(1) 无参数、无返回值
public void printHello() {
    System.out.println("Hello, World!");
}
​(2) 有参数、有返回值
public int add(int a, int b) {
    return a + b;
}
(3) 静态方法(类方法)​
public static void printMessage(String msg) {
    System.out.println("消息:" + msg);
}

二、方法的调用

1. 调用方式
  • 直接调用​:通过方法名和参数列表调用。
  • 对象调用​:通过类的实例调用实例方法。
  • 类名调用​:通过类名调用静态方法。
2. 示例代码
public class MethodExample {
    public static void main(String[] args) {
        // 调用静态方法(无需对象)
        printMessage("你好!"); 

        // 调用实例方法(需创建对象)
        MethodExample obj = new MethodExample();
        obj.printHello();

        // 调用带参数的方法
        int sum = obj.add(5, 3);
        System.out.println("5 + 3 = " + sum);
    }

    // 实例方法:无参数、无返回值
    public void printHello() {
        System.out.println("Hello, World!");
    }

    // 实例方法:有参数、有返回值
    public int add(int a, int b) {
        return a + b;
    }

    // 静态方法
    public static void printMessage(String msg) {
        System.out.println("消息:" + msg);
    }
}

三、方法的作用

  1. 代码复用​:将重复逻辑封装成方法,减少冗余代码。

  2. 模块化​:将复杂任务拆分为多个小方法,提高代码可读性和维护性。

    public void processData() {
        readData();
        validateData();
        saveData();
    }

  3. 参数化行为​:通过参数动态控制方法行为。

    printMessage("警告");  // 输出:消息:警告
    printMessage("错误");  // 输出:消息:错误

四、方法重载(Overloading)​

1. 定义
  • 同一类中,方法名相同但参数列表不同(类型、数量、顺序不同)。
  • 与返回类型无关
2. 示例
public class OverloadExample {
    // 方法1:两个整数相加
    public int add(int a, int b) {
        return a + b;
    }

    // 方法2:三个整数相加(参数数量不同)
    public int add(int a, int b, int c) {
        return a + b + c;
    }

    // 方法3:两个双精度浮点数相加(参数类型不同)
    public double add(double a, double b) {
        return a + b;
    }
}

五、注意事项

  1. 参数传递​:Java是值传递(基本类型传递值副本,对象传递引用副本)。

    public void modifyValue(int x) {
        x = 10; // 不影响原始值
    }

  2. 返回值​:若方法声明返回类型非 void,必须保证所有代码路径都有 return 语句。

六、总结

通过掌握方法的定义与调用,可以显著提升代码的组织性和效率!如果有具体场景的应用问题,欢迎进一步讨论 😊

(四)类与对象的语法、知识点和作用的详细说明

        

一、类与对象的核心概念

  • 类(Class)​​:
    类是对象的模板,定义了一类对象的属性(成员变量)​行为(成员方法)​

    • 类是抽象的,描述共性。
    • 例如:Car 类定义汽车的属性(品牌、颜色)和行为(启动、停止)。
  • 对象(Object)​​:
    对象是类的实例,是具体的实体。

    • 对象是具体的,具有实际的数据。
    • 例如:通过 new Car("Toyota", "Red") 创建一辆具体的汽车对象。

二、类的语法与知识点

1. 类的定义
// 语法
[访问修饰符] class ClassName {
    // 成员变量(属性)
    [访问修饰符] 数据类型 变量名;
    
    // 构造方法
    [访问修饰符] ClassName([参数列表]) {
        // 初始化代码
    }
    
    // 成员方法(行为)
    [访问修饰符] 返回类型 方法名([参数列表]) {
        // 方法体
    }
}
2. 示例:定义一个 Car 类
public class Car {
    // 成员变量(属性)
    private String brand;
    private String color;
    
    // 构造方法
    public Car(String brand, String color) {
        this.brand = brand;
        this.color = color;
    }
    
    // 成员方法(行为)
    public void start() {
        System.out.println(brand + " 启动了!");
    }
    
    public void stop() {
        System.out.println(brand + " 停止了!");
    }
    
    // Getter 和 Setter 方法(封装)
    public String getBrand() {
        return brand;
    }
    
    public void setBrand(String brand) {
        this.brand = brand;
    }
}

三、对象的语法与知识点

1. 对象的创建与使用
// 语法
ClassName 对象名 = new ClassName([参数列表]);

// 示例:创建 Car 对象
Car myCar = new Car("Toyota", "Red");
2. 对象的操作
// 调用方法
myCar.start();  // 输出:Toyota 启动了!
myCar.stop();   // 输出:Toyota 停止了!

// 访问成员变量(需通过Getter/Setter)
System.out.println(myCar.getBrand()); // 输出:Toyota
myCar.setBrand("Honda");

四、关键知识点与示例

1. 构造方法
  • 作用​:初始化对象的成员变量。
  • 特点​:
    • 方法名与类名相同。
    • 没有返回值类型(连 void 也没有)。
// 默认构造方法(无参数)
public Car() {
    this.brand = "Unknown";
    this.color = "Black";
}

// 调用不同构造方法
Car car1 = new Car();          // 使用默认构造方法
Car car2 = new Car("BMW", "White"); // 使用带参构造方法

后面会详细介绍构造方法和成员方法的区别(在后面)

2. 封装(Encapsulation)​
  • 作用​:隐藏对象的内部细节,通过公共方法控制访问。
  • 实现​:
    • 将成员变量声明为 private
    • 提供 public 的 getter 和 setter 方法。
      public class BankAccount {
          private double balance; // 私有变量
          
          // Setter 方法(带校验逻辑)
          public void deposit(double amount) {
              if (amount > 0) {
                  balance += amount;
              }
          }
          
          // Getter 方法
          public double getBalance() {
              return balance;
          }
      }

      后面会详细介绍封装内容

3. 静态成员(Static Members)​
  • 作用​:属于类而非对象,所有对象共享同一份静态成员。
  • 示例​:统计对象数量。
    public class Car {
        private static int count = 0; // 静态变量
        
        public Car() {
            count++; // 每次创建对象时计数+1
        }
        
        public static int getCount() { // 静态方法
            return count;
        }
    }
    
    // 使用静态成员
    Car car1 = new Car();
    Car car2 = new Car();
    System.out.println(Car.getCount()); // 输出:2

4. 继承(Inheritance)​
  • 作用​:子类继承父类的属性和方法,实现代码复用。
  • 示例​:ElectricCar 继承 Car
    public class ElectricCar extends Car {
        private int batteryCapacity;
        
        public ElectricCar(String brand, String color, int batteryCapacity) {
            super(brand, color); // 调用父类构造方法
            this.batteryCapacity = batteryCapacity;
        }
        
        // 子类特有方法
        public void charge() {
            System.out.println("正在充电...");
        }
    }

五、类与对象的作用

  1. 代码复用​:通过类模板创建多个对象,避免重复代码。
  2. 模块化​:将复杂系统拆分为多个类,提高可维护性。
  3. 封装​:隐藏实现细节,仅暴露必要接口,增强安全性。
  4. 继承与多态​:支持代码扩展和灵活设计(如 Animal → Dog → Cat

六、总结

通过掌握类与对象,可以高效组织代码,构建复杂的Java应用程序!

(五)构造方法和成员方法的区别

构造方法和成员方法是Java类中两种不同的方法类型,它们的核心区别在于用途、调用时机和语法规则。以下是详细对比:

一、定义与作用

二、语法对比

1. 构造方法
public class Person {
    private String name;
    private int age;

    // 构造方法(无参)
    public Person() {
        this.name = "未知";
        this.age = 0;
    }

    // 构造方法(带参,重载)
    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }
}
2. 成员方法
public class Person {
    // 成员方法:自我介绍
    public void introduce() {
        System.out.println("我叫" + name + ",今年" + age + "岁。");
    }

    // 成员方法:设置年龄(带参数)
    public void setAge(int age) {
        if (age > 0) {
            this.age = age;
        }
    }
}

三、核心区别

1. 初始化 vs 操作
  • 构造方法​:
    用于对象创建时的初始化​(如设置初始姓名、年龄)。

    Person p1 = new Person();          // 调用无参构造方法
    Person p2 = new Person("张三", 25); // 调用带参构造方法

    成员方法​:
    用于对象创建后的操作​(如修改数据、执行逻辑)。

    p2.introduce(); // 输出:我叫张三,今年25岁。
    p2.setAge(30);  // 修改年龄

2. 调用方式
  • 构造方法​:
    通过 new 关键字隐式调用,无法手动调用。

    Person p = new Person(); // 构造方法在 new 时自动触发

  • 成员方法​:
    通过对象显式调用。

    p.introduce(); // 显式调用成员方法

3. 重载与继承
  • 构造方法​:

    • 可以重载​(同名但参数列表不同)。
    • 不能被继承​(子类需通过 super() 调用父类构造方法)。
      public class Employee extends Person {
          private double salary;
      
          // 子类构造方法必须调用父类构造方法
          public Employee(String name, int age, double salary) {
              super(name, age); // 调用父类带参构造方法
              this.salary = salary;
          }
      }

  • 成员方法​:

  • 可以重载重写​(子类覆盖父类方法)。
    public class Employee extends Person {
        // 重写父类方法
        @Override
        public void introduce() {
            System.out.println("我是员工,姓名:" + name);
        }
    }

4. 默认存在性
  • 构造方法​:
    如果没有显式定义任何构造方法,Java会提供默认无参构造方法
    一旦定义了任意构造方法,默认构造方法将消失。

    public class DefaultExample {
        // Java自动提供默认无参构造方法
    }

  • 成员方法​:
    没有默认存在的成员方法,需显式定义。

四、实际应用场景

1. 构造方法
  • 初始化对象属性​:

    public class Book {
        private String title;
        private double price;
    
        public Book(String title, double price) {
            this.title = title;
            this.price = price;
        }
    }

  • 强制必要参数​:
    通过定义带参构造方法,强制用户在创建对象时提供关键参数。

    // 必须提供姓名和年龄
    Person p = new Person("李四", 30);

2. 成员方法
  • 业务逻辑处理​:

    public class Calculator {
        public int add(int a, int b) {
            return a + b;
        }
    }

  • 数据验证与修改​:

    public class Calculator {
        public int add(int a, int b) {
            return a + b;
        }
    }

    五、总结

  • 简单记忆​:

  • 构造方法是对象的“出生证明”,决定对象初始状态。
  • 成员方法是对象的“行为指南”,定义它能做什么

(六)封装

一、封装的定义

封装是面向对象编程的核心思想之一,指将数据(成员变量)​操作数据的方法(行为)​绑定在一起,并对外部隐藏对象的内部实现细节。

  • 核心目标​:
    • 保护数据​:防止外部直接访问或修改对象的内部状态。
    • 控制行为​:通过公共方法限制对数据的非法操作。
    • 提高可维护性​:内部实现可独立修改,不影响外部调用者。

二、封装的语法知识点

1. 访问修饰符(Access Modifiers)​

通过控制成员的可见性实现封装:

2. 封装的实现步骤
  1. ​**将成员变量声明为 private**​:
    防止外部直接访问。

    public class Person {
        private String name; // 私有变量,外部无法直接访问
        private int age;
    }

  2. 提供公共的访问方法(Getter/Setter)​​:
    通过方法间接操作私有变量,并在方法中添加校验逻辑。

    public class Person {
        private String name;
        private int age;
    
        // Getter 方法(读取数据)
        public String getName() {
            return name;
        }
    
        // Setter 方法(修改数据,带校验逻辑)
        public void setName(String name) {
            if (name != null && !name.isEmpty()) {
                this.name = name;
            } else {
                System.out.println("姓名无效!");
            }
        }
    }

  3. 可选:隐藏内部方法​:
    将仅用于内部逻辑的方法设为 private,对外暴露高层接口。

    public class Calculator {
        private void validateInput(int a, int b) {
            if (a < 0 || b < 0) {
                throw new IllegalArgumentException("输入必须为正数");
            }
        }
    
        // 公共方法调用私有校验方法
        public int add(int a, int b) {
            validateInput(a, b);
            return a + b;
        }
    }

三、封装的作用

1. 数据保护
  • 防止非法赋值​:通过 setter 方法校验输入,避免无效数据。
    Person p = new Person();
    p.setName("");    // 触发校验逻辑,输出“姓名无效!”

2. 代码可维护性
  • 内部实现可独立修改​:
    若将 age 的存储方式从 int 改为 String,只需调整 getter/setter,外部调用无需修改。
    public class Person {
        private String age; // 修改为字符串存储
    
        // 对外仍提供相同的接口
        public int getAge() {
            return Integer.parseInt(age);
        }
    }

3. 模块化设计
  • 高内聚、低耦合​:
    每个类专注于自己的职责,外部只需调用公共接口,无需关心内部细节。
4. 控制对象状态
  • 确保对象有效性​:
    在构造方法或 setter 中强制初始化必要属性。
    public class Car {
        private String engine;
    
        public Car(String engine) {
            if (engine == null) {
                throw new IllegalArgumentException("引擎不能为空");
            }
            this.engine = engine;
        }
    }

四、实际应用示例

1. 用户信息管理
public class User {
    private String username;
    private String password;

    // Getter 方法
    public String getUsername() {
        return username;
    }

    // Setter 方法(密码加密存储)
    public void setPassword(String password) {
        this.password = hashPassword(password); // 假设 hashPassword 是加密方法
    }

    private String hashPassword(String password) {
        // 实际应用中替换为加密算法(如 BCrypt)
        return "HASHED_" + password;
    }
}

// 使用封装类
User user = new User();
user.setPassword("123456"); // 密码被加密存储

 2. 银行账户管理

public class BankAccount {
    private double balance;

    public BankAccount(double initialBalance) {
        if (initialBalance < 0) {
            throw new IllegalArgumentException("初始余额不能为负");
        }
        this.balance = initialBalance;
    }

    // 存款(允许正数)
    public void deposit(double amount) {
        if (amount > 0) {
            balance += amount;
        }
    }

    // 取款(不允许透支)
    public void withdraw(double amount) {
        if (amount > 0 && amount <= balance) {
            balance -= amount;
        } else {
            System.out.println("余额不足!");
        }
    }

    public double getBalance() {
        return balance;
    }
}

五、封装 vs 其他 OOP 特性 

六、总结

简单记忆​:

  • 封装就像一个保险箱,外部只能通过特定方式存取物品,内部结构对外完全隐藏。

后续更新抽像、继承和多态等知识点~

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值