Java学习笔记(八)——类变量和类方法

前言

该部分已经进入面向对象高级部分知识,主要涉及到类变量、类方法、代码块等知识

类变量

引出

例子:有一群小孩在玩堆雪人,不时有新的小孩加入,请问如何知道现在共有多少小孩在玩?

思路:

  • 1、在main方法中定义一个变量count
  • 2、当一个小孩加入游戏后,count++,最后count就记录有多少个小孩玩游戏

问题:

  • 1、count是一个独立于对象/类的变量
  • 2、以后访问count比较麻烦,没有使用opp

解决:

  • 如果设计一个int count表示总人数,我们在创建一个小孩时,就把count+1,并且count是所有对象共享的就ok了

因此我们引出类变量(也叫静态变量)

类变量快速入门

1
2
3
4
5
6
class child{
private String name;
//当我们给一个属性增加了一个static修饰符,它就成了一个类变量(静态变量)
//该变量最大的特点就是会被child类的所有对象实例共享
public static int count = 0;
}

类变量基础知识

什么是类变量

类变量也叫静态变量/静态属性,是该类的所有对象共享的变量,任何一个该类的对象去访问他时,取到的都是相同的值,同样任何一个类的对象去修改它时,修改的也是同一个变量。

如何定义类变量

定义语法:

  • 访问修饰符 static 数据类型 变量名;【推荐】
  • static 访问修饰符 数据类型 变量名;

如何访问类变量

  • 类名.类变量名【推荐】

  • 对象名.类变量名【静态变量的访问修饰符的访问权限和范围和普通属性是一样的】

类变量内存布局

静态变量究竟放在哪里?

说法很多:

  • 1、静态域(方法区)

以上述例子为例:

​ 由于count是属于静态变量的,而child在进行类加载的时候,其类信息会放在方法区里面。在方法区中有一个空间叫静态域,这个count也就是在这个方法区的静态域中。

  • 2、堆

以上述例子为例:

放在堆中Child类对应的class对象最后。那这个class对象是什么呢?

当Child这个类在进行加载的时候,它会在堆里面生成一个Child类对应的class对象,这个class对象是一个原型对象,在创建每一个对象实例的时候都会依照它来创建,而且我们通过这个class对象可以拿到很多类的信息,这个在反射里面会详细讲。

Class对象如同堆中其他对象一样,存在于GC堆中。

那么到底放在哪个地方呢?——看jdk版本

  • JDK7、JDK8以前它们是放在方法区的静态域中。
  • JDK8之后:其实是放在堆中类对应的Class对象最后。会通过反射机制加载一个Class对象,在这个Class实例的尾部,它会把静态的数据放在Class对象中。

但不论是放在堆里面还是方法区的静态域中,都不会影响两个事实:

  • static变量是被同一个类所有对象共享的,因此不影响对静态变量的使用
  • static类变量,在类加载的时候就被生成了。——这就意味着即使没有创建对象实例也可以访问

类方法

基本介绍

类方法也叫静态方法,形式如下:

  • 访问修饰符 static 数据返回类型 方法名( ){ }
  • static 访问修饰符 数据返回类型 方法名( ){ }

类方法的调用:

  • 类名.类方法名
  • 对象.类方法名

经典使用场景

当方法中不涉及到任何和对象相关的成员,则可以将方法设计为静态方法,提高开发效率

比如:工具类中的方法。Math类、Arrays类、Collections集合类

程序员实际开发,往往会将一些通用的方法,设计成静态方法,这样我们不需要创建对象就可以使用,比如打印以为数组,冒泡排序,完成某个计算任务等。

使用细节、注意事项

  • 1、类方法和普通方法都是随着类的加载而加载,将结构信息存储在方法区。类方法中无this的参数,普通方法中隐含着this的参数。

  • 2、普通方法和对象有关,需要通过对象名调用,不能通过类名调用,而静态方法可以。

  • 3、类方法中不允许使用和对象有关的关键字,比如this和super,普通方法可以。

  • 4、类方法中只能访问静态变量或者静态方法

  • 5、普通成员方法,既可以访问非静态成员,也可以访问静态成员。

深入理解Main方法

语法说明:

main方法形式:

1
2
public static void main(String[] args){
}
  • 1、main方法是JVM调用的
  • 2、Java虚拟机需要调用类的main()方法,所以该方法的访问权限必须是public
  • 3、Java虚拟机在执行main()方法时不必创建对象,所以该方法必须是static
  • 4、该方法接受String类型的数组参数,该数组中保存执行java命令时传递给所运行的类的参数

String[] args这个字符串数组里面的形参到底是什么时候传进去的?是在执行下面程序(第5点)的时候传入的:

  • 5、Java执行的程序 参数1 参数2 参数3

截屏2022-09-14 19.43.35

1
2
3
4
5
6
7
public class Test{
public static void main(String[] args){
for(int i = 0 ; i < args.length ; i++){
System.out.println("第"+ (i+1) + "个参数=" + args[i]);
}
}
}

我们都知道,编写了上述代码后,需要:

1
2
3
javac Hello.java

java Hello

才可以执行,这个时候我们可以看到终端输出为空,但是如果将运行代码修改成下面:

1
java Hello tom jack smith

我们就可以看到输出:

1
2
3
第1个参数=tom
第2个参数=jack
第3个参数=smith

特别说明:

  • 1、在main()方法中,我们可以调用main方法所在类的静态方法或静态属性
  • 2、但是,不能直接访问该类中的非静态成员,必须创建一个实例对象后,才能通过这个对象去访问类中的非静态成员。