JavaSE--方法与变量
一、类的结构组成
在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("李四"); // 调用重载构造
}
}
构造方法的注意事项:
-
构造方法名必须与类名相同
-
构造方法没有返回值类型,连void都不写
-
一个类默认有无参构造方法
-
如果定义了有参构造,则不再自动生成无参构造
-
构造方法可以重载
四、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开发者的第一步。
更多推荐


所有评论(0)