项目代码
https://github.com/yinhai1114/Java_Learning_Code/tree/main/IDEA_Chapter10/src/com/yinhai/static_
一、类变量的引出
有一群小孩在玩堆雪人,不时有新的小孩加入,请问如何直到现在共有多少人在玩,编写程序解决
package com.yinhai.static_;
public class ChilGame {
public static void main(String[] args) {
Child child0 = new Child("xiaohuang");
Child child1 = new Child("xiaowang");
Child child2 = new Child("xiaoming");
Child child3 = new Child("xiaobai");
Child child4 = new Child("xiaoqing");
int count = 0;
child0.joinGame();
count++;
child1.joinGame();
count++;
child2.joinGame();
count++;
child3.joinGame();
count++;
child4.joinGame();
count++;
System.out.println("现在有" + count + "个小孩加入了游戏");
}
}
class Child{
private String name;
public Child(String name){
this.name = name;
}
public void joinGame(){
System.out.println(name + "加入了游戏");
}
}
旧方法的问题
1.count是一个独立于我们child对象的一个变量
2.以后访问count很麻烦
所以我们引出 类变量 / 静态变量
二、类变量快速入门
如果设计一个int count表示总人数,在创建一个小孩的时候就把count+1,并且count是所有对象共享的就可以了,所以现在使用类变量来解决上面的问题
public class ChilGame {
public static void main(String[] args) {
Child child0 = new Child("xiaohuang");
Child child1 = new Child("xiaowang");
Child child2 = new Child("xiaoming");
Child child3 = new Child("xiaobai");
Child child4 = new Child("xiaoqing");
int count = 0;
child0.joinGame();
child0.count++;
child1.joinGame();
child1.count++;
child2.joinGame();
child2.count++;
child3.joinGame();
child3.count++;
child4.joinGame();
child4.count++;
System.out.println("现在有" + Child.count + "个小孩加入了游戏");
System.out.println(child0.count);
System.out.println(child1.count);
System.out.println(child2.count);
//即这个变量可以用类Child访问,Child.count,也可以被所有的对象调用
//child0.count child1.count等等
}
}
class Child {
private String name;
//定义一个变量 count 是一个类变量(静态变量) static 静态
public static int count = 0;//该对象会被所有的对象共享
public Child(String name) {
this.name = name;
}
public void joinGame() {
System.out.println(name + "加入了游戏");
}
}
三、类变量的内存布局
显而易见的,所有的对象的类变量的引用,都是指向类变量,如图
但这个类变量如何存放要看jdk的版本,在jdk7 及以前都是在方法区内有一个静态域,在jdk8当类加载的时候就会在堆里创建一个原型对象,所有的对象创建都会参照这个对象,count就存放在这个class类的最后
无论如何1)static变量是所有对象共享的 (指在一个类内)
2)static类变量在类加载的时候就生成了
四、类变量的基本介绍
1.什么是类变量
类变量也叫静态变量/静态属性,是该类的所有对象共享的变量,任何一个该类的对象去访问它时,取到的都是相同的值,同样任何一个该类的对象去修改它时修改的也是同一一个变量。这个从前面的图也可看出来。
2.如何定义类变量
访问修饰符 static 数据类型 变量名;
static 访问修饰符 数据类型 变量名;
3.如何访问类变量
类名.类变量名或者 对象名.类变量名(静态变量的访问修饰符的访问权限和范围 和普通属性是一样的)
推荐使用:类名.类变量名
.
package com.yinhai.static_;
public class ViseStatic {
public static void main(String[] args) {
//类名.类变量名
System.out.println(A.name);
A a = new A();
System.out.println("a.name=" + a.name);
}
}
class A{
public static String name = "name yinhai";
}
五、类变量注意事项和细节讨论
1.什么时候需要用类变量
当我们需要让某个类的所有对象都共享一个变量时,就可以考虑使用类变量(静态变量);比如:定义学生类,统计所有学生交了多少钱 Student(name,static fee)
2.类变量与实例变量(普通属性)的区别
类变量是该类的所有对象共享的,而实例变量是每个对象独享的。
3.加上static称为类变量或者静态变量,否则称为实例变量/普通变量/非静态变量
4.类变量可以通过类名.类变量名 或者 对象名.类变量名来访问,java设计者推荐使用类名.类变量名方式访问(注意必须满足访问权限和范围)
5.实例变量不能通过 类名.变量名 方式访问
6.类变量是在类加载时就初始化了,及使没有创建对象也能使用类名.变量名访问
7.类变量的声明周期是随着类的加载开始的,随着类的死亡而消失
六、类方法的基本介绍
类方法也叫静态方法
类方法的形式
访问修饰符 static 数据返回类型 方法名(){
}
static 访问修饰符 数据返回类型 方法名(){
}
类方法的调用
使用方法:类名.类方法名 或者 对象名.类方法名
类方法的案例
package com.yinhai.static_;
public class StaticMethod {
//统计学生的学费
public static void main(String[] args) {
Stu stu = new Stu("xiaowang");
stu.payFee(1000);
Stu stu1 = new Stu("xiaochen");
stu1.payFee(2000);
stu1.showFee();
}
}
class Stu{
private String name;
private static double fee = 0;
public Stu(String name) {
this.name = name;
}
//1.当方法使用了static修饰后,该方法就是静态方法
//2.静态方法就可以访问静态属性
public static void payFee(double fee){
Stu.fee += fee;
}
public static void showFee(){
System.out.println("总学费有:" + Stu.fee);
}
}
类方法经典的使用场景
当方法中不涉及到任何和对象相关的成员,则可以将方法设计成静态方法,提高开发效率
如Util包内的Math 和 Arrays类等 即工具类的方法可以设置成静态方法
在实际开发中 往往会将一些通用方法设计成静态方法,这样不需要创建的时候就可以直接调用
比如打印一维数组等
public class StaticMethod {
//统计学生的学费
public static void main(String[] args) {
System.out.println(MyTools.calSum(10 ,20));
}
}
class MyTools {
//求出两个数的和
public static double calSum(double n1, double n2 {
return n1 + n2;
}
}
七、类方法使用注意事项和细节讨论
0) 静态方法不能被重写 但是可以被子类继承
1)类方法和普通方法都是随着类的加载而加载,将结构细储存在方法区
类方法中无this的参数
普通方法隐含着this的参数
2)类方法可以通过类名调用,也可以通过对象名调用
3)普通方法和对象有关,需要对象名来调用
4) 类方法中不允许使用和对象有关的关键字 比如 this和super 普通方法可以
5)类方法(静态方法)中只能访问静态变量或静态方法
6)普通成员方法,既可以访问成员变量,也可以访问静态变量。
class A{
public static String name = "name yinhai";
private int n1 = 100;
private static int n2 = 200;
public void say(){
}
public void ok(){
System.out.println(n1);
System.out.println(n2);
say();
hello();
}
public static void hello(){
System.out.println(n2);
System.out.println(A.n2);
}
}
八、类变量和类方法课堂练习
1.
public class Test {
static int count = 9;
public void count() {
System.out.println(" count=" + (count++));
}
public static void main(String args[]) {
new Test().count();
new Test().count();
System.out.println(Test.count);
}
}
2.
public class TestPerson {
public static void main(String[] args) {
System.out.println(" Number of total is "+ Person.getTotalPerson());//静态方法可以直接调用
Person p1 = new Person();
System.out.println("Number of total is "+ Person.getTotalPerson());
}
}
class Person{
private int id;
private static int total = 0;
public static int getTotalPerson(){
//id++;//静态方法只能调用静态属性 错误
return total;
}
public Person(){//无参构造器 构造器本质是成员方法 可以调用成员变量或类变量
total++;
id = total;
}
}
3.
public class TestPerson {
public static void main(String[] args) {
Person.setTotalPerson(3);
new Person();
}
}
class Person{
private int id;
private static int total = 0;
public static void setTotalPerson(int total){
// this.total = total; 类方法中不能带有this语句
Person.total = total;
}
public Person(){//无参构造器 构造器本质是成员方法 可以调用成员变量或类变量
total++;
id = total;
}
}