一、java的类变量和实例变量:
java中的变量可分成两种:成员变量和局部变量。

1、局部变量包括以下几类:

  • 方法内的局部变量:作用域为方法体。
  • 代码块内的局部变量:作用域为代码块
  • 形参:方法内的形式参数,作用域为方法体。
注意:局部变量的生存期很短,被存储在方法的栈内存之中。


2、成员变量:类体内定义的变量,使用static修饰的成员变量称为
静态变量或者类变量。

没有被static修饰的成员变量称为
实例变量。

注意1:static关键字的用法

static可以修饰的部分包括:成员变量、方法、内部类、初始化代码块、内部枚举类。如果使用static修饰,这些成

员就属于类本身,否则属于类实例。

注意2:Java中的前向引用。

一般看来,java没有规定定义成员变量时要有先后顺序。但Java要求定义成员变量时必须采用合法的前向引用。

package com.beijng.object;

public class Object01 {

        //a变量在b变量没定义之前就引用它,属于非法前向引用

int  a = b + 1;
int b = 2;
}

同样,两个类变量也不允许前向引用。如下

public class Object02 {

        //属于非法前向引用
static int a = b + 1;
static int b = 2;
}


但是,一个实例变量总是可以引用类变量。如下
public class Object01 {

        //完全正常

 int  a = b + 1;
static int b = 2;
}

总结:
(1)b是类变量,a是实例变量,在java中,类变量的初始化总是在实例变量的初始化之前。

(2)在同一个JVM中,一个类对应一个Class对象,因此同一个JVM的一个类的类变量只需要一块内存空间。

但每个类可以创建多个Java对象。每创建一个Java对象,对象的实例变量就会被分配一块内存空间。

二、实例变量的初始化

1、实例变量的初始化有三种情况

  • 定义实例变量时指定初始值
  • 非静态初始化块中为实例变量指定初始值
  • 构造方法中对实例变量指定初始值
需要注意的是:第1、2中情况比第3中情况更早执行,1、2两种情况的执行顺序与它们在源程序中的排列顺序相同。


示例如下:
 
package com.beijng.object;

public class User {

String username;
String password;
public User(String username,String password){
System.out.println("执行构造方法");
this.username = username;
this.password = password;
}
{
System.out.println("执行非静态初始化块");
age = 18;
}
//定义时指定初始值
int age =20;
public String toString(){
return "username="+username+",password="+password+",age="+age;
}
public static void main(String[] args){
User user1 = new User("xiaoming","123");
System.out.println(user1);
}
}

 

———————————————————————————————————————————————————执行非静态初始化块
执行构造方法
username=xiaoming,password=123,age=20


其实,
定义实例变量指定的初始值、初始化块中为实例变量指定初始值的语句地位是平等的,当经过编译器处理后,它

们都被提取到构造方法中:

示例如下:

package com.beijng.object;

public class JavapToolTest {

int a = 30;
{
a = 31;
}
public JavapToolTest(){
System.out.println(a);
}
public JavapToolTest(String b){
System.out.println(b);
} }

使用命令:javap -c JavapToolTest 可以查看Java编译器对JavapToolTest做的处理,可以显示每个方法具体

的字节码。

如下图中,构造方法JavapToolTest()和JavapToolTest(String name)中都包含了初始化实例变量

语句。

 




三、类变量的初始化

1、类变量属于Java类本身,程序初始化Java类时会为类变量分配内存空间,执行初始化。

可以在定义类变量时指定初始值,或者在静态初始化块中为类变量指定初始值。

2、程序初始化过程:分成2个阶段

(1)系统为程序的类变量分配内存空间

(2)按初始化代码(定义时指定初始值和初始化块中执定初始值)的排列顺序对类变量执行初始化

3、示例省略

四、父类构造器

1、当创建Java对象时,程序总是会依次调用每个父类非静态初始化块、父类构造方法(总是从Object类开始)执行

初始化,最后才调用本类的非静态初始化块、构造方法执行初始化。

2、
Java对象是在构造方法中创建的吗?

示例如下:

package com.beijng.object;
class Base {
private int i = 2;
public Base(){
System.out.println(this.i);//输出2
this.display();
}
public void display(){
System.out.println(i);//输出0
}
} class Derived extends Base {
private int i = 22;
public Derived(){
i = 222;
}
public void display(){
System.out.println(i);
}
} public class ConstructorTest { public static void main(String[] args) {
new Derived();
} }



注解
:(1)构造方法只是负责对Java对象实例变量进行初始化(即赋予初始值),在执行构造方法之前,该对象所占

用的内
存已经被分配了,这些内存里都默认是控制,基本类型变量的默认值是0或false,引用类型变量的默认值都是

null.  

(2)所以在程序执行new Derived()时,系统先为Derived对象分配内存空间,此时系统内存需要为Derived

对象分配两块内存,一个存放属于Base类定义的i实例变量,一个存放属于Derived类定义的i实例变量,此时这两个

实例变量的值都为0. 然后,在执行Derived类的构造方法之前,首先会执行Base类的构造方法,把Base的i变量赋

值为2,接着执行this.display(),
问题出现了?this代表哪个类的对象呢?

注意:当this在构造方法中时,this代表正在创建的Java对象,此时情况是:this位于Base构造方法内,但是这些

代码实际放在Derived的构造方法内执行,即
Derived的构造方法隐式调用了Base类的构造方法,所以此时this代表

的应该是
Derived对象,而不是Base对象。


(3)当变量的编译时类型和运行时类型不同时,通过该变量访问它引用的对象的实例变量时,该实例变量的值由声明

该变量的类型决定。但是通过该变量调用它引用对象的实例方法时,该方法行为将由它实际所引用的对象决定。

所以,当程序访问this.i时,
this虽然代表
Derived对象,但是它位于Base构造方法中,它的编译类型是Base,

所以就会访问Base类中定义个i实例变量,即输出2.  但是执行this.display()时,则实际表现出
Derived对象

的行为,即输出
Derived对象的i实例变量,也就是0.















(二)Java对象与内存控制的更多相关文章

  1. Java 对象及其内存控制

    作者:禅楼望月(http://www.cnblogs.com/yaoyinglong) 更新:其实这里有好多的变戏法,只要你理解了他们在JVM的中的实现机制,就豁然开朗了.有时间我会把这些变戏法的东西 ...

  2. JAVA对象与内存控制

    1.1 实例变量和类变量 成员变量和局部变量: 局部变量分为三大类: 1)形参:在方法签名中定义的局部变量,由方法调用者为其赋值,随方法的结束而消亡. 2)方法内的局部变量:在方法内定义的局部变量,随 ...

  3. JVM总结-java对象的内存布局

    在 Java 程序中,我们拥有多种新建对象的方式.除了最为常见的 new 语句之外,我们还可以通过反射机制.Object.clone 方法.反序列化以及 Unsafe.allocateInstance ...

  4. 10 Java 对象的内存布局

    Java 创建对象的方式 1:new 语句和反射机制创建.该方式会调用类的构造器,同时满足诸多约束.如果一个类没有构造器的话,Java 编译器会自动添加一个无参数的构造器.子类的构造器需要调用父类的构 ...

  5. Java对象的内存布局以及对象的访问定位

    一 Java对象的内存布局 在HotSpot虚拟机中,对象在内存中的布局分为3个区域 对象头(Header) Mark Word(在32bit和64bit虚拟机上长度分别为32bit和64bit)存储 ...

  6. 3 Java对象的内存布局以及对象的访问定位

    先来看看Java对象在内存中的布局   一 Java对象的内存布局 在HotSpot虚拟机中,对象在内存中的布局分为3个区域 对象头(Header) Mark Word(在32bit和64bit虚拟机 ...

  7. Java对象的内存模型(一)

    前言 新人一枚,刚刚入门编程不久,各方面都在学习当中,博文有什么错误的地方,希望我们可以多多交流! 最近,在开发App后台过程中,需要将项目部署到云服务器上.而云服务器的内存大小却只有1G.要如何做到 ...

  8. Java对象的内存布局

    对象的内存布局 平时用java编写程序,你了解java对象的内存布局么? 在HotSpot虚拟机中,对象在内存中存储的布局可以分为3块区域: 对象头 实例数据 对齐填充 对象头 对象头包括两部分信息: ...

  9. java对象在内存的大小

    前言 一直以来,对java对象大小的概念停留在基础数据类型,比如byte占1字节,int占4字节,long占8字节等,但是一个对象包含的内存空间肯定不只有这些. 假设有类A和B,当new A()或者n ...

随机推荐

  1. 【NOIP 2014 DAY1 T3】飞扬的小鸟(DP)

    题目描述 Flappy Bird 是一款风靡一时的休闲手机游戏.玩家需要不断控制点击手机屏幕的频率来调节小鸟的飞行高度,让小鸟顺利通过画面右方的管道缝隙.如果小鸟一不小心撞到了水管或者掉在地上的话,便 ...

  2. 协议(porotocol)

    fly.h: #import <Foundation/Foundation.h> @protocol Fly -(void) go; -(void) stop; @optional -(v ...

  3. Android开发之BroadcastReceiver的使用

    1.静态注册. 在manifest中注册. <receiver android:name="com.exce.learnbroadcastreceiver.MyReceiver&quo ...

  4. VJP1071新年趣事之打牌(背包+输出路径)

    简单的01背包 保存下方案总数 其实就是dp[v]值 输出路径dfs一下 #include <iostream> #include<cstdio> #include<cs ...

  5. 【转】win7 旗舰版激活密钥

    原文网址:http://zhidao.baidu.com/question/1496641289562471179.html 旗舰版KH2J9-PC326-T44D4-39H6V-TVPBYTFP9Y ...

  6. REST Web 服务介绍

    在项目上使用到了Rest技术,应该是Rest的服务概念才对.主要是对外(BPM)暴露API来提供Service.推荐一篇有质量的文章,接下来会系统一点的学习一下Restful概念.http://kb. ...

  7. STL总结之list

    STL中list和我们传统意义上的链表一样可以进行动态节点添加和释放. 优点:适合动态删除和添加 缺点:不支持随机访问.   C++标准对list模板声明: template < class T ...

  8. FZU2234 牧场物语 DP

    题意:先去再回,不能吃重复的,获取最大值 分析:等价于两个人同时去,不能吃重复的 定义dp[i][j][k]表示从起点走k步,第一个人的横坐标是i,第二个人的横坐标是j的最最大值 这个题和bc上一个回 ...

  9. js打印的两种方法

    第一种: <!--startprint1-->……打印的内容放在这里…… <!--endprint1--> //打印 function preview(DivID) { ) { ...

  10. JZ2440开发笔记(7)——2440启动方式

    JZ2440的启动方式有两种,一种是从NOR FLASH中启动,还有一种就是从NAND FLASH中启动. 如果从NOR FLASH启动,CPU会访问NOR FLASH的0地址,而0地址位于BANK0 ...