一、类的结构组成

在Java中,一个完整的类通常包含以下组成部分:

public class Person {
    // 1. 属性(成员变量/字段)
    private String name;    // 姓名
    private double height;  // 身高
    private int age;        // 年龄
    
    // 2. 方法(成员方法/行为)
    public void speak() {
        System.out.println(name + "正在说话");
    }
    
    public void run() {
        System.out.println(name + "正在跑步");
    }
    
    public int calculate(int a, int b) {
        return a + b;
    }
}

二、方法详解

1. 方法的基本语法

访问修饰符 返回值类型 方法名(参数类型 参数名, 参数类型 参数名, ...) {
    // 方法体
    [return 返回值;]
}

示例代码:

public class Calculator {
    
    // 无返回值方法
    public void printMessage() {
        System.out.println("这是一个计算方法");
    }
    
    // 有返回值方法
    public int sum(int a, int b) {
        return a + b;
    }
    
    // 多个参数的方法
    public double average(double x, double y, double z) {
        return (x + y + z) / 3.0;
    }
}

// 方法调用示例
Calculator calc = new Calculator();
calc.printMessage();            // 调用无返回值方法
int result = calc.sum(5, 3);    // 调用有返回值方法
System.out.println("结果:" + result);

三、构造方法

1. 构造方法的特点

public class Student {
    private String name;
    private int age;
    
    // 1. 无参构造方法(默认提供)
    public Student() {
        System.out.println("无参构造方法被调用");
    }
    
    // 2. 有参构造方法
    public Student(String name, int age) {
        this.name = name;
        this.age = age;
        System.out.println("有参构造方法被调用");
    }
    
    // 3. 构造方法重载
    public Student(String name) {
        this(name, 18);  // 默认年龄为18
    }
}

// 使用示例
public class Test {
    public static void main(String[] args) {
        Student s1 = new Student();           // 调用无参构造
        Student s2 = new Student("张三", 20); // 调用有参构造
        Student s3 = new Student("李四");     // 调用重载构造
    }
}

构造方法的注意事项:

  1. 构造方法名必须与类名相同

  2. 构造方法没有返回值类型,连void都不写

  3. 一个类默认有无参构造方法

  4. 如果定义了有参构造,则不再自动生成无参构造

  5. 构造方法可以重载

四、this关键字

1. this的三种用法

public class Person {
    private String name;
    private int age;
    
    // 1. 区分成员变量和局部变量
    public void setName(String name) {
        this.name = name;  // this.name指成员变量,name指参数
    }
    
    // 2. 调用本类其他方法
    public void display() {
        this.showInfo();  // 调用本类的showInfo方法
    }
    
    public void showInfo() {
        System.out.println("姓名:" + name + ",年龄:" + age);
    }
    
    // 3. 调用本类其他构造方法
    public Person() {
        this("未知", 0);  // 调用另一个构造方法
    }
    
    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }
}

五、方法重载(Overload)

1. 为什么要使用方法重载?

不重载的问题:

class Polygon {
    // 每个图形都有独立的计算方法名
    public double getCircleArea(double radius) {
        return Math.PI * radius * radius;
    }
    
    public double getTriangleArea(double base, double height) {
        return 0.5 * base * height;
    }
    
    public double getRectangleArea(double width, double height) {
        return width * height;
    }
    
    public double getTrapezoidArea(double top, double bottom, double height) {
        return (top + bottom) * height / 2;
    }
}

使用方法重载改进:

class ShapeCalculator {
    // 使用方法重载,统一方法名
    public double getArea(double radius) {
        return Math.PI * radius * radius;  // 计算圆面积
    }
    
    public double getArea(double base, double height) {
        return 0.5 * base * height;  // 计算三角形面积
    }
    
    public double getArea(double width, double height, String shape) {
        if ("rectangle".equals(shape)) {
            return width * height;  // 计算矩形面积
        }
        return 0;
    }
    
    public double getArea(double a, double b, double h) {
        return (a + b) * h / 2;  // 计算梯形面积
    }
}

// 使用方法
ShapeCalculator calculator = new ShapeCalculator();
double circleArea = calculator.getArea(5.0);  // 调用计算圆面积的方法
double triangleArea = calculator.getArea(3.0, 4.0);  // 调用计算三角形面积的方法
double rectangleArea = calculator.getArea(3.0, 4.0, "rectangle");  // 调用计算矩形面积的方法

方法重载的规则:

  • 方法名必须相同

  • 参数列表必须不同(类型、个数、顺序至少一个不同)

  • 返回类型可以相同也可以不同

  • 与访问修饰符无关

  • 与异常声明无关

六、值传递 vs 引用传递

1. 值传递(基本数据类型)

public class ValuePassingExample {
    public static void main(String[] args) {
        int a = 10;
        int b = 20;
        
        System.out.println("交换前:a = " + a + ", b = " + b);
        swap(a, b);
        System.out.println("交换后:a = " + a + ", b = " + b);
    }
    
    public static void swap(int x, int y) {
        int temp = x;
        x = y;
        y = temp;
        System.out.println("方法内交换:x = " + x + ", y = " + y);
    }
}

输出结果:

交换前:a = 10, b = 20
方法内交换:x = 20, y = 10
交换后:a = 10, b = 20

2. 引用传递(引用数据类型)

class Student {
    String name;
    
    public Student(String name) {
        this.name = name;
    }
}

public class ReferencePassingExample {
    public static void main(String[] args) {
        Student stu1 = new Student("张三");
        Student stu2 = new Student("李四");
        
        System.out.println("交换前:stu1.name = " + stu1.name);
        System.out.println("交换前:stu2.name = " + stu2.name);
        
        swapReference(stu1, stu2);
        
        System.out.println("交换后:stu1.name = " + stu1.name);
        System.out.println("交换后:stu2.name = " + stu2.name);
        
        modifyObject(stu1);
        
        System.out.println("修改后:stu1.name = " + stu1.name);
    }
    
    public static void swapReference(Student a, Student b) {
        Student temp = a;
        a = b;
        b = temp;
    }
    
    public static void modifyObject(Student student) {
        student.name = "王五";
    }
}

输出结果:

交换前:stu1.name = 张三
交换前:stu2.name = 李四
交换后:stu1.name = 张三
交换后:stu2.name = 李四
修改后:stu1.name = 王五

核心区别总结:

特性

值传递

引用传递

传递内容

值的副本

地址的副本

数据类型

基本数据类型

引用数据类型

修改影响

不影响原始值

可以修改对象内容

交换影响

无法交换原始变量

无法交换原始引用

七、局部变量 vs 全局变量

1. 变量作用域示例

public class VariableExample {
    // 全局变量(成员变量)
    private String name = "全局变量";
    private static int count = 0;
    
    public void testMethod() {
        // 局部变量
        String localVar = "局部变量";
        int number = 100;
        
        System.out.println("局部变量:" + localVar);
        System.out.println("局部变量:" + number);
        
        // 可以访问全局变量
        System.out.println("全局变量:" + this.name);
        
        // 局部变量与全局变量同名
        String name = "同名的局部变量";
        System.out.println("局部变量name:" + name);
        System.out.println("全局变量name:" + this.name);
        
        // 代码块中的局部变量
        {
            int blockVar = 200;
            System.out.println("代码块变量:" + blockVar);
        }
        // System.out.println(blockVar);  // 错误!无法访问代码块变量
    }
    
    public void anotherMethod() {
        // 无法访问其他方法的局部变量
        // System.out.println(localVar);  // 编译错误!
        
        // 但可以访问全局变量
        System.out.println("访问全局变量:" + name);
    }
}

2. 变量作用域对比

对比项

全局变量(成员变量)

局部变量

声明位置

类中,方法外

方法、构造方法或代码块内

作用域

整个类(除静态方法)

所在的方法或代码块

生命周期

对象创建到销毁

方法调用到结束

内存位置

堆内存

栈内存

初始值

有默认值

必须显式初始化

修饰符

可以加访问修饰符

不能加访问修饰符

八、static关键字详解

1. 静态变量(类变量)

public class School {
    // 实例变量 - 每个对象独立
    private String studentName;
    private int studentId;
    
    // 静态变量 - 所有对象共享
    public static String schoolName = "清华大学";
    public static int studentCount = 0;
    
    public School(String studentName) {
        this.studentName = studentName;
        this.studentId = ++studentCount;  // 每创建一个学生,计数加1
    }
    
    public void showInfo() {
        System.out.println("学号:" + studentId);
        System.out.println("姓名:" + studentName);
        System.out.println("学校:" + schoolName);
        System.out.println("总人数:" + studentCount);
    }
}

// 使用示例
public class TestSchool {
    public static void main(String[] args) {
        School s1 = new School("张三");
        School s2 = new School("李四");
        School s3 = new School("王五");
        
        s1.showInfo();
        System.out.println("----------------");
        s2.showInfo();
        
        // 通过类名访问静态变量(推荐)
        System.out.println("学校名称:" + School.schoolName);
        
        // 通过对象访问静态变量(不推荐)
        System.out.println("总人数:" + s1.studentCount);
    }
}

2. 静态方法

public class MathUtils {
    // 静态变量
    public static final double PI = 3.1415926;
    
    // 静态方法
    public static int add(int a, int b) {
        return a + b;
    }
    
    public static double circleArea(double radius) {
        return PI * radius * radius;
    }
    
    public static int max(int a, int b, int c) {
        return Math.max(a, Math.max(b, c));
    }
    
    // 实例方法
    public void displayPI() {
        System.out.println("PI的值是:" + PI);
    }
}

// 使用示例
public class TestMath {
    public static void main(String[] args) {
        // 直接通过类名调用静态方法
        int sum = MathUtils.add(5, 3);
        double area = MathUtils.circleArea(2.5);
        int maxValue = MathUtils.max(10, 20, 15);
        
        System.out.println("和:" + sum);
        System.out.println("圆面积:" + area);
        System.out.println("最大值:" + maxValue);
        
        // 实例方法需要通过对象调用
        MathUtils utils = new MathUtils();
        utils.displayPI();
    }
}

3. 静态变量 vs 全局变量对比

特性

静态变量

全局变量(实例变量)

声明方式

使用static修饰

不使用static修饰

内存位置

方法区(静态区)

堆内存

加载时机

类加载时创建

对象创建时创建

访问方式

类名.变量名(推荐)
对象.变量名

对象.变量名

共享性

所有对象共享一份

每个对象独享一份

生命周期

与类共存亡

与对象共存亡

默认值

有默认值

有默认值

九、综合示例

public class BankAccount {
    // 静态变量
    private static double interestRate = 0.03;  // 年利率
    private static int accountCount = 0;        // 账户总数
    
    // 实例变量
    private String accountNumber;
    private String accountHolder;
    private double balance;
    private final int accountId;
    
    // 构造方法
    public BankAccount(String accountHolder, double initialBalance) {
        this.accountHolder = accountHolder;
        this.balance = initialBalance;
        this.accountId = ++accountCount;  // 自动生成账户ID
        this.accountNumber = generateAccountNumber();
    }
    
    // 静态方法
    public static double calculateInterest(double amount, int years) {
        return amount * Math.pow(1 + interestRate, years) - amount;
    }
    
    public static int getAccountCount() {
        return accountCount;
    }
    
    public static void setInterestRate(double newRate) {
        interestRate = newRate;
    }
    
    // 实例方法
    public void deposit(double amount) {
        if (amount > 0) {
            balance += amount;
            System.out.println("存款成功!当前余额:" + balance);
        }
    }
    
    public void withdraw(double amount) {
        if (amount > 0 && amount <= balance) {
            balance -= amount;
            System.out.println("取款成功!当前余额:" + balance);
        } else {
            System.out.println("取款失败!余额不足。");
        }
    }
    
    public void displayAccountInfo() {
        System.out.println("账户ID:" + accountId);
        System.out.println("账号:" + accountNumber);
        System.out.println("户主:" + accountHolder);
        System.out.println("余额:" + balance);
        System.out.println("年利率:" + (interestRate * 100) + "%");
    }
    
    // 私有方法
    private String generateAccountNumber() {
        return "BANK" + String.format("%08d", accountId);
    }
}

// 测试类
public class TestBank {
    public static void main(String[] args) {
        // 创建账户
        BankAccount account1 = new BankAccount("张三", 1000);
        BankAccount account2 = new BankAccount("李四", 5000);
        
        // 显示账户信息
        account1.displayAccountInfo();
        System.out.println("----------------");
        account2.displayAccountInfo();
        
        // 操作账户
        account1.deposit(500);
        account1.withdraw(200);
        
        // 使用静态方法
        System.out.println("账户总数:" + BankAccount.getAccountCount());
        
        double interest = BankAccount.calculateInterest(10000, 5);
        System.out.println("10000元5年利息:" + interest);
        
        // 修改利率
        BankAccount.setInterestRate(0.035);
        System.out.println("利率已调整");
        
        account1.displayAccountInfo();
    }
}

十、总结与最佳实践

1. 方法设计原则

  • 单一职责原则:一个方法只做一件事

  • 命名规范:方法名使用动词开头,如getXXX(), setXXX(), calculateXXX()

  • 参数数量:尽量保持参数数量在5个以内

  • 方法长度:一个方法不要超过50行

2. 变量使用建议

  • 优先使用局部变量

  • 静态变量用于真正需要共享的数据

  • 常量使用static final修饰

  • 避免过度使用全局变量

3. 构造方法建议

  • 提供有意义的无参构造

  • 通过构造方法确保对象完整性

  • 使用构造方法重载提高灵活性

4. 代码组织技巧

  • 将相关的属性组织在一起

  • 将相关的方法组织在一起

  • 使用合适的访问修饰符

  • 添加必要的注释和文档

通过合理使用方法和变量,可以创建出结构清晰、易于维护的Java程序。掌握这些基础知识是成为优秀Java开发者的第一步。

Logo

汇聚全球AI编程工具,助力开发者即刻编程。

更多推荐