黑马程序员技术交流社区

标题: 关于this关键字的应用问题? [打印本页]

作者: hejinzhong    时间: 2014-7-9 01:29
标题: 关于this关键字的应用问题?
在视频中,看了利用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进行比较。

作者: hejinzhong    时间: 2014-7-9 01:36
[attach]47652[/attach]
这个是把创建对象放在Person类中,且在compare函数外部时,编译没问题。
运行结果却如下:


求高手解!

作者: hejinzhong    时间: 2014-7-9 01:39
[attach]47654[/attach]

将创建对象放在compare函数内部时,运行没有问题!图片如下。

作者: hejinzhong    时间: 2014-7-9 01:42

作者: fantacyleo    时间: 2014-7-9 01:51
本帖最后由 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;
复制代码


静态初始化块是在构造函数以外执行的,不会出现死循环
作者: 215041631    时间: 2014-7-9 02:09
fantacyleo 发表于 2014-7-9 01:51
你这个错误是栈溢出,原因是构造方法里出现了死循环。成员变量的初始化是在构造函数内部执行的。你的构造 ...

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

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

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

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

按栈溢出来说,应该是在栈中建立新对象变量名指向堆中的对象实体参数。
作者: 曾倩倩    时间: 2014-7-9 08:50
总结的不错,对大家应该很有帮助
作者: ╰_〃无法释怀的    时间: 2014-7-9 08:54
顶一下!
作者: 215041631    时间: 2014-7-9 09:02
fantacyleo 发表于 2014-7-9 02:13
函数调用要占用内存中的栈空间,调用一次栈空间就要扩大一次,直到函数返回,之前开辟的空间才会被回收。 ...

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

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

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

。。。我一开始说的就是死循环:L 不过也不是所有死循环都会栈溢出,必须是调用函数的死循环。比如
while(true);
也是死循环但不会栈溢出
作者: 215041631    时间: 2014-7-9 23:06
fantacyleo 发表于 2014-7-9 10:41
。。。我一开始说的就是死循环 不过也不是所有死循环都会栈溢出,必须是调用函数的死循环。比如
while( ...

哈哈 ,多谢大神指教,了解了。




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