类变量和类方法
提出问题
小孩玩游戏,其他小孩加入,要如何设计?传统方法使用count变量。
//ChildGame.java
public class ChildGame {
public static void main(String[] args) {
//小孩玩游戏,新的小孩加入
//传统方法使用一个变量来模拟
int count = 0;
Child child1 = new Child("狐狸精");
child1.join();
count++;
Child child2 = new Child("老鼠精");
child2.join();
count++;
Child child3 = new Child("蜘蛛精");
child3.join();
count++;
System.out.println(count + "名小孩加入了游戏");
}
}
class Child{
private String name;
public Child(String name) {
this.name = name;
}
public void join(){
System.out.println(name + "小孩加入了游戏");
}
}
可以发现上面传统方法定义的count变量和类是相互独立的,在以后不方便取用。
改进
在类内定义一个静态变量,用static修饰,该变量最大的特点就会被所有的对象实例共享。
静态变量在类加载的时候就生成了。
class Child{
private String name;
public static int count;//此处修改,并且把主函数中的count删掉
public Child(String name) {
this.name = name;
}
public void join(){
System.out.println(name + "小孩加入了游戏");
}
}
主方法修改如下:
public class ChildGame {
public static void main(String[] args) {
//小孩玩游戏,新的小孩加入
//传统方法使用一个变量来模拟
int count = 0;
Child child1 = new Child("狐狸精");
child1.join();
//count++;
child1.count++;
Child child2 = new Child("老鼠精");
child2.join();
// count++;
child2.count++;
Child child3 = new Child("蜘蛛精");
child3.join();
// count++;
child3.count++;
//使用类变量访问,或者用任意一个对象实例来访问
System.out.println(Child.count + "名小孩加入了游戏");
}
}
输出结果:
狐狸精小孩加入了游戏
老鼠精小孩加入了游戏
蜘蛛精小孩加入了游戏
3名小孩加入了游戏
jdk8以前静态变量存放在方法区;jdk8以后一般存放在堆中,每次调用该类时会生成class
实例,static变量保存在class
实例的尾部。
类变量
介绍
类变量也叫静态变量/静态属性,是该类的所有对象共享的变量。
任何一个该类的对象去访问它时,取到的都是相同的值。
任何一个该类的对象去修改它时,修改的也是同一个变量。
定义和访问类变量
//定义访问修饰符 static 数据类型 变量名(推荐)
static 访问修饰符 数据类型 变量名
//访问
类名.类变量名(推荐)
对象名.类变量名
静态变量的访问权限和范围是和普通属性一样的
VisitStatic.java
//VisitStatic.java
public class VisitStatic {
public static void main(String[] args) {
//类名.变量名
//类变量是随着类加载而创建,即使没有创建对象实例也能访问
System.out.println(A.name);
//也可以通过对象实例来访问
A a = new A();
System.out.println("name:" + a.name );
}
}
class A{
public static String name = "hsp教育";
}
输出结果:
hsp教育
name:hsp教育
总结
- 什么时候使用
当需要让某个类的所有对象都共享一个变量的时候,比如定义了一个学生类,统计所有学生一共要交多少学费时,就可以用类变量 - 类变量与实例变量的区别
类变量是所有对象共享,而实例变量是每个对象独享的 - 有static修饰的即称为类变量或静态变量,没有则叫做普通/实例/非静态 变量
- 建议满足访问权限的前提下,使用推荐的访问方式
- 实例变量不能通过
类名.类变量名
的方式来访问 - 类变量在类加载时就初始化了,因此即使没有创建实例也能使用
- 类变量的生命周期随着类加载开始,随着类消亡而销毁
类方法
介绍
和类变量相似,类方法也叫静态方法。
定义和调用类方法的方式与类变量差不多
定义
访问修饰符 static 数据返回类型 方法名(推荐)
static 访问修饰符 数据返回类型 方法名
调用
类名.类方法名
对象名.类方法名
类方法经典使用场景
当不涉及到任何对象相关成员,则可以设计成类方法提高开发效率。
而且由于不创建实例也能调用的特性,一般工具类的方法都可以设计成静态方法。
例如工具类的方法utils中很多类的方法都采用静态方式,如Math类、Arrays类、Collections类。
程序员实际开发中会将一些通用的方法设计成静态方法,这样就不需要创建对象实例了。
交学费案例
//StaticMethod.java
public class StaticMethod {
public static void main(String[] args) {
//创建两个学生对象来交学费
Stu tom = new Stu("Tom");
Stu mary = new Stu("Mary");
//两人分别交的学费
tom.payfee(100);
mary.payfee(200);
//显示当前的总学费
Stu.showfee();
//直接调用Math类的sqrt开方函数而不创建实例
System.out.println("9开方结果是:" + Math.sqrt(9));
//调用自己写的Mytools类的calSum方法
System.out.println(Mytools.calSum(10 ,20));
}
}
class Mytools{
public static double calSum(double n1, double n2){
return n1 + n2;
}
}
class Stu{
private String name;
public static double fee = 0;
public Stu(String name) {
this.name = name;
}
public static void payfee(double fee){
Stu.fee += fee;
}
public static void showfee(){
System.out.println("总学费有:" + Stu.fee);
}
}
输出结果:
总学费有:300.0
9开方结果是:3.0
30.0
注意事项
- 类方法和普通方法都随着类加载而加载,结构信息存储在方法区
类方法无this参数
普通方法中隐含this参数
- 类方法可以通过类名调用,也可以通过对象名调用;普通方法和对象有关,需要通过对象名调用。
- 类方法中不允许使用和对象有关的关键字,比如
super
和this
。 - 类方法只能访问类变量和类方法;普通方法则既能访问普通变量(方法),也能访问类变量(方法)。
//StaticMethodDetail.java
public class StaticMethodDetail {
public static void main(String[] args) {
D.hi();
}
}
class D{
private int n1=100;
public static int n2=200;
public void say(){//非静态方法
}
public static void hi(){//静态方法
//类方法中不允许使用和对象有关的关键字,比如`super`和`this`
//System.out.println(this.n1); 报错,不能用
}
//第4-1条 类方法只能访问类变量或类方法
public static void hello(){
System.out.println(n2);
System.out.println(D.n2);//用静态方式访问
//System.out.println(this.n2); 用关键字访问,错误
hi();//可以,因为hi是静态方法
//say(); 错误,say是非静态方法
}
//第4-2条 普通方法则既能访问普通变量(方法),也能访问类变量(方法)。
public void Ok(){
//非静态成员
System.out.println(n1);
say();
//静态成员
System.out.println(n2);
hello();
}
}