方法与面向对象基础

上一篇我们学了 Java 的基础语法,所有代码都写在 main 方法里。但真实的程序不可能把所有逻辑塞在一个方法中,我们需要把代码拆分成多个方法(函数),还需要用类和对象来组织代码。

这篇就来讲这两件事。

方法(函数)

方法就是一段可以重复调用的代码块,给它一个名字,需要的时候调用就行。其他语言一般叫「函数」,Java 里叫「方法」,意思一样。

定义与调用

一个方法由返回类型、方法名、参数列表和方法体组成:

现阶段方法前面先加个 static,这样就能在 main 方法中直接调用。等后面讲了类和对象,你就明白什么时候该加 static、什么时候不加了。

方法重载

Java 允许定义多个同名方法,只要参数列表不同(参数个数不同或类型不同)就行,这叫方法重载(Overload):

Java 会根据你传入的参数自动选择调用哪个方法。注意,只靠返回类型不同是不行的,必须参数列表有区别。

值传递

如果你学过 C++,应该听说过指针/引用的概念,把指针/引用传入函数,那么就可以在函数内直接修改这个对象的值。

但是 Java 的参数传递只有值传递,没有指针传递。

什么意思呢?基本类型传递的是值的副本,在方法内修改参数不会影响外面的变量:

简单记:基本类型(intdouble 等)传的是副本,改了白改。数组、对象这些引用类型传的也是副本,但副本和原变量指向同一个对象,所以修改对象内容是生效的

可变参数

如果参数个数不确定,可以用 ... 语法:

可变参数本质上就是一个数组,所以在方法内部可以用 for-each 遍历。一个方法最多只能有一个可变参数,而且必须放在参数列表的最后。

类与对象

Java 是面向对象的语言,类(Class)是组织代码的基本单位。前面我们一直在用 public class Main,但还没真正理解过它。

什么是类和对象

简单来说,类是一个模板,对象是根据模板创建出来的实例。

比如「学生」是一个类,它定义了学生有哪些属性(姓名、年龄)和行为(自我介绍)。而「张三」「李四」是具体的学生对象。

new Student() 就是根据 Student 这个模板创建了一个对象。每个对象有自己的 nameage,互不干扰。

构造方法

每次 new 完还要逐个赋值太麻烦,构造方法可以在创建对象的同时初始化:

构造方法里的 this.name = name 用到了 this 关键字。this 指向当前对象本身,当参数名和字段名相同时,用 this.name 来区分「对象的字段」和「方法的参数」。

构造方法重载

一个类可以有多个构造方法,只要参数列表不同就行,这叫构造方法重载

而且 this 除了用 this.name 访问字段,还可以用 this(...) 调用同一个类里的另一个构造方法:

这里定义了三个参数不同的构造方法,new 的时候 Java 会根据你传的参数自动匹配对应的那个。

注意 this(name, 18) 这种写法,它的意思是调用同一个类里的另一个构造方法。这样初始化逻辑只写一遍,参数少的构造方法把活「委托」给参数多的,避免重复代码。

不过有个限制:this(...) 必须写在构造方法的第一行,否则编译器会报错。

还有一点:如果你没写任何构造方法,Java 会自动提供一个无参的默认构造方法,所以前面「类和对象」那个例子里 new Student() 不传参数也能用。

但只要你手动写了任何一个构造方法,这个默认的就没了。所以如果你写了带参数的构造方法,又想支持 new Student(),就得像上面一样自己加一个无参版本。

static 关键字

static 表示「属于类本身」而不是「属于某个对象」。

现在回头看 public static void main,就好理解了:main 是一个静态方法,Java 启动时不需要创建对象就能直接调用它。前面我们定义的辅助方法也加了 static,就是因为要在 staticmain 方法里直接调用。

访问修饰符

Java 有三个访问修饰符来控制代码的可见性:

修饰符可见范围
public任何地方都能访问
private只有类内部能访问
protected类内部和子类能访问

不写修饰符的话,默认是包级别可见(同一个包内可以访问)。

把字段设为 private,然后通过 public 方法来操作,这是面向对象中「封装」的基本思想。好处是外部代码无法随意修改对象内部的数据,比如不能把余额直接改成负数。

异常处理

Java 用 try-catch 来处理运行时可能发生的错误:

Java 的异常分两种:

  • 受检异常(Checked Exception):编译器强制你处理,比如 IOException。方法签名要加 throws,调用时必须 try-catch 或继续 throws
  • 非受检异常(Unchecked Exception):RuntimeException 及其子类,比如 NullPointerExceptionArrayIndexOutOfBoundsException。不强制处理。

算法题中基本不需要写 try-catch,但看框架代码时会经常遇到。

小结

这篇讲了两个核心概念:

方法让你把代码拆成可复用的小块,避免重复。类和对象让你把数据和操作封装在一起,是 Java 组织代码的基本方式。

学到这里,你已经能看懂大部分 Java 代码的结构了。下一篇我们来学 Java 中最常用的数据结构,这是刷算法题的核心装备。