Java 常用语法极简通关(五):类与对象——字段、方法、构造器、this 与 static

开篇:先解决上一章留下的"数据错位"问题

第四章结尾我们留了个痛点:姓名一个数组、成绩一个数组,靠下标对齐维系关系,一旦错位,程序不报错但结果全错。这一章用类与对象把它根治。先看完整代码------把"工人"封装成一个类,一份数据一个对象,物理上捆在一起:

java 复制代码
public class Worker {
    // 字段:一个工人"有什么"
    String name;
    int score;
    String team;

    // 构造方法:创建对象时一次性把数据填好
    Worker(String name, int score, String team) {
        this.name = name;
        this.score = score;
        this.team = team;
    }

    // 方法:一个工人"能做什么"
    String getLevel() {
        if (score >= 90) {
            return "优秀";
        } else if (score >= 75) {
            return "良好";
        } else if (score >= 60) {
            return "及格";
        } else {
            return "不及格";
        }
    }

    void printInfo() {
        System.out.println(team + " | " + name + " | "
                + score + " 分 | " + getLevel());
    }
}

再写入口类,创建几个对象用起来:

java 复制代码
public class WorkerApp {

    public static void main(String[] args) {
        Worker w1 = new Worker("张伟", 85, "综采一队");
        Worker w2 = new Worker("李强", 92, "综采一队");
        Worker w3 = new Worker("王磊", 58, "掘进三队");

        w1.printInfo();
        w2.printInfo();
        w3.printInfo();

        // 统计有多少个工人对象被创建过
        System.out.println("当前共登记 " + Worker.count + " 名工人");
    }
}

输出:

java 复制代码
综采一队 | 张伟 | 85 分 | 良好
综采一队 | 李强 | 92 分 | 优秀
掘进三队 | 王磊 | 58 分 | 不及格

(最后一行先运行会报错------Worker.count 我们还没写,这正是讲 static 时要补上的,稍等。)

现在姓名、成绩、班组被"焊"在同一个对象里,w1.name 永远对应 w1.score,想错位都没机会。下面把这个类逐层拆开。

第一部分:字段与方法------对象的状态与行为

一个类里装两种东西:

java 复制代码
String name;      // 字段(field):对象的数据,描述"是什么"
int score;

String getLevel() { ... }   // 方法(method):对象的行为,描述"能干什么"
  • 字段 写在类里、方法外,每个对象各有一份。w1 的 score 是 85,w2 的是 92,互不干扰。

  • 方法 就是装在类里的函数,和 C/JS 函数的区别是:它天然属于某个对象,调用时要通过对象来点出来------w1.printInfo()

对照 TypeScript:Worker 类 ≈ 一个 interface + 实现。但 Java 里没有对象字面量,想造数据必须先定义类,这是 Java"重"的地方,也是它结构清晰的原因。

方法的声明格式

java 复制代码
String getLevel() { ... }
// ↑      ↑
// 返回值类型  方法名
void printInfo() { ... }   // void 表示不返回任何东西

两个要点:

  • 声明了返回值类型(非 void),方法里每条路径都必须 return 对应类型的值,少一个 return 编译报错;

  • return 除了交回结果,还有"立即结束方法"的作用,后面的代码不再执行。

方法参数与"值传递"

java 复制代码
void updateScore(int newScore) {
    score = newScore;
}

Java 的参数传递只有值传递 一种:传基本类型,传的是值的副本(方法里改了,外面不受影响);传引用类型,传的是地址的副本(方法里能通过这个地址改到对象内部)。日常开发记住一句就够:int、double 这些传进去随便改不影响外面;对象传进去,改它的字段是会影响外面的。这个考点软考偶尔出现,先有个印象。

第二部分:构造方法------对象出生时的"登记表"

java 复制代码
Worker(String name, int score, String team) {
    this.name = name;
    this.score = score;
    this.team = team;
}

new Worker("张伟", 85, "综采一队") 这行代码干了三件事:在内存里划出一块地方(新对象)→ 调用构造方法把三个值填进字段 → 把对象地址交给 w1。

构造方法的特征,一眼识别:

  1. 方法名和类名完全相同

  2. 没有返回值类型 ------连 void 都不写(写了 void 就变成普通方法了,这是个经典考点);

  3. 只能通过 new 触发,不能像普通方法那样 w1.Worker(...) 调用。

两个必知点:

  • 不写构造方法时,编译器白送你一个无参的new Worker() 可用,字段全是默认值);一旦你写了任何构造方法,这个白送的就收回了 。上面的代码写了三参构造,此时 new Worker() 会编译报错。想让两种都能用,就自己再补一个无参的:
java 复制代码
Worker() {
}
  • 构造方法的典型职责就是初始化字段,顺便可以做校验,比如分数不合法时给个默认值:
java 复制代码
Worker(String name, int score, String team) {
    this.name = name;
    this.score = (score >= 0 && score <= 100) ? score : 0;
    this.team = team;
}

第三部分:this------"我自己"

构造方法里满屏的 this. 是什么意思?

java 复制代码
this.name = name;

当参数名和字段名同名时(都叫 name),name = name 就成了自己赋给自己,字段根本拿不到值。this 指代当前这个对象this.name 明确说"我要的是字段那个 name",右边的 name 则是参数。这句是 Java 里出镜率最高的代码模式之一,IDE 生成构造方法时自动就是这么写的。

this 的第二个常用场景是普通方法里访问自己的字段 。方法内直接使用 score,其实隐含了 this.score,一般省略;需要把自己交给别人时就必须显式写,比如 list.add(this)------"把我自己加进清单"。

第四部分:static------属于"类",不属于"某个对象"

现在补上开头欠的账:统计一共创建了多少个工人。这个数不属于任何一个工人------它是"工人这个类"的公共信息。用 static

java 复制代码
public class Worker {
    static int count = 0;    // 静态字段:全类共享一份

    String name;
    int score;
    String team;

    Worker(String name, int score, String team) {
        this.name = name;
        this.score = score;
        this.team = team;
        count++;             // 每创建一个对象,计数加一
    }
    // ...
}

现在入口里那句 Worker.count 就能跑通了,输出 当前共登记 3 名工人

static 的本质一句话:

不加 static 的成员,每个对象各有一份(实例成员);加了 static 的成员,整个类只有一份,所有对象共享(静态成员/类成员)。

对应的访问方式也不同:

  • 实例成员:对象.成员,如 w1.namew1.printInfo()

  • 静态成员:类名.成员,如 Worker.count(用对象也能点出来,但规范写法是类名)。

main 方法为什么是 static 的?第一章埋的伏笔现在能回答了:程序启动时还没有任何对象,JVM 只能调用"属于类本身"的方法,所以入口必须 static。

还有一个硬限制要记住:静态方法里不能直接访问实例成员 。比如给 Worker 加一个静态方法,里面直接写 System.out.println(name) 会编译报错------静态方法是"类"在干活,此刻根本没有指定"哪个工人",哪来的 name?这也是为什么 main 方法里想干活,都得先 new 出对象来。

常踩的坑(排雷清单)

  1. 给构造方法写了 voidpublic void Worker(...) { } 编译不报错,但它变成了普通方法,new Worker(...) 会报"找不到构造方法"。构造方法没有任何返回值类型

  2. 写了带参构造,又想用无参 new:白送的无参构造已被收回,要么补上无参构造,要么老老实实传参。

  3. 静态方法里访问实例字段 :编译报错。记住静态上下文里没有"当前对象",this 也用不了。

  4. 用对象访问静态成员w1.count 能编译,但容易让人误以为 count 是 w1 私有的。统一用 Worker.count 的写法。

  5. 字段不初始化直接用 :字段有默认值(0 / null)所以不报错,但逻辑可能是错的------int 字段忘了赋值就是 0 分。局部变量则不同,不初始化直接编译报错

  6. 把 static 当全局变量滥用:计数器这种"全类共享"的场景用 static 恰如其分;如果一个数据明显属于"某个对象",加 static 会让所有对象互相串数据,这是新手期很典型的设计错误。

本章小结

  • 类 = 字段(状态)+ 方法(行为);对象 = new 出来的具体实例,每个对象的字段各有一份。

  • 构造方法:名字同类、无返回值类型、由 new 触发;写了带参构造,白送的无参构造就没了。

  • this 指当前对象,构造方法里 this.name = name 是标准模式。

  • static 成员全类共享一份,用 类名.成员 访问;静态方法里不能碰实例成员------main 方法就是最典型的静态方法。

这一章的 Worker 类,字段全部敞开着(w1.score = -999 随便改没人拦),这显然不合理。下一章:方法重载、访问修饰符与封装 ------我们会给 Worker 加上 private 和 getter/setter,讲讲为什么 Java 的字段几乎都是 private 的,顺便把方法重载这个高频考点讲透。

相关推荐
萧瑟余晖2 小时前
Java深入解析篇十七之Spring Security
java·开发语言·spring
jufeng13072 小时前
【系列:手搓自主 AI Agent:Hermes 架构原理剖析 · 第 1 篇】
人工智能·python·架构·agent
月光船幽幽3 小时前
影子模式下保护 logits 不被修改
人工智能·python·算法
离陌在学C#5 小时前
C# 重载与重写:深入理解面向对象编程的核心概念
java·c#
洛阳泰山5 小时前
AI 应用层被 Python 卷成红海,为什么我偏要用 Java 造一个 RAG + 工作流引擎?
java·人工智能·后端
二十雨辰5 小时前
[Java]-Spring面试题
java·开发语言
老马历写记5 小时前
Maven POM 依赖管理总结
java·maven·system·pom·optional
古法安卓5 小时前
Android-车机 GNSS 定位数据接收问题排查
android·java·android studio
_oP_i5 小时前
python 后缀 mjs文件
开发语言·python