Java static 新手入门:写给看不懂 static 的同学
Java static 新手入门写给看不懂 static 的同学大家好今天我们聊一个很多 Java 新手绕不开但又特别容易整懵的关键字static。你别看它只是一个小单词很多人刚学 Java 的时候就是卡在这里明明方法就写在这个类里为什么调不了两个对象改同一个变量为什么数据互相影响有的代码还没进main怎么就先打印了到底什么时候该加static什么时候不该加如果你也有这些困惑今天这篇文章就是写给你的。01 | 先说一个最扎心的报错你大概率遇到过这种红红的报错publicclassStudent{privateStringname;publicvoidsayHi(){System.out.println(Hi, name);}publicstaticvoidmain(String[]args){sayHi();// 直接爆红}}IDE 会提示你Non-static method ‘sayHi()’ cannot be referenced from a static context很多同学看到这句话的第一反应是我方法就在这个类里啊为什么不能调这不是同一个类吗Java 是不是故意刁难我其实不是 Java 针对你是你把“类的东西”和“对象的东西”搞混了。02 | static 的本质其实就一句话如果只让你记住一句话那就是static是属于类的不是属于某一个对象的。听起来还是有点抽象那我换一句更生活化的说法加了static的东西像是班级公告栏全班同学共用没加static的东西像是你自己的笔记本只有你一个人用Java 里很多困惑其实都来自这里你到底是在操作“整个类共用的信息”还是在操作“某一个对象自己的信息”03 | 为什么main里调用自己写的方法会报错这是大一同学最经典的坑之一。你看这个代码直觉上觉得能跑但它就是报错publicclassStudent{publicvoidsayHi(){System.out.println(Hi);}publicstaticvoidmain(String[]args){sayHi();// 报错}}为什么会这样因为main是static的它运行时不依赖任何具体对象。而sayHi()是普通方法它要依赖某个对象才能运行。换句话说编译器根本不知道你说的sayHi()到底是谁的sayHi()。你方法写在Student类里没错但它其实应该是小明的sayHi()小红的sayHi()还是小刚的 sayHi()你没有说清楚。所以编译器直接拒绝你你现在在static环境里连对象都没有不能直接调对象的方法。正确写法publicstaticvoidmain(String[]args){StudentsnewStudent();s.sayHi();// 这样才行}先创建对象再通过对象调用方法。这样 Java 才知道你要调的是“这个对象的sayHi()”。04 | 多个对象操作同一个变量数据为什么互不影响很多同学会问我创建了两个对象然后修改其中一个的属性为什么另一个对象没变比如这样publicclassStudent{Stringname;publicStudent(Stringname){this.namename;}}publicclassMain{publicstaticvoidmain(String[]args){StudentanewStudent(小明);StudentbnewStudent(小红);a.nameJava 小明;System.out.println(a.name);// Java 小明System.out.println(b.name);// 小红}}为什么b.name没变因为name是实例变量。它没有加static所以它是每个对象自己私有的。你可以这样理解a.name是小明自己的笔记本b.name是小红自己的笔记本你在小明本子上写字当然不会自动写到小红本子上。所以这不是 bug是本来就应该这样。05 | 那什么时候会互相影响当变量是static的时候。我们把代码改一下publicclassStudent{staticStringschoolNameJava 大学;Stringname;publicStudent(Stringname){this.namename;}publicvoidshow(){System.out.println(name 来自 schoolName);}}publicclassMain{publicstaticvoidmain(String[]args){StudentanewStudent(小明);StudentbnewStudent(小红);a.show();b.show();// 直接通过类名修改Student.schoolName面向对象学院;System.out.println(----- 修改后 -----);a.show();b.show();}}输出小明 来自 Java 大学 小红 来自 Java 大学 ----- 修改后 ----- 小明 来自 面向对象学院 小红 来自 面向对象学院你看这次就出现“互相影响”了。为什么因为schoolName是static它是所有对象共享的。它不再是某个对象自己的属性而是整个Student类公共的信息。你改的是“公告栏”那所有人看到的当然都会变。06 | 怎么判断一个东西该不该加 static很多同学最怕的其实不是语法而是不知道什么时候该用。我给你一个特别好记的判断标准先问自己三个问题第一这个东西是不是只和“类本身”有关如果是通常适合static。第二这个东西是不是依赖“某个具体对象”才说得清如果是不要static。第三这个数据是不是“所有人共享”的如果是共享状态就可以考虑static。常见判断举例学校名、班级名、系统配置 → 通常适合static学生姓名、成绩、年龄 → 不适合static数学计算、工具方法 → 通常适合static对象自己的行为比如“自我介绍” → 不适合static一句话总结如果它是“类公共的”就可能适合static如果它是“对象私有的”就不要static。07 | 为什么有的代码还没进 main 就先执行了有些同学第一次看到这种代码会很惊讶publicclassDemo{static{System.out.println(静态代码块先执行);}publicstaticvoidmain(String[]args){System.out.println(main 方法执行);}}输出静态代码块先执行 main 方法执行为什么static {}会先执行因为它叫静态代码块。它的作用是在类第一次被加载时执行一次。什么时候会触发类加载比如第一次运行这个类的main第一次使用这个类的静态成员第一次创建这个类的对象所以顺序很好理解类先加载然后才正式进入main。那静态代码块先跑就很合理了。这玩意一般拿来干嘛通常用于类级别初始化比如加载配置初始化共享资源打印一些类加载信息入门阶段你先记住一点就够了static {}是类加载时执行的不是创建对象时执行的。08 | static常见的几个问题Q1static 方法能不能访问非 static 变量不能。除非你先创建对象再通过对象访问。Q2非 static 方法能不能访问 static 变量可以。因为静态变量属于类对象自然也能访问。Q3static 方法能不能用 this不能。this表示当前对象而static方法不一定有对象所以不让用。Q4static 方法能不能被重写不能真正重写。子类可以写一个同名的static方法但那叫隐藏不算多态里的重写。09 | 最容易踩的几个坑坑 1觉得 static 方法不能调用任何方法不是。static方法可以调用其他 static 方法。只是不能直接调用非static方法。坑 2把所有方法都习惯性加 static这也不对。如果方法明显依赖对象的数据就不应该写成static。比如“学生自我介绍”它依赖对象的姓名就别加static。坑 3看到 static 就想到“安静、静态、自动”这些翻译其实容易误导人。你只要记住一个意思就行static 属于类。10 | 结尾先别怕先把代码跑起来最后我想说一句大实话很多新手学static卡住不是因为这个知识点太难而是刚开始接触面向对象脑子里还没建立“类 vs 对象”的概念。所以不要急着背概念。先从真实报错开始先看代码现象再反过头理解为什么。你看懂一个报错往往比背十个定义更有用。如果你是大一同学先记住下面这句话就够了static的东西属于类普通的东西属于对象。