全景定位(先在脑子里放一张地图)
Java 是面向对象的语言,所有代码都写在「类」里面。你可以把一个类理解成一个功能盒子,每个盒子里只装两样东西:
属性:盒子里存的数据(比如用户盒子里存姓名、年龄)
方法:盒子能做的事情(比如用户盒子能修改姓名、计算年龄)
简单说:属性是存东西的,方法是干活的,我们写 Java 代码,绝大多数时候都是在写方法。
1. 两大核心特性
1.1 方法签名
💡通俗理解:
就像人的身份证号,是区分不同方法的唯一标识。名字+参数类型不一样,才是不同的方法。
🔴记忆:定义
JVM 区分方法的唯一标识 =方法名 + 参数类型列表
返回值、修饰符、抛出的异常,都不算方法签名。
❌误区:参数名不影响签名。
比如add(int a, int b)和add(int x, int y)是完全相同的方法,不能同时存在,会编译报错。
1.2 方法重载(Overload)
💡通俗理解:
同一个菜谱名“煎蛋”,可以有不同版本:煎1个蛋、煎2个蛋、用鸭蛋煎。你喊“煎蛋”时,厨师会根据你递的原料自动选对应版本。
🔴 记忆:定义
同一个类中,方法名相同,参数列表不同,就叫方法重载。和返回值、修饰符没有关系。
参数列表不同只有3种合法情况:
参数个数不同:
add(int a)和add(int a, int b)参数类型不同:
add(int a)和add(double a)参数类型顺序不同:
add(int a, String b)和add(String b, int a)
❌误区:
只改参数名、只改返回值,都不算重载,会直接编译报错。
1.3 方法重写(Override)
💡通俗理解:
总店有一份“珍珠奶茶”的标准菜谱(父类方法),分店(子类)觉得不够甜,不改名、不改原料,只调整糖量和做法,做出分店版珍珠奶茶。顾客点单时,拿到的是对应分店的版本。
🟡进阶理解:定义
父子类继承关系中,子类写一个和父类方法名、参数列表完全一致的方法,覆盖父类的原有逻辑,这就是方法重写。它是面向对象「多态」的核心实现。
重写规则:两同两小一大
两同:方法名相同、参数列表完全相同
两小:
返回值类型兼容:基本类型必须完全一样;引用类型可以是父类返回类型的子类(比如父类返回Number,子类返回Integer)
抛出的异常范围小于等于父类(只针对受检异常)
一大:子类方法的访问权限,不能比父类更严格(父类是public,子类不能是private)
❌误区:
private方法、static方法都不能被重写,子类写同名方法只是自己的新方法,不是重写。
2. 参数传递机制:值传递
💡通俗理解:
基本类型:你把菜谱复印一份给朋友,朋友在复印件上改,你的原件完全不变。
引用类型:你给朋友一张仓库地址纸条(复印件)。朋友去仓库改了货物包装 → 仓库里的东西真变了;但朋友把纸条改成另一个仓库地址 → 你手里的纸条完全不变。
🔴 记忆:核心规则
Java 里只有值传递,没有引用传递,所有参数传的都是「副本」,只是不同类型的副本内容不一样:
基本类型参数:传的是数值的副本。方法里改参数值,完全不影响外面的原变量。
引用类型参数:传的是对象内存地址的副本。
方法内修改对象的内部属性 → 会影响外面的原对象(因为指向同一个内存)
方法内把参数重新赋值为新对象(new)→ 完全不影响外面的原引用(改的只是副本的地址)
🟡进阶补充:不可变类的特殊情况
String、Integer等不可变类,即使是引用类型,方法内“修改”也不会影响外部。
本质:不可变对象本身不能改,方法里的“修改”其实是让形参指向了新对象,属于「改指向」,不是「改内容」,完全符合值传递规则。
public void test(String s) { s = "新字符串"; // 形参指向了新对象,和外面的原引用无关 }3. 可变参数(Varargs)
💡通俗理解:
就像点菜时“随便加几个小菜”,你可以加0个、1个、5个,后厨用一个托盘(数组)全部装起来给你处理。
🔴记忆
语法:
参数类型... 参数名,比如int... nums本质:底层就是数组,方法里可以完全当数组用
3条硬规则:
一个方法最多只能有一个可变参数
必须放在参数列表的最后一位
调用时可以传0个、1个、多个,也可以直接传数组
🟡进阶:重载匹配优先级
如果同时有「固定参数方法」和「可变参数方法」,会优先匹配固定参数的,可变参数是兜底的。
public void method(int a) {} // 优先匹配这个 public void method(int... a) {} // 固定参数匹配不上才走这个❌误区:
不能和同类型数组参数构成重载,比如method(int... nums)和method(int[] nums)签名相同,会编译报错。
4. 两类特殊方法
4.1 构造方法
💡通俗理解:
品牌奶茶店加盟。每开一加盟家新店(new对象),都要按模板装修、安装设备、招员工,完成初始化。
🔴记忆
作用:专门用来创建、初始化对象,
new对象时会自动调用核心规则:
方法名必须和类名完全一样,大小写都不能错
不能写任何返回值类型,连 void 都不能写,写了就变成普通方法
没手动写构造方法时,编译器会自动生成一个无参的默认构造方法;只要手动写了一个,默认的就消失了
构造方法可以重载,用不同参数创建不同初始状态的对象
🟡进阶补充
构造方法可以用private修饰,作用是禁止外面new对象,只能在类内部创建,典型应用是单例模式。
4.2 main 方法
🔴记忆
作用:Java 程序的唯一入口,JVM 启动程序时会自动找它执行
固定格式,一个字都不能错:
public static void main(String[] args)public:JVM 要全局访问,必须公开static:JVM 调用时还没创建对象,必须属于类本身void:入口不需要给 JVM 返回值String[] args:命令行参数,可以在运行程序时传字符串进去
5. 静态方法 vs 实例方法
💡通俗理解:
静态方法:街边公共电话亭,不需要有房子(对象),谁都能直接打
实例方法:你家座机,必须先有房子(对象),才能用里面的电话
维度 | 静态方法(static修饰) | 实例方法(无static) |
归属 | 属于类本身 | 属于对象实例 |
调用方式 | 直接 | 必须先new对象,通过对象调用 |
能访问的内容 | 只能直接访问静态成员;不能用this/super | 所有成员都能直接访问 |
加载时机 | 类加载时就存在 | 对象创建时才存在 |
🟡进阶理解:为什么静态方法不能被重写
二者绑定机制不同:
静态方法:静态绑定(编译期就确定),看变量的声明类型
实例方法:动态绑定(运行时才确定),看对象的实际类型
代码验证:
class Father { public static void staticMethod() { System.out.println("父类静态方法"); } public void instanceMethod() { System.out.println("父类实例方法"); } } class Son extends Father { public static void staticMethod() { System.out.println("子类静态方法"); } @Override public void instanceMethod() { System.out.println("子类实例方法"); } } // 测试 Father f = new Son(); f.staticMethod(); // 输出:父类静态方法(看声明类型Father) f.instanceMethod(); // 输出:子类实例方法(看实际类型Son)6. 方法在 JVM 中的执行过程
🟢底层原理:入门阶段可跳过,不影响写代码
💡通俗理解:
每次做菜,厨房分配一张临时操作台(栈帧),上面摆原料、草稿纸。菜做好后端出去,操作台就清空腾给下一道菜。
每次调用方法,JVM 都会在虚拟机栈里创建一个「栈帧」压入栈顶,栈帧包含4部分:
局部变量表:存方法的参数、局部变量
操作数栈:做运算的临时空间
动态链接:定位方法的内存地址
返回地址:方法执行完回到调用方的位置
方法执行完,栈帧就出栈销毁,内存自动释放。
⚠️ 注意:递归层级太深,栈帧太多超过栈容量,就会抛出
StackOverflowError栈溢出错误。
7. 方法设计最佳实践
🟡进阶理解:写代码久了自然会有体会,入门先了解即可
💡通俗理解:
好菜谱一页纸写完,步骤清晰不跳跃;原料别太多,容易搞混;过敏原标清楚,名字一看就懂。
单一职责:一个方法只做一件事
短小精悍:尽量控制在50行以内,太长就拆分
参数精简:参数不超过5个,太多就封装成对象
防御式校验:入口处校验参数合法性,提前拦截非法数据
见名知意:动词开头,不用拼音和不明缩写
分支全覆盖:有返回值的方法,所有执行分支都要有return
8. 核心红线汇总表(复习专用)
坑点 | 详细说明 |
返回值不算方法签名 | 不能靠返回值不同做方法重载,直接编译报错 |
private方法不能重写 | 子类看不到父类私有方法,同名只是子类自己的新方法 |
静态方法不能重写 | 静态绑定,子类同名只是隐藏父类方法,没有多态 |
构造方法不能加返回值 | 连void都不能加,加了就变成普通方法 |
Java只有值传递 | 引用类型传的是地址副本,重新赋值不影响外部原引用 |
抽象方法没有方法体 | 连大括号都不能有,必须分号结尾;有抽象方法的类必须是抽象类 |
this()/super()必须在构造方法首行 | 调用本类/父类构造方法必须放第一行,二者不能同时用 |
return之后不能写代码 | 属于不可达代码,直接编译报错 |
静态方法不能用this/super | 静态方法不依赖对象,this代表当前对象,逻辑冲突 |
接口方法默认public abstract | 不写修饰符也是公共抽象的;Java 9之后才支持私有方法 |
ps:我会比较喜欢今天的这种风格,本身学习对于普通人来讲就是一件不容易的事情,是否容易理解还是很重要的,不懂的术语结合起来去解释另外一个术语,真的会打击学习者的兴趣!