Java学习5:static关键字内存分析详解及用法
来源:互联网 发布:万网域名怎么解析 编辑:程序博客网 时间:2024/06/06 03:56
static关键词
1.概述
static关键字可用于修饰变量、方法、初始化块。
分别叫做:静态变量、静态方法、静态初始化块。
1.1静态变量
在类中,用static声明的成员变量为静态变量,或者叫做类属性、类变量。
特点
- 静态变量是该类的公共变量,属于类,被该类的所有实例共享,在类被载入时被显示初始化。
- 对于该类的所有对象来说,static成员变量只有一份。被该类的所有对象共享。
- 可以使用 对象.类属性 来调用。不过,一般是用 类名.类属性进行调用。
- static变量置于方法区中
1.2静态方法
用static声明的方法为静态方法;
不需要对象,就可以调用(类名.方法名)。
特点
- 静态方法是该类的公共方法,属于类,被该类的所有实例共享,在类被载入时被显示初始化。
- 对于该类的所有对象来说,static方法只有一份。被该类的所有对象共享。
- 可以使用 对象.类属性 来调用。不过,一般是用 类名.静态方法进行调用。
- static方法不能访问非静态的方法和属性。
1.3静态初始化块
如果希望加载后,对整个类进行某些初始化操作,可以使用static初始化块
是在类初始化时执行,不是在创建对象时执行。
静态初始化块中不能访问非static成员
执行书序
上溯到Object类,先执行Object的静态初始化块,在向下执行子类的静态初始化块,直到我们的类的静态初始化块位置。
2.static成员内存分析
下面我们从内存分析的角度去理解并解释static成员。
2.1分析代码
首先创建一个Student类及一个Test类。如下:
public class Student { int age; String name; static int staticVar; public void sayHello() { } static void staticMed() { System.out.println(staticVar); //静态方法可以访问静态变量 }}
public class Test { public static void main(String[] args) { Student.staticVar = 20; Student stu = new Student(); stu.staticMed(); Student.staticMed(); }}
2.2代码分析
细节的内存分析可参考:图解Java内存分析
这里仅针对static相关进行分析。
1. 当加载类Student时,会在方法区内生成①Student类的代码信息;②static成员;③常量池信息。
这里static的方法并不会再次占用一块内存,而是根据十六进制八位的地址指向类代码信息中的staticMed()方法。
2. Student.staticVar = 20;
直接对方法区的static变量进行复制。
3. Student stu = new Student();
当我们以Student类信息为模板生成stu对象时,并不会生成相应的静态成员(static变量、方法等),仅会生成非静态的,如图中所示,仅有name、age和sayHello()。
4. stu.staticMed();
类的对象可以访问类中的非私有的属性和方法。
通过Student类的对象可以调用静态方法和变量,因为静态的属于类,且只有一个,被所有的对象共享。
但如果使用eclipse等IDE,会看到warning的标志,提示我们类方法和类属性应该通过类进行访问。
The static method staticMed() from the type Student should be accessed in a static way
Student.staticMed();
通过类进行方法的调用。
分析图:
2.3静态与非静态的调用关系
2.3.1非静态的调用静态的:可以
下面我们在Student类的sayHello()方法中,尝试调用静态成员:staticVar和staticMed();
public void sayHello() { System.out.println(staticVar); staticMed(); }
编译执行通过。
在2.2.4中我们分析,类的对象可以访问类中的非私有的属性和方法,在new Student实例中,虽然没有静态成员staticVar和staticMed(),但是其可以通过访问Student类信息获得。
2.3.2静态的访问非静态的:不可以!
静态方法可以访问静态变量,我们在代码中已经示范了。
下面我们在Student类的staticMed()静态方法中,尝试调用非静态成员:age和sayHello()。
static void staticMed() { System.out.println(staticVar); System.out.println(age); //报错信息:Cannot make a static reference to the non-static field age sayHello(); //报错信息:Cannot make a static reference to the non-static method sayHello() from the type Student }
我们发现会报错,报错信息很简单:static不能指向非static。为什么呢?
我们观察内存图,static成员是在类中,在方法区的static成员中,而非静态的在哪呢?没错,在new Student实例中,在堆空间中,当然访问不到。
另一方面,非静态的属性可以有很多,每生成一个实例就会产生一个age属性,访问时无法确定访问哪一个的。
小结
至此,已经基本分析完,虽然过程比较复杂,但是结论很简单:
静态的从属于类。
静态的只能调用静态的,即从属于类的只能调用从属于类的。
非静态的既可以调用非静态的,又可以调用静态的。
- Java学习5:static关键字内存分析详解及用法
- Java学习6:this(隐式参数)关键字内存分析详解及用法
- Java学习9:super(隐式参数)关键字内存分析详解及用法
- java static关键字用法详解
- static关键字内存分析
- java中static关键字的用法详解
- Java下static关键字用法详解
- java中的static关键字详解及面试
- java学习笔记-static关键字的用法
- Java学习-static关键字的用法
- Java学习笔记(19)--关键字static详解
- java static关键字用法
- Java关键字static用法
- java关键字static详解
- java关键字Static详解
- java static 关键字详解
- Java Static关键字详解
- Java 关键字static详解
- js中当值发生变化/键盘摁下等事件的不同之处
- spring @Transactional注解参数详解
- Mapreduce的工作流程
- Android获取系统版本号、软件版本号
- hibernate 一对一双向关联映射
- Java学习5:static关键字内存分析详解及用法
- 树莓派
- thinkPHP
- 转载-python pdb调试以及sublime3快捷键设置
- python爬虫爬取简单的动态数据-异步加载问题
- kotlin基础语法(一)
- 整理JavaScript算法
- YY赔款2000万,游戏直播也会侵权?
- map任务和reduce任务个数如何计算