Static修饰类的属性或方法
- 实例属性,是每个对象各自持有的独立内存空间(多份),对象单方面修改,不会影响其他对象。
- 静态属性,static 修饰的实例属性,为。静态属性,是整个类共同持有的共享空间(一份),任何对象修改,都会影响其他对象。
Java中规定:不能将方法体内的局部变量声明为 static!
静态属性:类属性
静态方法:类方法
不必创建对象,可直接通过类名访问【推荐】:类名.静态成员
public class TestStaticField {
public static void main(String[] args) {
MyClass mc1 = new MyClass();
mc1.a = 10;
//mc1.b = 100;
MyClass.b = 100;
MyClass mc2 = new MyClass();
mc2.a = 20;
//mc2.b = 200;
MyClass.b = 200;
System.out.println(mc1.a + " " + mc2.a);
System.out.println(MyClass.b + " " + MyClass.b);
System.out.println();
mc1.method2();
System.out.println();
mc2.method2();
}
}
/**
* 类的信息:类的名字com.day16.t1_static.MyClass
* 父类是谁:java.lang.Object
* 实例属性:int a = 0
* 静态属性:int b = 0; double PI = 3.14;
* 实例方法:xxx
* 静态方法:xxx
* 类的创建时间:xxxx-xx-xx xx:xx:xx
* 类的编译JDK版本:JDK 8.xx.xx(主版本号.次版本号)
* 类的加密:MD5 checksum
*/
class MyClass {
int a; // 实例属性
static int b; // 静态属性
static double PI = 3.14; // 静态属性(赋初始值)
public static void method1() {
System.out.println("method1()...");
}
public void method2() {
//System.out.println(MyClass.a);
System.out.println(MyClass.b);
System.out.println(MyClass.PI);
MyClass.method1();
}
}
/* 输出:
10 20
200 200
200
3.14
method1()...
200
3.14
method1()...
*/
// 统计一个类被创建的次数
public class TestApplyStaticField {
public static void main(String[] args) {
Student[] stus = new Student[10];
for (int i = 0; i < stus.length; i++) {
stus[i] = new Student();
}
System.out.println("count最终值:" + Student.getCount()); //10
}
}
class Student {
private static int count = 0;
public Student() {
count++;
}
public static int getCount() {
return count;
}
}
如这几个常见的静态方法,均使用类名直接调用
Arrays.copyOf();
Arrays.sort();
Math.random();
Math.sqrt();
- 静态方法规则:
- 静态方法允许直接访问静态成员(不需要this.);
- 静态方法不允许直接访问非静态成员;
- 静态方法中不允许使用this或super关键字;
- 静态方法可以继承,不能重写(覆盖)、没有多态;
-
static静态代码块
在执行类时,希望先执行的初始化动作,可以使用static定义一个静态代码区域,在类加载时即会被执行仅有的一次。
语法:
public class example {
// 静态代码块:主要用于类执行前的一些初始化
static {
// do some init things.
}
}
类加载
JVM首次使用某个类时,需通过CLASSPATH查找该类的.class文件
将.class文件中对类的描述信息加载到内存中,进行保存
如:包名、类名、父类、属性、方法、构造方法...
即:对一个类而言,加载的操作只做一次。
- 加载时机:
- 创建对象
- 创建子类对象
- 访问静态属性
- 调用静态方法
- 调用类加载语法
Class.forName("全限定名");
- 类加载时:
触发:静态属性和静态代码块的执行 - (仅1次)
顺序:静态属性初始化之后执行静态代码块
作用:可谓静态属性赋值,或必要的初始化行为
public class TestClassLoad {
public static void main(String[] args) throws Exception {
//new Super();
//Super.method();
//System.out.println("------------------------------------");
//Super.method();
//System.out.println("------------------------------------");
//Class.forName("com.day16.t3_classloaded.Super"); // 静态属性, 静态代码块 (优先执行,且只执行1次)
Class.forName("com.day16.t3_classloaded.Sub");
System.out.println("------------------------");
new Sub();
System.out.println("************************");
new Sub();
}
}
//调用顺序: ↓↓↓
class Super {
// 1.1静态属性(类层面:仅加载类时执行一次,归类所有,非对象所有)
static String field2 = "父类静态属性";
// 1.2静态代码块(类层面:仅加载类时执行一次,归类所有,非对象所有)
static {
System.out.println(field2);
System.out.println("父类静态代码块");
}
// ----------------------父类执行顺序分割线--------------------------
// 3.实例属性(创建对象时执行)
String field1 = "父类实例属性";
// 4.动态代码块(创建对象时执行)
{
System.out.println(field1);
System.out.println("父类动态代码块");
}
// 5.无参构造方法(创建对象时执行)
public Super() {
super();
System.out.println("父类无参构造方法");
}
// 6.类中静态方法(可被类名直接调用,可执行多次)
public static void method() {
System.out.println("父类类中的静态方法");
}
}
class Sub extends Super {
// 2.1静态属性(类层面:仅加载类时执行一次,归类所有,非对象所有)
static String subfield2 = "子类静态属性";
// 2.2静态代码块(类层面:仅加载类时执行一次,归类所有,非对象所有)
static {
System.out.println(subfield2);
System.out.println("子类静态代码块");
}
// 7.实例属性(创建对象时执行)
String subfield1 = "子类实例属性";
// 8.动态代码块(创建对象时执行)
{
System.out.println(subfield1);
System.out.println("子类动态代码块");
}
// 9.无参构造方法(创建对象时执行)
public Sub() {
super();
System.out.println("子类无参构造方法");
}
// 10.类中静态方法(可被类名直接调用,可执行多次)
public static void submethod() {
System.out.println("子类类中的静态方法");
}
}
/* 输出:
父类静态属性
父类静态代码块
子类静态属性
子类静态代码块
------------------------
父类实例属性
父类动态代码块
父类无参构造方法
子类实例属性
子类动态代码块
子类无参构造方法
************************
父类实例属性
父类动态代码块
父类无参构造方法
子类实例属性
子类动态代码块
子类无参构造方法
*/
static静态属性/方法/代码块进行一个小结:
(1)特点:
1、static是一个修饰符,static修饰的成员变量称之为静态变量或类变量。
2、static修饰的成员被所有的对象共享。
3、static优先于对象存在,因为static的成员随着类的加载就已经存在。
4、static修饰的成员多了一种调用方式,可以直接被类名所调用(类名.静态成员)。
5、static修饰的数据是共享数据,对象中的存储的是特有的数据。
(2)成员变量和静态变量的区别:
1、生命周期的不同:
成员变量随着对象的创建而存在随着对象的回收而释放。
静态变量随着类的加载而存在随着类的消失而消失。
2、调用方式不同:
成员变量只能被对象调用。
静态变量可以被对象调用,也可以用类名调用。(推荐用类名调用)
3、别名不同:
成员变量也称为实例变量。
静态变量称为类变量。
4、数据存储位置不同:
成员变量数据存储在堆内存的对象中,所以也叫对象的特有数据。
静态变量数据存储在方法区(共享数据区)的静态区,所以也叫对象的共享数据。
(3)静态使用时需要注意的事项:
1、静态方法只能访问静态成员(非静态既可以访问静态,又可以访问非静态)。
2、静态方法中不可以使用this或者super关键字。
3、主函数是静态的。