通常在进行分析的时候,会从三个方面进行分析:类、方法(构造方法、成员方法)、变量(成员变量(静态变量、实例变量)、局部变量)。java
1、static修饰符:被static修饰的变量和方法,被类的全部实例所共享
。加载类时只分配一次内存。dom
静态变量:能够直接经过类名来访问 Person.a;ide
静态方法:能够直接经过类名来访问 Person.say();静态方法内,能够访问静态变量,可是不能使用this关键字
且不能访问实例变量
,由于被全部实例所共有,没法判断属于哪一个实例对象函数
静态代码块:java虚拟机在加载类时就执行代码块this
有final修饰表示最终(不可再修改)
的意思:指针
final类:不能被继承(即没有子类);code
final方法:不能被子类的方法覆盖(final不用来修饰构造方法,父类与子类之间的构造方法不存在覆盖关系,final修饰是没有意义的);对象
final修饰的变量:即常量,常量只能被赋值一次,以后不能改变。(如下静态常量
属于编译时常量
(final static int a=2*3;在编译的时就能计算出具体的值),在编译的时候将这个值就放入到常量池中,a被访问时类是不会被初始化的(这是类的被动使用
)。访问类的静态变量或静态方法的时候类会被初始化(这是类的主动使用
)。但只有static修饰的常量,只会在类初始化的时候才会赋值)。具体细节请参考“类的生命周期”
---加载(堆区、方法区)--链接(验证、准备(静态变量分配内存、设置默认初始值为0)、解析(符号引用替换为直接引用,即指针指向方法区的内存位置))--初始化(程序对类或接口主动使用
的时候才会被初始化)。继承
类的初始化
即java虚拟机为类的static静态变量
赋予初始值(这和准备阶段设置默认初始值为0是不同的)。只有类的主动使用才会初始化类
。接口
1.类的主动使用(6种):
1.1 建立类的实例:用new语句建立实例 Person ps=new Person();
1.2 调用类的静态变量或对静态变量赋值:
public class Person{ //这和final static int a=2*3;是有区别的 static int a=2*3; //Java在定义一个类的时候里面只能放方法和属性,这是规定死了的。 //System.out.println()是在调用一个叫println的函数, //这里是函数的调用而不是类里面定义一个函数。因此须要用static代码块 static{ //static声明的静态代码块, //使得类在初始化的时候会被调用而不须要建立实例对象。 //它这时候就不在任何一个方法中。 System.out.println("init Person"); } }
调用的时候写:
//这样就能够在不new一个Person实例的状况下,来初始化Person类了。 System.out.println("a="+Person.a);
1.3 调用类的静态方法;
1.4 调用java API中的反射方法:Class.forName("Person");
1.5 初始化子类的时候会先初始化父类(但"父类"是接口的时候,不会先初始化它所实现的接口的,只有在程序在使用接口的静态变量时才会使静态接口初始化)
1.6 java虚拟机启动时被标明为启动类的类
2.类的被使用:
1.1 final类型的静态变量在编译的时候能计算出值(即编译时常量,在编译的时候将这个值就放入到常量池中了):
注: final类型的静态变量在编译的时候不能计算出变量的值的时候是会被初始化的
//变量a是编译时常量 final static int a=2*3; //变量a不是是编译时常量 final static int a=(int)Math.random();
1.2 "父类"是接口的时候,不会先初始化它所实现的接口的,只有在程序在使用接口的静态变量时才会使静态接口初始化
1.3 ClassLoader类的loadClass("Person")方法的时候,只是对类的加载,不是初始化。Class.forName("Person");才会初始化