下面我举个例子:
我们定义一个学生类:
然后我们实例化三个对象:
在这个例子中,我们发现三个同学姓名年龄学号都不一样,但是他们都是一个班的同学。首先说明一下,定义一个类,就需要在内存里开辟一块空间,而类内部的属性都属于这个内存空间,那么当我们实例化的时候,又在每个对象中添加一个所在班级的属性,那为什么不将所在班级这个属性放在类中呢,而且这样做节省内存,一旦使用了static关键字,那么这个内容就不在属于对象自己,而是属于类,凡是本类的对象,都共享同一份,比如上面例子中的三个对象共享同一份name、age、num。静态,个人感受就是相对于对象来说,调用方法或者变量不需要实例化,在加载类的时候就已经被加载。
static方法一般称作静态方法,由于静态方法不依赖于任何对象就可以进行访问,因此对于静态方法来说,是没有this的,因为它不依附于任何对象,既然都没有对象,就谈不上this了。并且由于这个特性,在静态方法中不能访问类的非静态成员变量和非静态成员方法,因为非静态成员方法/变量都是必须依赖具体的对象才能够被调用。简而言之:方便在没有创建对象的情况下来进行调用(方法/变量)。
在类当中,使用static修饰符的属性(成员变量)成为静态变量,或者称为类变量,常量称为静态常量,方法称为静态方法或者类方法,不论是静态变量还是静态方法,统称为静态成员,归整个类所有。
静态成员不依赖于对象,换句话说就是不依赖类的特定实例,被整个类所共享。也就是说,只要是static修饰的方法或者变量不需要依赖于对象进行访问,只要这个类被加载,JVM(Java虚拟机)就可以根据类名找到它们。
注意事项:
代码演示访问静态变量和实例变量:
public class demo01Static {
// 使用static修饰过的变量,静态变量。
public static String str1 = "shuyv";
public static void main(String[] args) {
// 实例变量
String str2 = "dkl";
// 直接访问静态变量和实例变量
System.out.println("There are two names : " + str1 + " and " + str2);
// 通过类名访问静态变量和实例变量
String strone = demo01Static.str1+ " and " + str2;
System.out.println("There are two names : " + strone);
// 通过对象访问静态变量和实例变量
demo01Static name = new demo01Static();
name.str1 = name.str1 + " and " + str2;
String strtwo = name.str1;
System.out.println("There are two names : " + strtwo);
}
}
三次输出的结果都是:
There are two names : shuyv and dkl
从运行结果来看,静态属性,在main方法中可以直接访问,也可以通过类名访问,还可以实例化对象来访问,总之,静态属性被一个类中的所有实例所共享。
与静态变量相似静态方法即是被static修饰的方法。
反之,实例方法即是没有被static修饰的方法。
静态方法和实例方法的区别:
代码演示
public class demo02StaticMethod {
// 定义静态变量
public static int count = 1;
// 定义实例方法method1
public int method1() {
count++;
System.out.println("----------------------------------");
System.out.println(count); // 在实例方法中可以直接访问静态变量
return count;
}
// 定义静态方法method2
public static int method2() {
count += count;
System.out.println("----------------------------------");
System.out.println(count);
return count;
}
// 定义静态方法PrintCount
public static void PrintCount() {
count += 2;
System.out.println("----------------------------------");
System.out.println(count);
}
// 通过实例化对象来调用方法
public static void main(String[] args) {
demo02StaticMethod math = new demo02StaticMethod();
System.out.println("实例方法method1的返回值为:" + math.method1());
System.out.println("静态方法method2的返回值为:" + math.method2());
demo02StaticMethod.PrintCount(); // 通过类名调用静态方法,打印count
}
}
运行结果如下:
----------------------------------
2
method1的返回值为:2
----------------------------------
5
method2的返回值为:5
----------------------------------
7
通过上面代码举例,我们发现,首先count作为静态变量在整个类当中被共享,因此,在各个方法当中调用的值不同。在静态方法medthod2方法和PrintCount方法中是不可以调用非静态方法method1的,而在method1方法中可以调用静态方法medthod2和PrintCount方法的。
在访问非静态方法时,需要通过实例对象来访问,而在访问静态方法时,可以直接访问,也可以通过类名来访问,还可以通过实例化对象来访问。
静态代码块在Java中指的是 static{ } 代码块,主要用于初始化类,为类的静态变量赋值初始值,提升程序性能。
静态代码块的特点:
代码演示:
public class demo03StaticCode {
public static int count = 0; // 静态变量
// 非静态代码块
{
count++;
System.out.println("非静态代码块执行了");
System.out.println("count:" + count);
}
// 静态代码块
static {
count++;
System.out.println("---------------------------");
System.out.println("静态代码块1: " + count);
}
// 静态代码块
static {
count++;
System.out.println("---------------------------");
System.out.println("静态代码块2: " + count);
}
public static void main(String[] args) {
//int count01 = 11;
System.out.println("---------------------------");
demo03StaticCode sta1 = new demo03StaticCode(); // 实例化第一个对象
System.out.println("---------------------------");
demo03StaticCode sta2 = new demo03StaticCode(); // 实例化第二个对象
}
}
运行结果为:
---------------------------
静态代码块1: 1
---------------------------
静态代码块2: 2
---------------------------
非静态代码块执行了
count:3
---------------------------
非静态代码块执行了
count:4
上述代码中的非静态代码块,是在创建对象的时候自动调用。不创建对象不执行该类的非静态代码块。代码域中定义的变量都是局部的,只有域中的代码可以调用。