在Java中static是很难理解的一个关键字,对于初学者来说很容易混淆,不知道在什么情况下使用static来使用static修饰方法或者变量。本篇文章从以下几个方面对static的使用原理进行分析。
1、static关键字的基本用法
2、深入分析static关键字
3、private static修饰
本篇文章为记录自己的学习过程,若有不正之处,希望谅解并欢迎批评指正。
一、static关键字的基本用法
在使用static修饰变量或者方法之前,需要明白只要使用了static来修饰了变量和方法,那这个修饰的东西不需要创建对象来调用,直接使用类名就可以调用了。
1、static修饰变量
如果一个变量被static关键字修饰了,那么这个变量不再属于自己,而是属于所在的类,即不需要再创建一个对象来调用这个变量,直接使用类名.变量名就可以调用了。static变量可以被所有对象共享,在内存中只有一个副本,它当且仅当在类初次加载时会被初始化。
2、static修饰方法
一旦使用static修饰方法,那么这就成为了静态方法。静态方法不属于对象,而是属于类的。
注意事项:
- 静态不能直接访问非静态,
原因:因为在内存中是【先】有的静态内容,【后】有的非静态内容。静态先执行,后释放。 - 静态方法当中不能使用this
原因:this代表当前对象,通过谁调用的方法,谁就是当前的对象。
public class MyClass {
static int numStatic; //静态变量
int num; // 成员变量
// 静态方法
public static void methodStatic() {
System.out.println("我是静态方法!");
// 静态方法可以访问静态变量
System.out.println(numStatic);
// 静态方法不能访问成员变量【】重点
//System.out.println(num); // 错误写法
// 静态方法中不能使用this关键字
//this. // 错误写法
}
// 成员方法
public void method() {
System.out.println("我是成员方法!");
// 成员方法可以访问成员变量
System.out.println(num);
// 成员方法可以访问静态变量
System.out.println(numStatic);
}
}
3、静态代码块
静态代码块的格式是:
public class 类名称{
static {
// 静态代码块内容
}
}
特点:当第一次用到本类时,静态代码块执行的唯一一次
静态内容总是用于非静态,所以静态代码块比构造方法先执行
静态代码块的典型用途:用来一次性地对静态成员变量进行赋值。
public class Person {
static {
System.out.println("静态代码块执行!");
}
public Person(){
System.out.println("构造方法执行!");
}
}
// 输入顺序:静态代码块执行,构造方法执行。
二、深入分析static关键字
从JVM内存来看static修饰的静态区。
常用的3个内存结构:
- 栈(Stack):用来存放基础变量以及对象的引用,存放的是具体的数值。
- 堆(Heap):new出来的东西都放在堆中,即对象本身,存放的是地址值。
- 方法区(Method Area):存放的是.class文件,即代码块,使用static修饰的时候,会在方法区中开辟一块静态区。
从内存的角度来看,为什么static会有这样的特性,首先定义一个Student类。
public class Student {
private int id;
private String name;
private int age;
static String room;
private static int idCountter;
public Student() {
this.id = ++idCountter;
}
public Student(String name, int age) {
this.name = name;
this.age = age;
this.id = ++idCountter;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
}
然后来调用它:
public class Demo3Student {
public static void main(String[] args) {
// 首先设置一下教室,这是静态的东西,应该通过类名称进行调用
Student.room = "3年级2班";
Student one = new Student("周杰伦",38);
System.out.println("姓名:" + one.getName() +
",年龄" + one.getAge() + ",年纪" + Student.room);
Student two = new Student("林俊杰",36);
System.out.println("姓名:" + two.getName() +
",年龄" + two.getAge() + ",年纪" + Student.room);
}
}
接下来我们从内存的角度出发,看看这个程序运行的过程。
从图中可以调用static关键字修饰的变量或者方法的时候是直接从方法区调用的,而对象是存储在堆中的,多个对象共享一份static数据,一变都变。
下面对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、主函数是静态的
三、private static修饰
被private static修饰的属性仅仅可以被静态方法调用,但是只能被本类中的方法(可以是非静态的)调用,在外部创建这个类的对象或者直接使用这个类访问都是非法的。
public class MyTest {
static String name;
private static int age;
public static void test(){
age++;
}
}
调用:
public class Demo05MyTest {
public static void main(String[] args) {
MyTest.name = "李连杰";
MyTest.age;//错误
MyTest myTest = new MyTest();
myTest.age;//错误
}
}