一、引出类变量
需求:有一群小孩👶在玩堆雪人☃️的游戏,不时会有新的小孩加入游戏。请问如何知道现在共有多少人在玩?
public class Child { public static int childCnt = 0; private String name; /** * 返回全部的孩子个数 */ public int getChildCnt() { return childCnt; } public Child(String name) { this.name = name; childCnt++; System.out.println("【" + this.name + "】小朋友加入了游戏"); } }
public class ChildPlaySnowman { public static void main(String[] args) { System.out.println(); Child qy = new Child("庆医"); Child hn = new Child("浩男"); Child ms = new Child("莫松"); Child wf = new Child("王凡"); Child lh = new Child("陆昊"); System.out.println(); System.out.println("共有 " + qy.getChildCnt() + " 个小孩在玩游戏!"); System.out.println("共有 " + Child.childCnt + " 个小孩在玩游戏!"); System.out.println("共有 " + hn.childCnt + " 个小孩在玩游戏!"); } }
🔑 被
static
修饰的成员变量叫做类变量(也叫做静态变量、静态字段)🔑 类变量的值被所有该类的实例共享(所有 Child 类的对象修改 childCnt 变量的值的时候,修改的是同一个 childCnt 变量的值)
🔑 类变量在程序运行过程中只占用一份固定的内存(存储在方法区)
🔑 没有被
static
修饰的成员变量也叫做实例变量🔑 类变量可通过类名访问(推荐)
🔑 类变量可通过对象名访问(不推荐)
🔑 类被初始化的时候类变量会被赋予初始值
🔑 当类第一次被主动使用的时候,类会被初始化
二、类变量(Class Variables)
(1) 官方教程
🌼 When a number of objects are created from the same class blueprint, they each have their own(属于它们自己的) distinct copies of instance variables.
🌾 使用同一个类的蓝图创建多个对象后,这多个对象有它们自己的独特的实例变量。
🌼 Sometimes,you want to have variables that are common to all objects.
🌾有时候,您希望拥有所有对象共有的变量。
🌼 This is accomplished with the static
modifier. Fields that have the static
modifier in their declaration are called static fields or class variables.
🌾 这是通过static
修饰符完成的。在其声明中具有static
修饰符的字段被称为静态字段或类变量。
🌼 They are associated with the class, rather than with any object. Every instance of the class shares a class variable, which is in one fixed location in memory.
🌾 类变量与类相关联,而不与任何对象相关联。同一个类的每一个实例都共享一个类变量,类变量位于内存中的一个固定的位置。
🌼 Any object can change the value of a class variable, but class variables can also be manipulated without creating an instance of the class.
🌾 同一个类的所有对象都可以改变类变量的值,但类变量的值也可以在不创建任何对象实例的时候被操纵。
(2) 类变量细节
✏️ ① 当需要让某个类的所有对象共享一个变量的时候,可以考虑使用类变量(静态变量)
✏️ ② 类变量是该类的所有对象共享的,而实例变量是每个对象独享的
✏️ ③ 被static
修饰的称为类变量或静态变量,否则称为实例变量或属性
✏️ ④ 类变量在类加载(类被初始化:第一次主动使用类)的时候有初始值(即使没有创建对象,只要类被初始化了,类变量就有值了)
三、类方法
(1) 类方法知识点罗列
🌼 The Java programming language supports static methods as well as static variables. Static methods, which have the static
modifier in their declarations, should be invoked with the class name, without the need for creating an instance of the class.
🌾 Java 语言支持静态方法(类方法)和静态变量(类变量)。方法声明的时候有static
关键字的是静态方法,静态方法应该通过类名来调用,无需创建一个类的实例。
🌼 You can also refer to static methods with an object reference,
but this is discouraged because it does not make it clear that they are class methods.
🌾 你也可以通过对象引用来调用静态方法,但并不鼓励这样做,因为它没有明确说明它们是类方法。
🌼 A common use for static methods is to access static fields.
🌾 静态方法的一个常见用途是访问静态字段。
🌼 ① Instance methods can access instance variables and instance methods directly. 实例方法可以直接访问实例变量和调用实例方法。
🌼 Instance methods can access class variables and class methods directly. 实例方法可以直接访问类变量和调用类方法。
class MethodAccessDemo { public static int staticVar = 666; private String instanceVar = "庆医"; public int instanceMethod1() { // instanceVar = 庆医 System.out.println("instanceVar = " + instanceVar); // staticVar = 666 System.out.println("staticVar = " + staticVar); // instanceMethod2() instanceMethod2(); // staticMethod() staticMethod(); return staticVar; } private static void staticMethod() { System.out.println("staticMethod()"); } public void instanceMethod2() { System.out.println("instanceMethod2()"); } } public class Demo { public static void main(String[] args) { MethodAccessDemo instance = new MethodAccessDemo(); int cnt = instance.instanceMethod1(); // staticVar = 666 System.out.println("staticVar = " + cnt); } }
🌼 Class methods can access class variables and class methods directly. 类方法可以直接访问类变量和调用类方法。
🌼 Class methods cannot access instance variables or instance methods directly.【they must use an object reference. Also, class methods cannot use the this keyword as there is no instance for this
to refer to】 类方法不能直接访问实例变量和调用实例方法。【在类方法中必须使用对象引用才能够访问实例变量和调用实例方法,并且类方法中不能使用this
关键字,因为没有实例对象让this
去引用】
(2) 案例(统计捐款金额)
📜 疫情无情,人有情。一方有难,八方支援。新冠病毒☠️肆虐我的家乡,为了帮助我们抗击疫情, 很多人用金钱给予帮助。请编写一个程序,统计总共捐款金额。
/** * 捐款者 */ class Donor { private static double totalMoney; private String name; public Donor(String name) { this.name = name; } public void donate(double val) { if (val <= 0) { System.out.println("金额必须大于0"); return; } System.out.println("\n感谢【" + name + "】资助 " + val + " 元"); totalMoney += val; } public static double getTotalMoney() { return totalMoney; } } public class Demo { public static void main(String[] args) { Donor wf = new Donor("王凡"); wf.donate(10000); Donor zhn = new Donor("张浩男"); zhn.donate(99999); Donor qy = new Donor("庆医"); qy.donate(800); // 总共收到捐款金额:110799.0 System.out.println("\n总共收到捐款金额:" + Donor.getTotalMoney()); } }
(3) 类方法使用场景
✏️ 当某个方法中的代码不涉及任何与对象相关的成员的时候,可以考虑将该方法设计为静态方法
✏️ 如果希望不创建类的实例也可以调用该方法,可考虑将该方法设计为静态方法
✏️ 如 jdk 中的 Math、Arrays、Collections 类
✏️ 工具类中的方法可以考虑设计为静态方法
(4) 类方法注意事项
📖 类方法和实例方法都是随着类的加载而加载的,方法的结构信息存储在方法区。this
是一个隐藏的、位置最靠前的方法参数,this
是指向当前对象的引用,this
与实例相关。类方法中是不能使用this
的【类方法可以通过类名调用,也许通过类名调用类方法的时候对象根本就没有创建(对象没有创建就不可能存在this
)】
📖 实例方法的方法参数中隐藏着一个位置最靠前的方法参数this
(它指向调用该方法的对象)
📖 实例方法和对象相关,只能通过对象名调用,不能通过类名调用
📖 类方法可以通过类名调用,也可以通过对象名调用
四、类变量和类方法 Exercise
第 ① 题
❓ 看下面的代码, 分析打印结果是什么?
public class Demo { static int count; public void count() { System.out.println("count = " + (count++)); } public static void main(String[] args) { // count = 0 new Demo().count(); // count = 1 new Demo().count(); // 2 System.out.println(Demo.count); } }
第 ② 题
❓ 看下面的代码, 修改错误,并思考打印结果:
class Person { private int id; private static int total; public static int getTotalPerson() { /* 1.id 是实例变量 2.getTotalPerson() 是静态方法 3.静态方法中不能够直接访问实例成员 */ // id++; // ERROR return total; } public Person() { /* 1.total 类变量 2.Person() 是构造方法, 构造方法是和实例相关的 3.在构造方法中可以直接访问类变量 */ total++; id = total; } } public class TestPerson { public static void main(String[] args) { // total = 0 System.out.println("total = " + Person.getTotalPerson()); /* 创建 Person 对象会调用构造方法, 构造方法的调用会使得 total 的值 变为1, id 的值也变为1 */ new Person(); // total = 1 System.out.println("total = " + Person.getTotalPerson()); } }
第 ③ 题
❓ 看下面的代码, 修改错误,并思考打印结果:
class Person { private int id; public static int total; public static void setTotalPerson(int total) { /* 1.setTotalPerson() 是类方法 2.类方法中坚决不能使用 this 关键字 */ // this.total = total; // ERROR Person.total = total; } public Person() { total++; id = total; } } public class TestPerson { public static void main(String[] args) { Person.setTotalPerson(1); new Person(); // 2 System.out.println(Person.total); } }
五、深入介绍 main() 方法
(1) 电影 Hello World
❤️ 即使世界毁灭,我也想再见你一面 ❤️
❤️为了再见你一面,我愿意重启整个世界❤️
这是日本动画电影《Hello World》里面的台词
✏️ 在京都居住的16岁内向男高中生👦直实的面前,突然出现从10年后穿越而来的自己。
✏️ 未来的直实告诉他,自己不久便会与瑠璃相爱,可是之后烟花🎆大会时瑠璃却会因为一场事故意外成为植物人。
✏️ 一心为拯救初恋的直实与十年后的自己并肩作战,卷入了这场现实与虚拟的记忆世界,经历了一系列超乎想象的事情。
✏️ 原本怯懦的高中生直实燃生了即使世界毁灭,我也想再见你一面的勇气。
✏️ 十年后穿越而来的直实也终于说出了深藏心底的那句我一直爱你 …
赶快去看看吧!🍀① 为了浪漫的台词【即使世界毁灭,我也想再见你一面;为了再见你一面,我愿意重启整个世界】;🍀② 为了刻在程序开发者心中的 Hello World!
(2) Hello World!
📃 学习一门新的编程语言的时候,大多数人的第一个程序一般都是【Hello World】,Java 的【HelloWorld】程序如下所示:
public class HelloWorld { public static void main(String[] args) { // Hello World! System.out.println("Hello World!"); } }
📃 当你第一次编写并运行了 Java 中的【HellowWorld】程序后,你便用 Java 语言和计算机打了一个招呼,有了一个美好的邂逅。
📃 这美好的邂逅是在 Java 的入口方法
main()
方法中进行的📃 但对
main()
方法还没有一个完美的介绍📃 下面深入介绍一下 Java 的入口方法:
public static void main(String[] args){}
(3) 深入介绍 main() 方法
public class HelloWorld { public static void main(String[] args) { for (int i = 0; i < args.length; i++) { System.out.println("parameter" + (i + 1) + ": " + args[i]); } } }
📖 ① public:JVM 需要调用类的 main()
方法 (入口方法),所以该方法的访问权限必须是public
📖 ② static:JVM 调用main()
方法的时候无需创建对象,所以是static
📖 ③ String[]:main()
方法接收 String 数组类型的参数,该数组中保存了执行 java 命令时传递的参数
👑 java 命令:运行 class 文件
👑 love、study、handsome 被放在字符串数组 args 中
👑 参数名 args 只是一个标识,写成其他的参数名也是可以的(下面的代码把 args 改为了 canShu 也是正确的)
public class HelloWorld { public static void main(String[] canShu) { for (int i = 0; i < canShu.length; i++) { System.out.println("parameter" + (i + 1) + ": " + canShu[i]); } } }
📖 ④ 在 main() 方法中可以直接调用 main() 方法所在类的静态方法或访问静态属性,但不能直接访问或调用实例成员,只有创建该类的对象后才能访问实例成员
结束!若有错误,请不吝赐教!