发表于: 2018-04-03 22:56:39
2 673
今天完成的事:
学习对象和内存控制
1.类变量和实例变量
·变量定义没有先后顺序,但是实际上应该算是有的,根据在内存中初始化时机的不同就有先后的顺序。
·类变量的初始化总是在实例变量的初始化之前,或者说类变量就是初始化变量
·类变量属于类,当类被初始化的时候类变量也就随之初始化。而实例变量属于对象。当然类也是对象。
两者最大的不同就是存放于内存中,当一个类被初始化的时候,它里面的类变量(如果有的话)也被初始化,也就是说在堆内存中的空间不变,是在这个类里面的。以后无论怎样去访问类变量都是相当于通过这个类去访问这个类变量。
而实例变量则不同,在new对象的时候,每有一个新对象被创建,堆内存中就会在这个类的空间外分配出一个新的空间存放这个对象实例,可以通过这个对象来访问它的类变量。但是无论创建多少的新对象,通过它访问的类变量都是同一个地址。
比如user类有一个类变量为 static eat = 1;user被初始化的时候eat就在其中被初始化了,它不会被分配新的内存。当我们new两个新对象:
User user1 = new User();
User user2 = new User();
这时候,无论是通过user1访问est还是通过user2访问,它们访问的都是同一个内存地址,都是先通过User这个类去访问到的,所以无论是谁去改变了这个类变量的值,都是一样的。
比如通过user2改变eat的值
user2.eat = 2 ;
然后再去通过user1访问它的话,它的值就是已经被改变的值,也就是2。
2.栈内存的数据共享
(java的内存划分:寄存器/本地方法区/方法区/栈内存/堆内存)
栈与堆都是内存,它们的优缺点是:
栈存取速度比堆动作快,栈储存的是基本数据类型、引用数据类型和局部变量等。存放对象生命周期一到就会立即释放。
堆可以动态分配内存大小,存放的是对象实体,new的都存在堆之中。对象一旦没有被引用不会立即释放,而是会被回收机制不定时的释放。
存放在栈中的数据是共享的。比如创建两个数据类型:
int a = 1;
int b = 1;
编译器会先在栈中创建一个地方来储存a,再去找有没有指向1的地址,有就把a指向1的地址,没有就开辟一个。然后再创建一个地方来储存b,再把b指向1的地址,这样就是共享1这个数据。如果修改了a的值,编译器就会把a指向一个新的地址,而b指向的地址不变,1也不变,它就在那。
3.实例变量初始化的时机:
(这个没怎么明白先后顺序。abc都是被合并到构造器之中,但是a和b总是位于c(构造器的所有语句)之前。)
a·定义实例变量的时候初始化;
b·非静态初始化块中对实例变量指定初始值;
c·构造器中对实例变量指定初始值。
4.父类与子类
创建java对象时的执行顺序:
依次调用每个父类非静态初始化块——父类构造器——本类非静态初始化块——本类构造器执行初始化。最后返回本类的实例(从最顶级父类开始)
·关于java对象是否是由构造器创建的:构造器只是负责对对象实例变量执行初始化,在它之前这些对象所占的内存已经被分配下来,只是里面默认值都是0或者false或者null。
父类子类和this:编译时类型和运行时类型。
this在构造器中的时候,代表的是正在初始化的对象。
父类和子类拥有同名变量的时候,将会在内存中为每一个变量分配一块内存。但是直接在子类中使用变量的时候是当前子类的变量,父类的同名变量需要创建父类对象去访问。但是,这些同名变量都是储存在子类对象的内存中的,子类不仅保存了自己定义的所有实例变量,还保存了它的所有的父类所定义的全部实例变量。也就是说,父类有多少变量,子类就会多保存多少变量。即使是同名的也一样。
明天计划的事:
继续学习java基础,基础非常深
问题和收获:
1,类变量和实例变量在内存中的分配
2.父类和子类在内存中调用和引用(有些地方不明白,比如父类中使用this方法,子类使用super调用)
3.了解了内存的释放,知道了还有内存泄漏这个概念
4.一些比较杂的东西…比如说来非法向前引用、父类访问子类的实例变量、父类与子类相同的变量名(主要是看系统分配内存的问题)等等。
评论