黑马程序员技术交流社区

标题: 关于static修饰成员变量的问题 [打印本页]

作者: 李思杰    时间: 2013-3-13 14:00
标题: 关于static修饰成员变量的问题
本帖最后由 李思杰 于 2013-3-13 18:46 编辑
  1. class Person
  2. {
  3. String name;
  4. static String country="CN";
  5. public void show()
  6. {
  7. System.out.println(name+"::"+country);
  8. }
  9. }


  10. class StaticDemo
  11. {
  12. public static void main(String[] args)
  13. {
  14. Person p=new Person();
  15. p.name="lisi";
  16. p.country="US";
  17. Person p1=new Person();
  18. p1.show();
  19. //输出结果是null::US。我没给p1的country赋值,怎么会打出US?
  20. }
  21. }
复制代码
输出结果是null::US。
我没给p1的country赋值,怎么会打出US?

作者: 丁一    时间: 2013-3-13 14:13
static String country="CN";   声明了 country 为静态成员变量了   如果去掉 static 就不会改变
作者: 丁一    时间: 2013-3-13 14:18
官方解释为:静态变量在某种程度上与其他语言的全局变量相类似,如果不是私有的就可以在类的外表进行访问,此时不需要产生类的实例对象,只需要雷鸣就可以引用了
作者: 沉默de羔羊    时间: 2013-3-13 14:27
我想这个问题是,static修饰过的东西,会放到一个指定的内存区域,可以供大家使用。

你第一次就p.country="US";赋过值了,那么也就是改变了那个static分配的内存区域的值。

那么第二次虽然new 新的对象,但是他以后还是会调用static分配的内存区域。所以打印的值为“US”!
作者: 曾钦    时间: 2013-3-13 14:28
被static修饰的成员变量和成员方法独立于该类的任何对象。也就是说,它不依赖类特定的实例,被类的所有实例共享。
作者: 陈宇鹏    时间: 2013-3-13 14:35
本帖最后由 陈宇鹏 于 2013-3-13 14:40 编辑

我的想法是。因为static是属于全局的,也就是说,在第一个类中被赋值后就一直存在也就是说是全局的,而且还能被访问到,在创建了p对象之后,p中的country就是cn,可是之后,又被修改为us,这时的static的变量被替换了,也因为是它是全局的,所以在第二次new对象时,就变成了us。。仅仅是这么想的,估计不对。
就像二楼说的,去掉static,就是局部变量,局部变量,你无论怎么更改,都仅仅作用于本类中。
作者: 张亚青    时间: 2013-3-13 14:45
static特点:
1、随着类的加载而加载。
        也就是说:静态会随着类的消失而消失。
2、优先于对象存在。
3、被所有对象所共享。
4、可以被类名调用。
实例变量和类变量的区别:
1、存放位置
        类变量随着类的加载而存在于方法区中。(也就是说static变量只存在一份,在一个对象中更改后,其他对象中也会更改)
        实例变量随着对象的建立而存在于堆内存中。
2、生命周期
        类变量生命周期最长,随着类的消失而消失
        实例变量生命周期随着对象的消失而消失

【本问题的答案:】

综上所述,static变量被所有对象所共享,优先于对象而存在,随着类的加载而加载,那么所有创建的对象都会共用static变量(相当于全局变量),
就像问题中Person类中的static String country="CN";一旦在一个对象中更改,其他对象再访问该变量时,也会更改。
作者: 黑马17期-闫东东    时间: 2013-3-13 15:14
static String country="CN";   
当一个类的成员属性和方法被static修饰时,这个成员就是就是静态的,它属于类属性(静态属性),类方法(静态方法),属于这个类的所有对象所共享,类的实例访问它时,都是对同一个内存单元的访问,或操作。如下例子:
class Demo
{
static int id=10; //成员属性用static修饰
public static void main(String[] args)
{
Demo d1=new Demo();
d1.id++;
Demo d2=new Demo();
d2.id++;
System.out.println(d1.id);//
System.out.println(Demo.id);//可以用类名 来访问。
}
}
作者: HM张勇    时间: 2013-3-13 16:29
在Person类中,name、country都是全局变量,而static String country定义之后,就是静态全局变量,关键点是他们都是变量,而不是常量。所以show函数对变量赋值时,就会对变量的值改变。

我觉得你的意识想:把country设置成全局常量,应该这样写static final country ="CN";就不会改变country的值了。
作者: HM张勇    时间: 2013-3-13 16:54
HM张勇 发表于 2013-3-13 16:29
在Person类中,name、country都是全局变量,而static String country定义之后,就是静态全局变量,关键点是 ...

上述解释的不完全对。

成员变量一旦被static修饰后,成员变量的存储位置就由”堆内存“转到”共享区内存“。

共享区内存存储的数据有以下特点:

1,对象可以交替对共享内存数据调用和赋值;

2,一旦内存数据被更改后,不影响其他其他对象对内存的调用,同时其他对象对更新后的内存具有可见性。

静态全局变量是共有的,可以被更改,更改后的结果对调用其对象具有可见性。
作者: 张雪萍    时间: 2013-3-13 17:02
首先说一下static的用法:
static  静态修饰对象呗所有对象所共有
用法: 是一个修饰符,用于修饰成员变量,当成员被静态修饰后,
就多了一个调用方式,除了可以被对象调用外,还可以直接被类名调用,
格式:类名.成员变量。
static的特点 1随着类的加载而加载随着类的消失而消失,生命周期最长
2优先于对象存在
静态时先存在的,对象时后存在的
3被所有对象所共享
4 可以直接被类名调用
实例变量和类变量区别: 1存放位置
随着类的加载与方法一样存在方法区,(数据区,共享区)
实例变量随着对象的建立而存在于堆内存中 2生命周期。类变量生命周期最长
实例变量的生命周期随着对象的消失而消失       

静态使用注意事项:
1 静态方法只能访问静态成员,非静态方法既可以访问静态也可以访问非静态
2 静态方法中可以定义this,super关键字
因为静态优先于对象存在,所以静态方法中不可以出现this
3  主函数是静态的,


静态有利有弊
利处:对对象的共享数据进行单独空间的存储,节省内存,没有必要每个对象中
都存储一份,可以直接被类名调用。
弊端:生命周期过长,访问出现局限性(静态虽好,只能访问非静态。)
你把country设置为静态的,那就说明在内存中它只存在一份,在此之后的所有的操作都会作用于同一个内存中
你对p对象的country赋了值,就说明此时country值已经改变了,此后所有用person类new出来的对象的country值都将是US,因为无论new多少person类对象,
他们的country值都存储在同一个地方,
static就是用来节约内存的,因为每个人都有country属性,并且就中国人来说都是CN,所以没必要每个人都分配一个。
作者: HM赵磊    时间: 2013-3-13 18:32
这个问题要理解static的特性了
static修饰的成员随着类加载而加载(非static成员是通过new操作创建对象而存在对内存中);静态优先于对象存在(也就是说,当类加载进入内存,静态成员已经在内存中存在了);static修饰的成员被所有的对象所共享(缺点是生命周期过长),也就是所有对象在刚建立时存取的都是同一个东东。所以不难解释你的迷惑了,你创建了p1对象,虽然你没有为p1的country赋值,但是由于country是静态成员变量,所以当你创建p1的时候,其实他就已经存在了,并且为US
作者: HM周磊    时间: 2013-3-13 19:23
静态存在内存中的方法区呀,并随着类的加载而加载,随着类的消失而消失。
你创建p对象时,变量country随着类的加载存入方法区。当赋完值时。country变成“us”,
对象p变成垃圾。而country是不会的。所以你再创建另一个对象,调用country时,country是“us ”




欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/) 黑马程序员IT技术论坛 X3.2