一、 对象存储在那个地方
(1) 寄存器(register) 位于cpu内部,资源有限由程序编译的时候根据需求进行分配
(2) 堆栈(stack) 位于RAM(Random Access Menory),通过堆栈指针分配内存,指针上移释放内存。下移分配内存。
JAVA编译器必须知道存储在堆栈中的数据确切的大小和生命周期,包括存储基本数据类型和对象引用类型
(3) 堆(heap) 位于RAM,存放JAVA对象,编译器不需要知道大小和生命周期。灵活性强,不过分配内存速度比stack慢
(4) 静态存储 位于RAM 存放着程序运行时一直存放的数据,但java对象不能存储在静态存储空间里
(5) 常量存储 位于ROM(Read Only Menory) 永远不会改变,
(6) 非RAM存储 数据存在于程序之外,可以不接受任何程序的控制,在程序没有运行时都可以存在,如持久对象和流
static讲解:
(1)如果要为某些特定数据分配内存,而不管要创建多少对象,或者根本就不需要创建任何对象。
(2)如果某些方法不予包含它的类的任何对象关联在一起,也就是说没有创建对象也可以调用这个方法。
通过static 来定义数据和方法可以给所有的对象共享使用。通过类可以直接访问。称之为类数据或类方法。
二、初始化
在类的内部,变量的初始化的先后顺序决定了初始化的顺序。即使变量定义分散于方法定义之间,它们仍然能在
任何方法(包括构造器)被调用之前得到初始化。
class A{
public A(int nCount){
System.out.println(""+nCount);
}
}
class B{
A a0 = new A(0);
public B(){
System.out.println("HelloWorld");
a2 = new A(3);
}
A a1 = new A(1);
public void f(){
System.out.println("f()");
}
A a2 = new A(2);
}
public class HelloWorld{
public static void main(String []args){
B b=new B();
b.f();
}
}
打印结果:
0
1
2
HelloWorld
2
f()
三、静态数据的初始化
静态的数据成员只有在它所对应的类的对象被创建时才被初始化,初始化以后就不会再初始化,并且是先于非静态成员
初始化之前。
class Bow1{
public Bow1(int market) {
System.out.println("Bow1("+market+")");
}
public void f(int market){
System.out.println("f("+market+")");
}
}
class Table{
static Bow1 b1 = new Bow1(1);
public Table(){
System.out.println("Table()");
b2.f(1);
}
public void f2(int market){
System.out.println("f2("+market+")");
}
static Bow1 b2 = new Bow1(2);
}
class CupBord{
Bow1 b3 = new Bow1(3);
static Bow1 b4 = new Bow1(4);
public CupBord(){
System.out.println("cupBord");
b4.f(2);
}
void f3(int market){
System.out.println("f3("+market+")");
}
static Bow1 b5 = new Bow1(5);
}
public class Init {
public static void main(String []args){
System.out.println("Creating new CupBord in main");
new CupBord();
System.out.println("Creating new CupBord in main");
new CupBord();
t2.f2(1);
t3.f3(1);
}
static Table t2 = new Table();
static CupBord t3 = new CupBord();
}
打印结果:
Bow1(1)
Bow1(2)
Table()
f(1)
Bow1(4)
Bow1(5)
Bow1(3)
cupBord
f(2)
Creating new CupBord in main
Bow1(3)
cupBord
f(2)
Creating new CupBord in main
Bow1(3)
cupBord
f(2)
f2(1)
f3(1)
总结:假如有一个Dog类
(1)首先创建Dog对象或者首次访问类的静态方法时,java解释器找到类路径,定位到Dog.class文件
(2)载入Dog.class文件,Dog类的静态方法和静态域被访问,并且只是在载入时初始化一次
(3)在堆上面为Dog分配足够的存储空间
(4)存储空间被清0,基本数据类型初始化为默认值,而引用类型设置为null
(5)执行所有出现域的初始化动作
(6)执行构造器
四、方法的绑定概念RTTI RunTime type indentify 运行时类型识别
方法调用和方法关联起来叫绑定。当一个方法前有final或者static时(被final修饰的方法是不能重载和重写的),方法是前期绑定的。因为在编译的时候就可以确定。
而一般的方法是后期绑定,即在运行时才确定是调用哪个方法如:
class Shap{
public draw(){};
}
class Circle extends Shap{
public draw (){};
}
//调用
Shap circle = new Circle();
circle.draw();//在这里只有在运行时才能确定是调用了Circle类里的方法draw();
那么在运行时是如何调用(或者绑定)Circle类的方法呢?这就需要知道类对象Class了
Class对象在需要时被载入,载入方法有制造这个类的对象或者通过类载入器载入。
它包含了类的有关信息。