疯狂java基础功16讲(2)------对象与内存控制

[b]Java内存管理分为两个方面:内存分配和内存回收。[/b]
内存分配特指创建Java对象时JVM为该对象在堆内存中所分配的内存空间。
内存回收指的是当该Java对象失去引用,变成垃圾时,JVM的垃圾回收机制自动清理该对象,并回收该对象所占用的内存。

由于JVM垃圾回收机制由一条后台线程完成,本身非常消耗性能的,因此如果[b]肆无忌惮地创建对象[/b],让系统分配内存,这样会有两个坏处:
A:不断分配内存使得系统中可用内存减少,从而降低程序运行性能。
B:大量已分配内存的回收使得垃圾回收的负担加重,降低程序的运行性能。

[b]本课主要介绍
创建Java对象时的内存分配细节, 即内存管理管理中关于内存分配方面知识。[/b]

一、实例变量与类变量

Java程序的变量大体可分为成员变量和局部变量。
1、局部变量,局部变量可以分为3类。
A:形参,在方法签名中定义的局部变量,由方法调用者为其赋值,随方法结束消亡
B:方法内的局部变量,在方法内定义,在方法内对其进行显示初始化,随方法结束消亡。
C:代码块内的局部变量,在代码块内定主,在代码块内对其进行显示初始化,随代码块结束而消亡。
[b]局部变量的作用时间很短暂,它们都被存储在方法的栈内存中。[/b]

2、成员变量,成员变量可以分为非静态变量(实例变量)或静态变量(类变量)
A:非静态变量,没有使用static修饰符修饰的变量
B:静态变量,使用了static修饰


public class TwoObject {
/*1
//下面代码将提示:非法向前引用
int num1 = num2 + 2 ;
int num2 = 3 ;
*/

/*2
//下面代码将提示:非法向前引用
static int num1 = num2 + 1 ;
static int num2 = 2 ;
*/

/*3
* num2的初始化时机总是位于num1之前
*/
//下面代码完全正常
int num1 = num2 +1 ;
static int num2 = 2 ;

}



A、实例变量和类变量
使用static修饰的成员变量为类变量,属于该类本身;
没有使用static修饰的成员变量为实例变量,属于该类的实例。

由于同一人JVM内每个类只对应一个Class对象,因此同一个JVM内的一个类变量只需一块内存空间;
但对于实例变量而言,每创建一次实例,就需要为实例变量分配一块内存空间。

实例变量属于对象,类变量属于类的特性。

public class TwoObject2 {
public static void main(String[] args) {
//类变量属于该类本身,只要该类初始化完成,程序即可使用类变量
Person.eyeNum = 2 ;
//通过Person类访问eyeNum类变量
System.out.println("Person 的eyeNum属性:"+Person.eyeNum);

//创建 1个Person对象
Person p = new Person();
p.name = "孙悟空";
p.age = 500;
//通过p访问Person类的eyeNum类变量
System.out.println("p.eyeNum="+p.eyeNum);
p.info();
//创建第2个Person对象
Person p2 = new Person();
p2.name = "唐僧";
p2.age = 20 ;
//通过p2修改Person类变量eyeNum
p2.eyeNum = 3 ;
System.out.println("p.eyeNum="+p.eyeNum);
System.out.println("p2.eyeNum="+p2.eyeNum);
System.out.println("Person.eyeNum"+Person.eyeNum);

}
}

class Person{
String name ;
int age ;
static int eyeNum;
public void info(){
System.out.println("name="+name+" age="+age);
}
}




B、实例变量的初始化时机

对于实例变量而言,它属于Java对象本身,每次程序创建Java对象时都需要为实例变量分配内存空间,并执行初始化。
程序可以在3个地方为实例变量执行初始化:
A:定义实例变量时指定初始值;
B:非静态初始化块中对实例变量指定初始值;
C:构造器中对实例变量指定初始值;
A和B两种方式比C种更早执行,A和B的执行顺序与它们在程序中的排列顺序相同。

定义实例变量指定初始值 、初始化块中指定初始值,地位是平等的,当经过编译器处理后,它们都将被提取到构造器中。并总是位于构造器的所有语句之前;合并后,两种语句的顺序保持它们在源代码中的顺序。


package com.crazyjava;

public class TwoObject3 {
public static void main(String[] args) {
Cat cat = new Cat("tom",2);
System.out.println(cat);

}
}
class Cat{
String name ;
int age ;
public Cat(String name,int age) {
this.name = name ;
this.age = age;
}
{
weigth = 2.0 ;
}
double weigth = 2.3;
@Override
public String toString() {
return "Cat[name="+name+",age="+age+",weigth="+weigth+"]";
}

}

Output: Cat[name=tom,age=2,weigth=2.3]



C、类变量初始化时机

类变量属于Java类本身,只有当程序初始化该Java类时才会为该类分配内存空间,并执行初始化。

程序可以在2个地方为类变量来执行初始化:
A:定义类变量时指定初始值
B:静态初始化块中对类变量指定初始值
这两种方式的顺序与它们在源程序中排列顺序相同。


package com.crazyjava;

public class TwoObject4 {
//定义count类变量,定义时指定初始值
static int count = 2;
//通过static块为name指定初始值
static{
System.out.println("初始化块");
name = "Java编程";
}
static String name = "疯狂Java讲义";

public static void main(String[] args) {
System.out.println("count="+count+" name="+name);
}
}

Output:
初始化块
count=2 name=疯狂Java讲义




二、父类构造器

[b]当创建任何对象时,程序总会先依次调用每个父类非静态初始化块、父类构造器(总是从Object开始)执行初始化,最后才调用本类的非静态初始化块、构造器执行初始化。[/b]


三、父子实例的内存控制


四、final修饰符
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值