黑马程序员技术交流社区

标题: Java中实例变量和类变量的属性访问问题 [打印本页]

作者: dev    时间: 2012-6-26 17:08
标题: Java中实例变量和类变量的属性访问问题
本帖最后由 翁游龙 于 2012-6-27 09:38 编辑

我知道使用static修饰的成员变量是类变量,属于该类本身,没有使用static修饰的
成员变量是实例变量,属于该类的实例。关于以下代码有点小小的疑问:

class Person{
        String name;
        int age;
        static int eyeNum;
        public void info(){
                System.out.println("我的名字是:" + name + ",年龄是:" + age);
        }
}
public class FieldTest{
        public static void main(String[] args){
                Person.eyeNum = 2;
                System.out.println("1、通过Person类访问eyeNum类变量:" + Person.eyeNum);

                Person p = new Person();
                p.name = "张三";
                p.age = 20;
                p.eyeNum = 3;
                System.out.println("2、通过p变量访问Person类的eyeNum类变量:" + p.eyeNum);
                p.info();
        }
}


我的问题是:该程序中可以通过Person类名直接访问eyeNum属性,也可以通过Person实例p来
访问eyeNum属性,那么这两种访问方式有什么区别,哪种比较高效?



作者: 李伟    时间: 2012-6-26 17:25
  static int eyeNum;//既然定义成静态的了,就说明这个是共享数据,既然是共享数据,直接用类调用就可以了,当然用对象调用也可以,只是没有什么意义,如果直接用类名调用,一看就知道是共享数据了
作者: 张华廷    时间: 2012-6-26 17:30
public static int eyeNum;
static声明的变量是静态的,依赖于类而不依赖于示例

说白点,就是它是类的属性,所有这个类的实例都共用这么一个变量,而name这个变量每个实例都会有一个

看内存:
第一次用到这个类的时候,就会在内存中为eyeNum分配空间,然后在new出一个实例的时候,所有的eyeNum都会指向这个空间,所以他们共用一个值
而name,没有static声明,在每new出一个实例的时候都会为name分配出一个新的空间,所有的实例各自指向自己的name


作者: 车风波    时间: 2012-6-26 17:31
应该是通过Person类名直接访问eyeNum属性高效。
我在Eclipse中用对象调用,会有这个提示:

The static field Demo.x should be accessed in a static way:应该用静态方式访问Demo中的 静态变量x,
所以肯定是用类名调用好。
作者: 赵庆礼    时间: 2012-6-26 17:33
静态变量和实例变量都可以用一个具体实例加.来引用。
静态变量还可以直接用类名加.进行引用。
静态变量和实例变量最大的区别是静态变量在内存中只有一份,所以该类的所有实例共享该变量;而实例变量随实例的不同可以不相同。
作者: 刘笑    时间: 2012-6-26 18:12

   实例变量需要通过类的实例对象来调用,而静态变量,只要类名就可以调用了 .不过静态变量和实例变量都可以用一个具体实例加“.”来引用
     静态变量是类相关的变量,所以他的生命周期是从这个类被声明,到这个类彻底被垃圾回收机制彻底回收才会被销毁。
    实例变量是这个类的对象里的变量,它和静态变量不同,它只能由创建出的对象来调用,所以实例变量是从这个对象(其实就是实例)被创建开始,直到这个对象没有任何引用变量去引用它,最终被垃圾回收站回收,这时这个实例变量也跟着就消失了。
简言之,静态变量生命周期就是类的开始和销毁;实例变量生命周期就是对象的开始和销毁
    同时,类的静态变量在内存中只有一个,java虚拟机在加载类的过程中为静态变量分配内存,静态变量位于方法区,被类的所有实例共享。静态变量可以直接通过类名进行访问,其生命周期取决于类的生命周期。而实例变量取决于类的实例。每创建一个实例,java虚拟机就会为实例变量分配一次内存,实例变量位于堆区中,其生命周期取决于实例的生命周期。
    既然静态变量是在执行前就补分配到内存中的,即程序在加载之前系统已为该类变量分配了内存空间,所以我觉得应该是通过静态变量效率高一些吧,即通过Person类名直接访问eyeNum属性效率高一些

作者: whocases    时间: 2012-6-26 18:20
在生成每个类的实例对象时,Java运行时系统为每个对象的实例变量分配一块内存,然后可以通过该对象来访问这些实例的变量。不同对象的实例变量是不同的。而对于类变量来说,在生成类的第一个实例对象时,Java运行时系统对这个对象的每个类变量分配一块内存,以后再生成该类的实例对象时,这些实例对象将共享同一个类变量,每个实例对象对类变量的改变都会直接影响到其他实例对象。类变量可以通过类名直接访问,也可以通过实例对象来访问,两种方法的结果是相同的。
作者: Forever。    时间: 2012-6-26 18:40
static修饰过的成员变量,可以直接用类名点.调用,而当程序只要加载这个类的时候这个变量就已经存在于内存中了。
需要注意的是 静态属性和方法属于类方法,加载类后,就已经存在静态属性和方法,实例是需要用new构造出来后 才会有引用
根据先后顺序,就有以下两条规则
1、非静态的方法可以调用静态的或者非静态的属性和方法;
2、静态的方法不可以调用非静态的属性和方法,因为非静态的还不一定存在,只能先构造出来后,再通过实例引用
例如 在main方法中 可以直接调用static 的方法,调用非static方法 需要先构造出类的实例,通过实例才能调用方法

关于效率应该没区别,如果你在程序中需要用到static你用普通的变量是代替不了的,就算可以实现功能很可能会走很多的弯路
而你没有必要用static的时候用了,也是一种浪费,而且造成程序的安全系数大打折扣
作者: 黄奕豪    时间: 2012-6-27 00:55
利用类名直接调用效率高,利用实例的话得先找引用,找引用才发现是静态的,最后还是调用的类名调用~!因为就像命名空间一样,静态方法在方法区内是以(类名.方法)存储的!




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