Java开发教程2-类与对象

xianaldai 2026-08-11 16:27 1

本期是Java开发教程系列的第二期,本期主要向各位介绍 Java 面向对象的基础知识——类与对象.若你已经了解类和对象的基本概念,可以跳过本期内容.


每期叠甲:


时间仓促,水平有限,文中难免存在缺点和错误,恳请广大开发者和从业者指正.




一、为什么需要类和对象


第 1 期我们学了变量、方法、数组和集合.但如果要描述"一堆学生",每个学生的姓名、成绩都单独定义变量,代码很快会变成灾难:



String name1 = "小明";

double score1 = 92;

String name2 = "小红";

double score2 = 88;

// 如果有一百个学生呢?这样写根本没法维护,也就是俗称的史山代码.


我们需要一种把"相关的数据 + 相关的操作"打包在一起的方式.Java 用(class)和对象(object)来做这件事:




  • = 一张图纸,规定了这一类东西"长什么样、能干什么"




  • 对象 = 按图纸造出来的具体东西;同一张图纸,可以造出无数个对象




打个比方:Student 类是"学生"的模板,而"小明""小红"是按这个模板造出来的具体对象——每个对象有自己的姓名、成绩,但结构(有哪些字段、哪些方法)都一样.




二、定义类:字段与方法


2.1 一个最简单的类


用代码定义一个"学生"类:



public class Student {

// 字段(也叫属性):描述学生"是什么样"

String name; // 姓名

double score; // 成绩

// 方法:描述学生"能干什么"

void sayHello() {

System.out.println("你好,我是 " + name);

}

}




  • public class Student 声明一个公开的类,类名是 Student




  • 类里面的 namescore字段,保存这个对象的"状态"




  • sayHello()方法,定义这个对象的"行为"




  • 注意:这些代码目前是定义,什么都没运行




2.2 使用对象:new



题外话:这也是有时候说找不到对象就new一个的原因.



要在程序里真正用上,得先造一个对象出来,用 new:



public class Main {

public static void main(String[] args) {

Student s1 = new Student(); // 用 new 造出一个学生对象

s1.name = "小明"; // 给字段赋值

s1.score = 92;

s1.sayHello(); // 调用方法

System.out.println(s1.score);

}

}


运行结果:



你好,我是 小明

92.0




  • new Student() 就是创建对象,s1 是一个指向这个对象的引用




  • 通过 s1.字段名 读/写字段,通过 s1.方法名() 调方法




  • 一个类可以造出任意多个互不干扰的对象:再写 Student s2 = new Student();,s2 是另一个学生






三、构造方法


3.1 为什么需要构造方法


上面的写法要 s1.name = "小明"; s1.score = 92; 两行才设置好初始值,麻烦.


构造方法(constructor)可以在****创建对象的同时****把初始值填好:



public class Student {

String name;

double score;

// 构造方法:方法名和类名一模一样,而且不写返回类型

Student(String name, double score) {

this.name = name;

this.score = score;

}

}


使用方式立刻清爽了:



Student s1 = new Student("小明", 92); // 创建的同时就初始化好了

Student s2 = new Student("小红", 88);


构造方法的三条规则:




  • 方法名必须和类名一样(包括大小写)




  • 不写返回类型(连 void 都不写)




  • 通过 new 调用,不需要也不能手动调用




3.2 无参构造与有参构造




  • 如果你一个构造方法都没写,编译器会免费送一个无参构造,它什么都不干,字段保持默认值(数字是 0、引用是 null)




  • 一旦你自己写了构造方法,免费的无参构造就消失了.此时再写 new Student() 会编译报错——除非你显式再补一个无参构造:





public class Student {

String name;

double score;

// 无参构造

Student() {

}

// 有参构造

Student(String name, double score) {

this.name = name;

this.score = score;

}

}


这样 new Student()new Student("小明", 92) 都能用.两个构造方法名字相同、参数不同,这正是第 1 期讲过的方法重载的典型应用.




四、this 关键字


this 只有一个含义:“当前这个对象”.你可以把它想成对象的名片——谁在跑这段代码,this 就是谁.


4.1 它在构造方法里做什么


再看刚才的构造方法:



Student(String name, double score) {

this.name = name;

this.score = score;

}


执行 new Student("小明", 92) 时,this 就是那个新造出来的"小明"对象.这行代码里出现了两个 name,它们不是一回事:




  • 右边的 name:是参数.参数就在最近的括号里,所以不带 thisname 默认指它




  • 左边的 this.name:是字段.前面加了 this,明确说"这个对象的字段"




所以 `this.name = name;` 的意思就是:**把传进来的参数 name,存进当前对象的 name 字段里**.


这里藏着一条新手最容易懵的规则: 就近原则 :不带 thisname,先找参数,找到就指参数,参数里没有才去找字段.构造方法里参数和字段恰好同名,所以必须靠 this 才能指到字段.


4.2 为什么参数要和字段同名


其实换成别的名字也能写:



Student(String n, double s) {

this.name = n;

this.score = s;

}


参数叫 n/s 当然可以,但这样看不出"这个参数是给哪个字段用的".更常见的习惯是参数和字段同名,再用 this 区分——一眼就知道 name 要存进 name,score 要存进 score.所以这不是必须的语法,而是一种让代码更好读的写法.


4.3 新手速记


this 不只出现在构造方法里,但新手阶段只需要记住构造方法里这一个用法——参数和字段同名时,this.字段 指字段.普通方法里没有同名参数,this 通常不用写,现在先别管它.




五、一个文件一个公开类


这里有个新手常搞混的点,先划重点:被限制的是"public 类"的个数,不是"public 成员"的个数.




  • 一个 .java 文件里只能有一个 public 类,而且这个类的名字必须和文件名一模一样(大小写也要一致)




  • 一个类内部可以有任意多个 public 成员——多个 public 字段、多个 public 方法都没问题:





public class Student { // 文件里唯一的 public 类,必须和文件名 Student.java 一致

public String name; // public 字段,可以有多个

public double score;

public void sayHello() { // public 方法,也可以有多个

System.out.println("你好,我是 " + name);

}

}



  • 同一个文件里还能放**不加 public 的辅助类**,但不能再放第二个 public 类:



public class Main {

public static void main(String\[\] args) {

Helper h = new Helper();

h.go();

}

}

// 同一个文件里可以放非 public 的类,但不能再加一个 public 的

class Helper {

void go() {

System.out.println("我是辅助类");

}

}


如果文件名和 public 类名不一致,编译器会直接报错.


为什么这么规定?为了让编译器能快速找到类:它要找 Student,直接去 Student.java 找就行,不用把整个项目的文件都扫一遍.这个习惯要记牢,后面写工程都是这个规则.




六、三元运算符


接下来介绍一个第 1 期没讲过的小语法——三元运算符 条件 ? 值A : 值B:



String result = score >= 60 ? "及格" : "不及格";


意思是:条件成立(为 true)就取 ? 后面的值,不成立就取 : 后面的值.上面这行等价于:



String result;

if (score >= 60) {

result = "及格";

} else {

result = "不及格";

}


看到区别了吗?三元运算符就是把最简单的 if/else 压缩成一行,适合"根据一个条件选一个值"的场合.分支一多就不要用它,可读性会变差.接下来的小项目你就可以试一试三元运算符.




七、小项目:学生成绩统计


把本期内容串成一个能运行的小程序,共两个文件.


文件一 Student.java:



public class Student {

String name;

double score;

// 构造方法:创建对象时初始化

Student(String name, double score) {

this.name = name;

this.score = score;

}

// 判断是否及格

boolean passed() {

return score >= 60;

}

// 格式化打印自己

void printInfo() {

System.out.println(name + " 成绩 " + score

+ (passed() ? " 及格" : " 不及格"));

}

}


文件二 Main.java:



public class Main {

public static void main(String\[\] args) {

// 创建三个学生对象

Student a = new Student("小明", 92);

Student b = new Student("小红", 58);

Student c = new Student("小刚", 76);

// 把对象装进数组,逐个打印

Student\[\] students = {a, b, c};

for (Student s : students) {

s.printInfo();

}

// 计算平均分

double sum = 0;

for (Student s : students) {

sum += s.score;

}

System.out.println("平均分:" + sum / students.length);

// 找出最高分

Student best = students\[0\];

for (Student s : students) {

if (s.score > best.score) {

best = s;

}

}

System.out.println("最高分:" + best.name);

}

}


运行结果:



小明 成绩 92.0 及格

小红 成绩 58.0 不及格

小刚 成绩 76.0 及格

平均分:75.33333333333333

最高分:小明


这个小程序用到了第 1 期的数组和增强 for,加上本期的类和对象.注意看 students 数组里装的不是数据,而是对象的引用——数组 students[0]students[1]students[2] 分别指向三个 Student 对象.




朝花夕拾:现在能看懂第 1 期的 File 了


第 1 期我们写过这样一行:



File myFile = new File(new xxxxxx);


当时说它"有问题",但没说清问题在哪.学完本期,你能看懂一大半了:




  • new创建对象,new File(...) 就是创建一个 File 对象




  • new xxxxxx 之所以写不出来,是因为 File 的构造方法接收的是一个路径字符串,不是另一个对象.正确写法是:





File myFile = new File("D:\\mc\\mod\\config.txt");


其实 File 本身就是一个类,myFile 就是一个 File 对象——对象,正是本期学的核心概念.




总结


本期我们迈出了面向对象的第一步:




  • 类与对象:类是图纸,对象是按图纸造出来的实体;一个类能造出无数个对象




  • 字段与方法:字段描述对象"是什么样",方法描述对象"能干什么"




  • 构造方法:创建对象时初始化;方法名和类名相同、不写返回类型;一旦写了有参构造,无参构造就没了




  • this:区分字段和同名参数




  • 一个文件一个公开类:public 类名必须和文件名一致




掌握这些,就能用"类"把相关的数据和操作组织起来了.下一期我们将学习分包、注释与访问控制——讲清楚类与类之间怎么组织、谁能访问谁.

最新回复 (15)
  • wintsa 08-11 16:34
    1

    此帖子已被社区举报,现已被临时隐藏。

  • 晚上要做白日梦 08-11 16:36
    2

    好学 ^-^,爱学 ^-^,期待下一节 ^-^

  • 冷月映秋风 08-11 16:38
    3

    对象?哪里有对象?包分配吗?

    开玩笑,感谢做这类教程

  • 此门不通 08-11 16:38
    4

    我很难想象这种发言会出现在L站里 ^-^

  • 当且仅当 08-11 16:38
    5

    我去,梦回十年前,好有感觉,我的青春回来了

  • tero 08-11 16:39
    6

    今夕是何年,竟然还能在这看到这么熟悉又陌生的东西

  • xianaldai 楼主 08-11 16:41
    7

    佬友提了一个很有意思的问题,我觉得您的问题可以换成另一种说法:大家都在用模型生成大段代码的时代,传统的编程语言教学还有意义吗?


    我觉得是有的.


    既然大家都在用模型来生成代码,没有谁比谁出彩,因而大家都只是在所谓的平均水平徘徊.


    这个时候,如果你能发现模型生成代码存在的某些小错误,甚至是某些安全功能:限流/熔断/数据清洗等等做的不到位的地方,有安全隐患的地方,这就是你的能力了


    换一个方面,模型生成代码不总是对的,人类永远是模型代码最后的面壁人.ai写的代码含有安全漏洞的概率,统计学上比人类从业者要高得多.


    不积跬步,无以至千里,我认为打好基础是迈向ai新时代的必要一步

  • 纸雨 08-11 16:42
    8

    死去的回忆又出现了,我不想想起来呀,我有gpt了

  • xianaldai 楼主 08-11 16:43
    9

    可以自己new一个喵


    不过不建议new很多因为占用内存捏

  • 752 08-11 16:43
    10

    老师老师能不能讲讲八股文这些对于我现在来说太遥远了 ^-^

  • 纸雨 08-11 16:45
    11

    支持楼主哦,有人会需要的,谁不是看这玩意过来的

  • xianaldai 楼主 08-11 16:46
    12

    你指的是各个框架还有23种设计模式吗?估计比较靠后了,先得教完全部基础 ^-^

  • 51烦 08-11 16:46
    13

    依旧是小明,但有种时代变了的感觉 ^-^

  • xianaldai 楼主 08-11 16:47
    14

    本来想写张三的但是感觉不太好,最后还是用数学书上的命名吧

  • taku 08-11 16:57
    15

    分配对象需要空间的,如果你没有大house, 分配的对象也是会被回收的

* 帖子来源Linux.do
返回