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

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© hejinzhong 中级黑马   /  2014-7-9 01:29  /  2030 人查看  /  17 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文

在视频中,看了利用this关键字去比较,一个人是否与自己同龄时,遇到的一些改进问题。先附上代码:

//需求:比较一个人是否与自己同龄。

//先创建一个人的类
class Person
{
    int age;
    Person(int age)//构造函数
    {
        this.age=age;
     }
    public boolean conpare(Person p)//比较是否为同龄人的方法,返回为真或假
    {
        return this.age==p.age;
    }
}

class Demo
{
    public static void main(String[] args)
    {
        Person p = new Person(10);
        Person p1 = new Person(12);
        System.out.println(p1.compare(p));
    }
}
这个结果,是创建了两个新的对象并比较,当然没有问题。

//新需求:我想在Person类内创建一个初始个体,来比较新建的个体是否其同龄。

class Person
{
    int age;
    Person(int age)
    {
        this.age=age;
    }

    Person p = new Person(10);//创建一个基准个体,以此为对象与其他新建对象进行比较。

    public void compare()//以后不用给其传递参数
    {
        System.out.println(this.age==p.age);
    }
}

class Demo
{
    public static void main(String[] args)
    {
        Person p = new Person(10);
        p.compare();
    }
}//这样为什么可以编译通过,但是执行的时候,却有错?

当把Person类修改下则可以运行:
class Person
{
    int age;
    Person(int age)
    {
        this.age=age;
    }

    public void compare()
    {
        Person p = new Person(10);//将对象创建放在函数内部。
        System.out.println(this.age==p.age);
    }
}// 但这样做,相当于每次调用compre时候都创建了一个对象P,违背了需求,设定一个基准P,也就是说,想每次创建的对象都与同一个P进行比较。

17 个回复

倒序浏览

这个是把创建对象放在Person类中,且在compare函数外部时,编译没问题。
运行结果却如下:


求高手解!
回复 使用道具 举报


将创建对象放在compare函数内部时,运行没有问题!图片如下。
回复 使用道具 举报
回复 使用道具 举报
本帖最后由 fantacyleo 于 2014-7-9 01:52 编辑
hejinzhong 发表于 2014-7-9 01:36
这个是把创建对象放在Person类中,且在compare函数外部时,编译没问题。
运行结果却如下:

你这个错误是栈溢出,原因是构造方法里出现了死循环。成员变量的初始化是在构造函数内部执行的。你的构造方法在执行时是这样的:
  1. Person(int age) {
  2.     super();
  3.     Person p = new Person(10);
  4.     this.age = age;
  5. }
复制代码


当你在构造方法里new Person时,就会又一次调用构造方法,造成死循环。你要实现基准P的需求,可以把基准Person声明为静态,然后在静态初始化代码块中对它进行初始化:
  1. static {
  2.     p = new Person(10);
  3. }
  4. static Person p;
复制代码


静态初始化块是在构造函数以外执行的,不会出现死循环
回复 使用道具 举报
fantacyleo 发表于 2014-7-9 01:51
你这个错误是栈溢出,原因是构造方法里出现了死循环。成员变量的初始化是在构造函数内部执行的。你的构造 ...

栈溢出是什么意思啊?
看来这个问题跟THIS引用没有关系啊:lol
另外直接用一个INT类型的10来做基准不是更加简单嘛,不用搞那么复杂吧?
回复 使用道具 举报
215041631 发表于 2014-7-9 02:09
栈溢出是什么意思啊?
看来这个问题跟THIS引用没有关系啊
另外直接用一个INT类型的10来做基准不是更 ...

函数调用要占用内存中的栈空间,调用一次栈空间就要扩大一次,直到函数返回,之前开辟的空间才会被回收。栈空间大小是有上限的,如果函数调用出现死循环,那就会不停开辟新的栈空间而没有返回,最后到了上限,程序就挂掉了。
回复 使用道具 举报
原来如此,高手!开始没视频后面,刚看了static关键字后,明白了道理。super貌似不熟悉,继续学习
回复 使用道具 举报
215041631 发表于 2014-7-9 02:09
栈溢出是什么意思啊?
看来这个问题跟THIS引用没有关系啊
另外直接用一个INT类型的10来做基准不是更 ...

基准年龄可能变化。而且用10来比较的,就变成了判断一个人是否是10岁了。
回复 使用道具 举报
fantacyleo 发表于 2014-7-9 01:51
你这个错误是栈溢出,原因是构造方法里出现了死循环。成员变量的初始化是在构造函数内部执行的。你的构造 ...

嗯,静态代码是在加载类的时候就加载进方法区的。那么这里建立在静态中建立的这个对象是在那里存呢?也是在方法区?还是在栈中建立变量指向了方法区中?还是栈中建立变量指向堆中?
回复 使用道具 举报
hejinzhong 发表于 2014-7-9 02:31
嗯,静态代码是在加载类的时候就加载进方法区的。那么这里建立在静态中建立的这个对象是在那里存呢?也是 ...

按栈溢出来说,应该是在栈中建立新对象变量名指向堆中的对象实体参数。
回复 使用道具 举报
总结的不错,对大家应该很有帮助
回复 使用道具 举报
顶一下!
回复 使用道具 举报
fantacyleo 发表于 2014-7-9 02:13
函数调用要占用内存中的栈空间,调用一次栈空间就要扩大一次,直到函数返回,之前开辟的空间才会被回收。 ...

哦哦 通俗点说就是方法中出现死循环了?是这个意思吗
回复 使用道具 举报
hejinzhong 发表于 2014-7-9 02:27
基准年龄可能变化。而且用10来比较的,就变成了判断一个人是否是10岁了。 ...

基准年龄变化修改INT值不行吗?我感觉没想清楚,你这个程序不也是比较他是否是10岁吗
回复 使用道具 举报
hejinzhong 发表于 2014-7-9 02:31
嗯,静态代码是在加载类的时候就加载进方法区的。那么这里建立在静态中建立的这个对象是在那里存呢?也是 ...

静态变量在方法区。肯定不可能在栈中,否则方法调用一结束,静态变量就没了,基准P就被垃圾回收了。
回复 使用道具 举报
215041631 发表于 2014-7-9 09:02
哦哦 通俗点说就是方法中出现死循环了?是这个意思吗

。。。我一开始说的就是死循环:L 不过也不是所有死循环都会栈溢出,必须是调用函数的死循环。比如
while(true);
也是死循环但不会栈溢出
回复 使用道具 举报
fantacyleo 发表于 2014-7-9 10:41
。。。我一开始说的就是死循环 不过也不是所有死循环都会栈溢出,必须是调用函数的死循环。比如
while( ...

哈哈 ,多谢大神指教,了解了。
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马