static - 静态
修饰符 - 用于修饰数据(变量、常量)、方法、代码块以及内部类
静态变量
- 用static修饰的变量,称之为静态变量,也叫类变量。
- 在类加载的时候加载到了方法区,并且在方法区中被赋予了默认值。
- 静态变量是先于对象出现的,所以习惯上是通过类名来调用静态变量。
- 每一个对象存储的是这个静态变量在方法区中的地址,所以静态变量是被这个类的所有对象所共享的
- 静态变量能否定义到构造方法中?—不能。静态变量是在类加载的时候出现,先于对象出现。构造方法在创建对象的时候执行,方法执行采用意义。
- 注意:
- 类是加载到方法区中的
- 类是在第一次使用的时候才加载,加载之后就不会移除
package cn.tedu.reiew;
public class StaticDemo {
public static void main(String[] args) {
System.out.println(A.i);
// System.out.println(A.j);
}
}
class A {
// 先加载a,i,j
// 其中a先标记为null,i和j标记为0
// 进行初始化操作
// 先执行 static A a = new A();
// 这个时候a的具体地址来覆盖掉标记的null
// a的实际对象是存在堆内存中,然后方法区中存储a的地址
// 创建a对象那么就得执行a的构造方法
// 意味着要执行i++,j++,在创建对象将标记值先认为是默认值
// i->1 j->1
// a的构造方法执行完成,然后初始化i和j
// i = 5;利用实际数据5覆盖掉标记值1
// 注意:在类加载过程中不允许计算标记值/
// 但是在创建对象或者其他方式使用的时候会将标记值认为是默认值使用
static A a = new A();
static int i = 5;
static int j;
public A() {
i++;
j++;
// System.out.println(i);
// System.out.println(j);
}
}
静态方法:
-
用static修饰的方法
-
静态方法随着类的加载而加载到方法区中,但是在方法区中不执行只存储,在方法被调用的时候到栈内存执行。
-
静态方法先于对象存在,所以习惯上是通过类名来调用静态方法。
-
静态方法中不能直接使用本类中的非静态
-
静态方法中可以定义静态变量吗?
不能
静态方法在调用的时候执行,静态方法执行的时候里面的变量才能初始化;静态变量是在类加载的时候就初始化了 -
静态方法中能否使用this/super?
不行
this代表当前在活动的对象,静态方法先于对象存在,它可能被类调用(类名.方法名),所以可能先于对象执行。 -
能否在静态方法中直接使用本类中的非静态方法/非静态属性?
不行
非静态方法和属性必须对象类调用(具体的对象存在的时候非静态方法和属性才存在),都是默认用this调用(int j =(this.)i;)! -
思考这几个点:定义/调用、方法只谈调用
-
静态方法中不能定义静态变量、非静态变量、也不能调用非静态方法
-
非静态方法不能定义静态变量、可以调用静态方法,但可以定义静态常量
-
注意:
目录,再往上一拉 -
静态方法可以重载吗?—可以
-
静态方法可以被继承吗?—可以
-
静态方法可以重写吗?—不可以
-
静态方法虽然不能被重写,但是父子类中可以存在方法签名一致的静态方法 — 静态方法的隐藏(hide)
-
父子类中可以存在方法签名一致的方法,要么都是非静态(重写)要么都是静态(隐藏)
静态代码块
- 用static{}包起来的代码 — 在类加载的时候执行一次,在类加载的时候到栈内存中执行。
- 执行顺序:父类静态 -> 子类静态 -> 父类非静态(先成员变量 )-> 父类的构造方法(构造代码块先于构造方法执行) -> 子类非静态 -> 子类的构造方法
- 注意:能够执行Java程序的内存块只有栈内存。
final
-
修饰符 — 修饰数据、方法以及类
-
final修饰数据的时候 — 常量 -> 定义好之后值不可改变。
-
如果final修饰的是基本类型的数据,那么指的是实际值不可变;
-
如果final修饰的引用类型的数据,那么指的是地址不可变,但是对象中的元素或者属性值可以改变
-
对于成员常量要求在对象创建完成之前给值;对于静态常量而言要求在类加载完成之前给值
-
注意:常量的存储和方法区中的运行时常量池有关
-
final修饰方法 — 最终方法,能被继承但是不可被重写/隐藏,能被重载。
-
final修饰类 — 最终类 — 不能被继承
小知识点
-
重写执行的子类,非静态的向上造型看的是子类,隐藏执行的是父类,静态的向上造型看的是父类!
-
执行(存在有意义)和存储、静态和非静态
-
当构成静态方法的隐藏的时候,方法的执行看的是声明类
-
静态变量能共享,可以记录属性值的变化,
-
非静态变量只在具体对象空间内,为每一个对象所私有的
package exer1;
public class StaticDemo4 {
public static void main(String[] args) {
// 加载父类 --- 父类静态
// 加载子类 --- 子类静态
// 创建父类对象 --- 父类构造
// 创建子类对象 --- 子类构造
new SB();
System.out.println("========");
new SB();
/*A1
C
B1
C
D
A2
A3
B2
B3
========
C
D
A2
A3
B2
B3*/
}
}
class SA {
SD d = new SD();
static {
System.out.println("A1");
}
{
System.out.println("A2");
}
public SA() {
System.out.println("A3");
}
}
class SB extends SA {
static SC c = new SC();
static {
System.out.println("B1");
}
{
System.out.println("B2");
}
public SB() {
System.out.println("B3");
}
}
class SC {
public SC() {
System.out.println("C");
}
}
class SD extends SC {
public SD() {
System.out.println("D");
}
}