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

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© 王乐 中级黑马   /  2012-9-22 18:51  /  2056 人查看  /  11 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文

这是1段比较类中数据是否相同的代码
我发现在Demo中定义a的时候如果加上了static修饰符,那么在创建对象的时候即使2个对象中的a赋的值是不同的,但是返回结果仍然是true。如何2个数都被判断为相等了
去掉static的话程序就正常了
请问这是为什么?
下面附上代码:
class Demo
{
        private static int a;
        Demo(int a)
        {
                this.a=a;
        }
       

        public boolean equals(Object obj)
        {
                if(!(obj instanceof Demo))
                {
                return false;
                }
                else
                {
                Demo b=(Demo)obj;
                return this.a==b.a;
                }       
        }
       
}



class Aquals
{
        public static void main(String[] args)
        {
                Demo d=new Demo(12);
                Demo d1=new Demo(2);
                System.out.println(d.equals(d1));
               
        }
}

评分

参与人数 1技术分 +1 收起 理由
刘芮铭 + 1 赞一个!

查看全部评分

11 个回复

倒序浏览
这是因为当一个变量被定义为static后,类被加载的时候就在内存中分配好了一块自己独立的位置(这个位置是始终存在的)可以通过类名来调用,也可以通过对象调用。对定义为static 的变量进行更改都是更改那一个。所以你用equals方法比较的时候是相等的。

评分

参与人数 1技术分 +1 收起 理由
admin + 1

查看全部评分

回复 使用道具 举报


static修饰属性(类变量):

        那么这个属性就可以用" 类名.属性名 "来访问,也就是使这个属性成为本类的类变量,为本类对象所共享

            无论哪一个对象修改了,别的对象调出来都是修改后的值 。

        类变量,会在加载时自动初始化,初始化规则和实例变量相同。

因为 static 是随着类的加载而加载的。静态先存在,对象后存在。静态是随着类的加载存放在方法区中,二不是堆内存中



class Demo {
        private static int a;

        Demo(int a) {
                this.a = a;
        }

        public boolean equals(Object obj) {
                if (!(obj instanceof Demo)) {
                        return false;
                } else {
                        Demo b = (Demo) obj;
                        return this.a == b.a;
                }
        }

        public static int getA() {//我给你 加了个getA()方法,获取a的值,因为你的a是private的
                return a;
        }

}

public class Aquals {
        public static void main(String[] args) {
                Demo d = new Demo(12);
                Demo d1 = new Demo(2);
                System.out.println(d.equals(d1));
                System.out.println(d.getA());//这里的输出结果,你会发现,结果是一样的,因为静态在本类对象中是共享的
                System.out.println(d1.getA());
        }
}


评分

参与人数 1技术分 +1 收起 理由
刘芮铭 + 1 赞一个!

查看全部评分

回复 使用道具 举报
优先加载而且只会初始化一次
回复 使用道具 举报
static 修饰的是全局变量,也就是说变量是属于类的,并不属于对象,但是对象可以访问并修改,不管有多少对象,static变量只有一个。

评分

参与人数 1技术分 +1 收起 理由
admin + 1 参与有奖

查看全部评分

回复 使用道具 举报
王陶成 发表于 2012-9-22 19:46
static修饰属性(类变量):

        那么这个属性就可以用" 类名.属性名 "来访问,也就是使这个属性成 ...

嗯,我看了你给的代码
我这么做是修改了类中的变量的值而不是对象中的是吗?
如果修改了类中变量的值那已经通过该类创建过对象的对象中的值也会随着改变?


还有我注意到你在定义 Aquals类的时候加上了public,请问这么做是为什么啊?
烦请不吝赐教

评分

参与人数 1技术分 +1 收起 理由
admin + 1 参与有奖

查看全部评分

回复 使用道具 举报
王乐 中级黑马 2012-9-23 09:47:29
7#
陈琦 发表于 2012-9-22 23:28
static 修饰的是全局变量,也就是说变量是属于类的,并不属于对象,但是对象可以访问并修改,不管有多少对 ...

那请问是不是说再类中定义了不加static的变量的话,创建了对象以后,每个对象中就都有1个属于自己的变量了
该变量也就是属于对象,而不属于类。只有有了对象才可以对该变量进行操作?
回复 使用道具 举报
王海宇 黑马帝 2012-9-23 10:21:20
8#
王乐 发表于 2012-9-23 09:47
那请问是不是说再类中定义了不加static的变量的话,创建了对象以后,每个对象中就都有1个属于自己的变量 ...

对的。实例变量只有在实例化类的时候才会一同创建这个变量。实例变量只属于创建他的那个对象,因此要访问实例变量,只能通过实例化一个对象去访问。静态变量是属于类的,是被所有对象共享的,在内存里面只存在一个,对它的修改也就会影响到所有的对象了。因为静态变量是属于类的,所以在类被加载到内存的时候就会创建它(类首先要被加载到内存里面,然后才能创建类的实例对象,因此创建静态变量会在创建对象之前进行),因此不需要创建对象,就可以通过类名来访问它

评分

参与人数 1技术分 +1 收起 理由
admin + 1 参与有奖

查看全部评分

回复 使用道具 举报
陈琦 中级黑马 2012-9-23 14:43:41
9#
王乐 发表于 2012-9-23 09:47
那请问是不是说再类中定义了不加static的变量的话,创建了对象以后,每个对象中就都有1个属于自己的变量 ...

恩恩,static修饰的变量存储在公共代码区,每个对象包括用类调用的时候都是连接到公共代码区,而非static的变量存储在堆内存(对象)中,我技术不太行,再深一点就不会了。

评分

参与人数 1技术分 +1 收起 理由
admin + 1 参与有奖

查看全部评分

回复 使用道具 举报
王乐 发表于 2012-9-23 09:44
嗯,我看了你给的代码
我这么做是修改了类中的变量的值而不是对象中的是吗?
如果修改了类中变量的值那已 ...

static标明的变量,变量所在的类的对象,一个对象改了值,另一个对象调用出来就是修改之后的值。无论建多少个对象都是一样的。

public因为我用的软件是myEclipse,编译的时候方便编译器找入口。这个其实不加也行。

你现在学习到哪里了

评分

参与人数 1技术分 +1 收起 理由
admin + 1 参与有奖

查看全部评分

回复 使用道具 举报
这个问题很简单啊,因为用static修饰的变量属于静态变量,类的多个对象共享这个变量,当Demo d1=new Demo(2) 时两个对象都共享的变量为2,所以两个对象的变量无论如何都相等,因为他们共享同一个变量

评分

参与人数 1技术分 +1 收起 理由
滔哥 + 1

查看全部评分

回复 使用道具 举报
首先,老弟你要明白static关键字的作用,以下是我在学习的小结,希望对你有用:
static:关键字,是一个修饰符。
用于修饰成员(成员变量和成员函数)。

特点:
1,想要实现对象中的共性数据的对象共享。可以将这个数据进行静态修饰。
2,被静态修饰的成员,可以直接被类名所调用。也就是说,静态的成员多了一种调用方式。类名.静态方式。
3,静态随着类的加载而加载。而且优先于对象存在。
注意:
静态看上去甚至使用上,感觉很美。但是有弊端。
1,有些数据是对象特有的数据,是不可以被静态修饰的。因为那样的话,特有数据会变成对象的共享数据。
        这样对事物的描述就出了问题。比如姓名数据。
        所以,在定义静态时,必须要明确,这个数据是否是被对象所共享的。
2,静态方法只能访问静态成员,不可以访问非静态成员。
        应为静态方法加载时,优先于对象存在,所以没有办法访问对象中的成员。
3,静态方法中不能使用this,super关键字。
        因为this代表对象,而静态在时,有可能没有对象。所以this无法使用。

4,主函数是静态的。
-----------------

成员变量和静态变量的区别:
1,
成员变量所属于对象。所以也称为实例变量。
静态变量所属于类。  所以也称为类变量。

2.
成员变量存在于堆内存中。
静态变量存在于方法去中。

3,
成员变量随着对象创建而存在。随着对象被回收而消失。
静态变量随着类的加载而存在。随着类的消失而消失。

4,
成员变量只能被对象所调用 。
静态变量可以被对象调用,也可以被类名调用。

所以,成员变量可以称为对象的特有数据,静态变量称为对象的共享数据。

静态的注意:
静态的生命周期很长。

评分

参与人数 1技术分 +1 收起 理由
admin + 1 恭喜,25分了

查看全部评分

回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马