1、修成员变量
被static修饰的成员变量,我们将之称为静态变量或类变量,相比于普通的成员变量,它有着以下几点不同之处:能够被所有的对象所共享;随着类的加载而存在;它存在于方法区的静态区,JVM只为它分配一次内存空间;有两种调用方法,通过类名来调用或通过对象来调用。我也将用简单通俗的例子来解释:
共享性:
静态变量就像是家里的“公共电视”,家里的每个人(即类的每个对象)都可以看这台电视,电视的内容对所有人都是可见的、共享的。同样,静态变量也是被类的所有对象所共享的,任何一个对象改变了它的值,其他对象再访问时都会看到这个改变。
存在周期:
静态变量不像你口袋里的钱(普通成员变量),钱是你个人的,你不在的时候钱也还在你口袋里。静态变量更像是家里的“家传宝物”,它随着家的存在而存在,不依赖于家里任何一个人的存在。也就是说,静态变量在类加载的时候就已经存在了,即使类的所有对象都被销毁了,静态变量还在。
存储位置:
普通成员变量就像是你房间里的私人物品,每个人(每个对象)都有自己的房间(内存空间)来放这些物品。而静态变量则像是客厅里的大花瓶,它只有一个,放在公共的地方(方法区的静态区),大家都可以看到,JVM也只为它分配一次内存空间。
调用方式:
静态变量有两种调用方式,一种是通过“家门牌号”(类名)来直接找到它,比如“张家的大花瓶”(ZhangFamily.bigVase);另一种是通过家里的人(对象)来间接找到它,比如“张三说他家的大花瓶”(zhangSan.bigVase,但这里其实是不推荐的,因为静态变量本质上是属于类的,不是属于某个对象的)。
2、修饰成员方法
被static修饰的成员方法,我们称之为静态方法,相比于普通的成员方法,它有着如下几点不同之处:静态方法可以通过类直接调用;静态方法只能访问静态变量;静态方法中不可以使用this或者super关键字;主函数是静态的。
调用方式:
静态方法就像是家里的“公用电话”,你不需要先找到家里某个人(对象)才能打电话,而是直接拿起电话就能打。同样,静态方法也不需要通过对象来调用,你可以直接通过类名来调用它。
访问权限:
静态方法只能“看到”和“摸到”家里的“公共物品”(静态变量),它看不到也摸不到任何人的“私人物品”(非静态变量)。因为静态方法是属于类的,而不是属于某个对象的,所以它只能访问类的静态成员。
不能使用this或super:
静态方法里没有“我”(this)的概念,因为它不是针对某个具体对象的。同样,它也不能使用“我爸”(super)的概念,因为静态方法是和类绑定的,而不是和对象的继承关系绑定的。
主函数是静态的:
程序的入口,也就是主函数(main方法),是一个特殊的静态方法。它就像是家里的“大门”,你不需要先进入家里某个房间(对象)才能进门,而是直接通过大门就能进入家里。程序运行时,也是先找到这个静态的主函数来启动整个程序的。
3、静态代码块
静态代码块优先级最高,所有父类子类中静态代码块优先执行。
// 父类 Person
class Person {
// 实例初始化代码块(每次创建对象时执行)
{
System.out.println("父类代码块");
}
// 静态代码块(类加载时执行一次)
static {
System.out.println("父类静态代码块");
}
// 父类构造方法
public Person() {
System.out.println("父类构造方法");
}
}
// 子类 Student 继承自 Person
class Student extends Person {
// 子类实例初始化代码块(每次创建对象时执行)
{
System.out.println("子类代码块");
}
// 子类静态代码块(类加载时执行一次)
static {
System.out.println("子类静态代码块");
}
// 子类构造方法
public Student() {
// 调用父类构造方法(隐式调用,也可以显式使用 super() 调用)
// 此处没有显式调用,因此会隐式调用父类的无参构造方法
System.out.println("子类构造方法");
}
}
// 测试类 Test
class Test {
public static void main(String[] args) {
// 创建 Student 对象,触发相关代码块的执行
new Student();
}
}
输出结果:
父类静态代码块
子类静态代码块
父类代码块
父类构造方法
子类代码块
子类构造方法
4、静态内部类
在定义内部类的时候,在前面加上一个static,则这个内部类就成为了静态内部类,静态内部类和普通内部类相比,有着一些不同之处,因此所起的作用也是有很大的不同,
静态内部类
与外部类的关系:
静态内部类就像是外部类的一个“独立房间”。它不需要依赖外部类的实例就能存在。它可以访问外部类的“公共区域”(即静态成员和静态方法),但不能直接访问外部类的“私人房间”(即非静态成员和非静态方法)。
创建方式:
你可以直接在外部类外面创建静态内部类的实例,不需要先创建外部类的实例。
内部特性:
静态内部类内部可以有自己的静态成员和静态方法。
非静态内部类
与外部类的关系:
非静态内部类更像是外部类的一个“贴身保镖”,它必须依附于外部类的实例才能存在。它可以自由访问外部类的所有成员(无论是静态的还是非静态的),因为它和外部类的实例紧密绑定。
创建方式:
要创建非静态内部类的实例,你必须先有一个外部类的实例,然后通过这个外部类实例来创建内部类的实例。
内部特性:
非静态内部类不能有静态成员或静态方法,因为它总是依赖于一个外部类的实例。
举个例子
想象你有一个“房子”(外部类),房子里有一个“客厅”(静态内部类)和一个“卧室”(非静态内部类)。客厅(静态内部类)是公共的,谁都可以进去,但它只能访问房子里公共的东西(静态成员和方法),不能进入卧室(非静态成员和方法)。卧室(非静态内部类)是私人的,只有房子的主人(外部类的实例)才能进去,而且卧室里的所有东西(成员和方法)都只能由主人来使用和访问。
5、静态导包
静态导包就是java包的静态导入,用import static代替import静态导入包是JDK1.5中的新特性。