A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© 黑马-王鹏 中级黑马   /  2013-3-14 23:11  /  3180 人查看  /  8 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文

本帖最后由 黑马-王鹏 于 2013-3-15 09:07 编辑

在语法定义上的区别:静态变量前要加static关键字,而实例变量前则不加。
在程序运行时的区别:实例变量属于某个对象的属性,必须创建了实例对象,其中的实例变量才会被分配空间,才能使用这个实例变量。静态变量不属于某个实例对象,而是属于类,所以也称为类变量,只要程序加载了类的字节码,不用创建任何实例对象,静态变量就会被分配空间,静态变量就可以被使用了。总之,实例变量必须创建对象后才可以通过这个对象来使用,静态变量则可以直接使用类名来引用。
例如,对于下面的程序,无论创建多少个实例对象,永远都只分配了一个staticVar变量,并且每创建一个实例对象,这个staticVar就会加1;但是,每创建一个实例对象,就会分配一个instanceVar,即可能分配多个instanceVar,并且每个instanceVar的值都只自加了1次。?求解:这句话怎么理解啊?
  1. public class VariantTest
  2. {
  3. public static int staticVar = 0;
  4. public int instanceVar = 0;
  5. public VariantTest()
  6. {
  7. staticVar++;
  8. instanceVar++;
  9. System.out.println(“staticVar=” + staticVar + ”,instanceVar=” + instanceVar);
  10. }
复制代码

点评

如果问题已经解决了,请将分类改为已解决,谢谢  发表于 2013-3-15 08:13

评分

参与人数 1技术分 +1 收起 理由
黄玉昆 + 1

查看全部评分

8 个回复

倒序浏览
静态变量 你可以理解为  是这个类所实例化的所有对象共享的一个变量  无论这个类实例化出的任意对象对其进行操作 其结果都会改变并被保留下来
而非静态变量  可以理解为  是类所实例化出的 某一个对象的 属性  只有这个对象对其进行的操作 其结果都会改变并被保留下来 而和这个类实例化出的其他对象无关
比如 VariantTest a = new VariantTest();
VariantTest b = new VariantTest();
a.staticVar  和b.staticVar其实是同一个东西

a.instanceVar 只对应对象a
b.instanceVar 只对应对象b  它们两个本身没有关系

评分

参与人数 1技术分 +1 收起 理由
黄玉昆 + 1

查看全部评分

回复 使用道具 举报
本帖最后由 吴上波 于 2013-3-14 23:33 编辑

无论创建多少个实例对象,永远都只分配了一个staticVar变量,并且每创建一个实例对象,这个staticVar就会加1:
staticVar是静态变量,属于类位于内存的方法区里,所有的对象均指向同一个staticVar(存放在方法区中)。每当创建一个新的对象时,就会调用一次构造函数,所以staticVar就会自加1,创建多少个对象,staticVar就会自加多少次。           

但是,每创建一个实例对象,就会分配一个instanceVar,即可能分配多个instanceVar,并且每个instanceVar的值都只自加了1次:
instanceVar是成员变量,每创建一个对象时,构造函数就被调用,在构造函数调用时会为相应的对象分配一个intanceVar成员变量,各个对象有自己intanceVar(在自己相应的堆内存中),每个intanceVar只会自加一次。所以创建多少个对象就会有多少个instanceVar成员变量产生,但是每个intanceVar都只自加一次

评分

参与人数 1技术分 +1 收起 理由
黄玉昆 + 1

查看全部评分

回复 使用道具 举报
假如你VariantTest a = new VariantTest();
           VariantTest b = new VariantTest();
静态变量是存放在方法区里,他的生命周期和本类一样长,你new两个对象他就会加两次。
非静态变量存放在堆里,由对象对他赋值,你new了a,b则会在堆里产生两个对象,他们分别有自已的instanceVar,相互没有关系。
回复 使用道具 举报
  1.     public class VariantTest
  2.     {
  3.                 public static int staticVar = 0;   //staticVar属性是类属性,不属于某个对象
  4.                 public int instanceVar = 0;
  5.                 public VariantTest()
  6.                 {
  7.                         staticVar++;
  8.                         instanceVar++;
  9.                         System.out.println("staticVar=" + staticVar + ",instanceVar=" + instanceVar);
  10.                 }
  11.                 public static void main(String[] args)
  12.                 {
  13.                         new VariantTest();   //第一次创建一个对象,该对象有自己的属性instanceVar
  14.                         new VariantTest();   //第二次创建一个对象,该对象有自己的属性instanceVar,与第一次的属性instanceVar不同
  15.                         new VariantTest();   //第三次创建一个对象,该对象有自己的属性instanceVar,与第一,二次的属性instanceVar不同
  16.                 }
  17.     }
复制代码
这么理解,静态属性是随着类的加载而存在的,当对象不存在时,静态属性就已经存在,并且初始值为0,静态属性属于类,随着类的存在而存在,并不属于哪个对象,而对象属性是在创建对象的时候才会在内存中开辟空间,才能被对象初始化或赋值。
      对于上面的程序,当类加载时staticVar已经存在,当第一次new VariantTest();时,该对象有了一个属性叫instanceVar,调用VariantTest的构造函数, staticVar和instanceVar各自加1;当第二次new VariantTest();时,又有了一个新对象,新对象也有一个属性叫instanceVar并且初始值=0,调用构造函数时,新的instanceVar被加1,值为1,此时类 VariantTest还存在,所以静态属性staticVar还是存在的,被加1后,staticVar=2;当第三次new VariantTest();时,再三创建了一个新对象,新对象还是具备自己的属性instanceVar并且初始值=0;调用构造方法时,instanceVar加1,instanceVar=1,此时类VariantTest存在,staticVar依然存在,staticVar+1,staticVar=3;
      总之,理解好静态变量是随着类的存在而存在,跟对象无关,而非静态属性跟对象相关,没创建一个新对象,该对象就有一个自己的属性,这个属性只跟该对象有关,跟其他new出来的对象无关,其它对象无法操作该对象的属性!
回复 使用道具 举报
本帖最后由 谢洋 于 2013-3-14 23:55 编辑

无论创建多少个实例对象,永远都只分配了一个staticVar变量,并且每创建一个实例对象,这个staticVar就会加1;但是,每创建一个实例对象,就会分配一个instanceVar,即可能分配多个instanceVar,并且每个instanceVar的值都只自加了1次。?求解:这句话怎么理解啊?
1、static var在类的字节码被加载的时候就加载到内存的静态区,产生对象时,不会再新建一份
2、而instance Var,每创建一个对象时,都会在堆内存中开辟开间存放,这样子,每创建一个对象都会产生一个intance var
3、非静态方法,在产生对象时会在相应堆内存中开辟一个指向字节码中对应非静态方法的地址,并非把实际方法存入堆内存中,
当对象调用方法时,正是利用这个指向字节码中的非静态方法地址,找到所需方法,并让JVM把该方法"copy"栈内存中,,以供对象使用,
当该方法一旦被使用完,它在栈内存占用的空间就会被释放(JVM如果不这样做,就会占用大量的内存),这也是为什么方法内局变量一旦在方法执行完后就消失的原因,
也是为什么静态方法不能调用非静态方法的原因。
回复 使用道具 举报
我认为你是对内存的划分不是很理解,就是不会话内存图。首先给你认识下Java变量
的所以存储位置:
1.寄存器:最快的存储区, 由编译器根据需求进行分配,我们在程序中无法控制.
2. 栈:存放基本类型的变量数据和对象的引用,但对象本身不存放在栈中,而是存放在堆(new 出来的对象)或者常量池中(字符串常量对象存放在常量池中。)
3. 堆:存放所有new出来的对象。
4. 静态域:存放静态成员(static定义的)
5. 常量池:存放字符串常量和基本类型常量(public static final)。
6. 非RAM存储:硬盘等永久存储空间

我们只要关注栈、堆、静态域就足够了。回到程序中
VariantTest a = new VariantTest();
VariantTest b = new VariantTest();
(1)对于instanceVar只加1的疑惑解释
我们实例化了两个对象,这两个对象都有了int instanceVar=0;这个变量
,换句话说他们在不同的箱子里面保存,那你对各自箱子里面的数据操作,肯定
就不会影响到其他的箱子了。所以 instanceVar的值就自加一次。
(2)每实例化一次staticVar就加1的疑惑解释
你要知道staticVar 是一个static变量是被存储在静态域的,这个域会随着类的存在而产生的,
当你运行VariantTest a = new VariantTest();之后就已经存在这个类所以staticVar就会一直存放
在静态域,所以再运行VariantTest b = new VariantTest();就会继续从原来的基础上加上去。

再给你补充点知识:
对于栈和常量池中的对象可以共享,对于堆中的对象不可以共享。栈中的数据大小和生命周
期是可以确定的,当没有引用指向数据时,这个数据就会消失。堆中的对象的由垃圾回收器
负责回收,因此大小和生命周期不需要确定,具有很大的灵活性。
希望对你有帮助。

评分

参与人数 1技术分 +1 收起 理由
黄玉昆 + 1

查看全部评分

回复 使用道具 举报
这个问题分三点说:
一、首先还是静态和非静态的问题。静态修饰的变量可以称为静态变量或者类变量,她是随着类的加载而加载的,她比对象现在存在于内存中。非静态变量也就是实例变量,也可以理解为对象变量,她是通过new操作符创建对象时才存在于对内存中的。
二、静态成员有个特殊的地方-------可被所有的该类对象所共享,也就是说创建该类的所有实例(对象)共同使用这一个静态成员,这个对象也可以对他进行操作,另一个的对象也可以接着上一次操作的结果再对他进行操作,这就是为什么“无论创建多少个实例对象,永远都只分配了一个staticVar变量,并且每创建一个实例对象,这个staticVar就会加1”的原因
三、实例变量,通俗理解对象变量,也就是每一个对象自己独有的变量,与其他对象的这个变量无关,在通过new操作符创建每个实例(对象)的时候,都会在实例自己的堆内存中存放自己的实例变量,各自的实例变量发生变化时,不影响其他实例的这个成员,这也就是“每创建一个实例对象,就会分配一个instanceVar,即可能分配多个instanceVar,并且每个instanceVar的值都只自加了1”的原因

希望可以解答你的迷惑。

评分

参与人数 1技术分 +1 收起 理由
黄玉昆 + 1

查看全部评分

回复 使用道具 举报
静态变量和实例变量的区别?
1.静态变量随着类的加载而存在,而实例变量是当创建对象的时候才在内存中划分一块空间。
2.静态变量被该类的所有对象共亨,也就是说该类的任何一个对象都可以去改变它的值。而实例变量只有它所属对象可以直接改变其值或调用对象对外提供的方法去改变其值。
3.静态变量的生命周期很长。而实例变量的生命周期较短,会随着对象的消亡而垃圾回而回收。
4.静态变量可以直接被类名调用而不用对象调用。而实例变量只能被对象调用。
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马