在JAVA中为什么可以在一个类当中New自己类 例如: public class A{ A a = new A();//为什么可以new自己 }

如题所述

先问下,问什么不能new自己。
当然,假如按楼主的写法,当这个A第一次被调用的时候,就出抛异常,超出堆栈、内存溢出之类。

楼主,你需要理解“声明”和“实例化”的概念。

A a;
即是声明,创建了一个A类型的变量a
new A();
即是实例化,实实在在地在内存里为A()划分了一块内存空间

a=new A();即是使a指向new A()。以后只要你不更改a的引用,对a的任何操作都会影响到你分配出来的这块内存空间。

理解了这个再回到问题

public class A{}
这个是对类的一个定义,此时,A只是一个“概念”,在电脑里并没有实体存在,但是java的虚拟机(jvm)已经得知了该类的所有定义,就是说,该类被加载进jvm的类加载器(class loader)了,其他的类有可能访问到该A类。
此时A本身就是jvm中的一个类,它自己当然是和自己同包,对不对?
所以A必然可以访问到A
那么public class A{ A a=new A();}
这句话,编译期是正确的,不存在错误,所以可以声明也(被jvm认为)可以实例化。

但是到了运行期,真正的跑起来的时候,它是错误的
因为这是个迭代的死循环。
在new A()的时候,又会执行一遍A a= new A();
然后该new A()又执行一遍A a= new A();
如此往复,直到堆栈溢出。

当然 以下写法是正确的
public class A{
A a=null;
}
嗯,事实上,有些专门的写法,如单例,工厂类,就是需要在某个类里面实例化它本身。这个,楼主等你基础打好了,再研究吧。追问

那么假如 我这个类里面有一个方法同个这个方法new 当前类,会导致内存溢出么?
public calss A{
public int doX(){
A a = new A();
}
}

追答

不会的,你应该在脑子里自己模拟下运行顺序。
在doX()这个方法被调用前,new A()是不会运行的,对不对?

当然 你也可以这么写使之溢出:

public class A{
A(){
doX();//因为new A()会调用的构造方法A(),这里会被调用到。
}
public int doX(){
A a = new A();
return 0;//注意,有返回值的方法一定要return。不然就写void吧。
}
}

追问

在问你个问题 java中的 this.* 和*.this calss名.this 分别有什么不同

追答

this是指的当前实例,this.*即是指当前实例的属性或方法。
如:
public class A{
A a=null;
public void setA(A a){
this.a=a;
//这里出现了两个a对吧,this.a就是A类的属性a,而第二个a则是指传进来的参数,是个局部变量
}
}

类名.this就稍微复杂点。它本质上还是和this是等价的,但是当你有一个内部类的时候,this本身的含义是模糊的,所以要加上类名.this。如:
public class A{
class InnerA{
void print(){
System.out.println(this);//这里的this不是A.this,而是InnerA.this。如果你要在InnerA内部用A
//的方法,就必须使用A.this来指定,this是不行的
}
}
}

追问

最后问一个问题 实例化 到底实例了哪些东西?除了传入的构造函数的那些属性,为什么像A a = new A()这样也会在实例化过程中执行

追答

实例化是实例化了这个“类”

然后呢,实例化有不同的入口,这些入口即是构造函数。
所以,它会同时定义的(不是实例的)只有三种,1、构造函数;2、属性;3、静态语句块

举例
A a=new A();
即是调用无参构造函数A()

A a=new A(1);
即是调用一个参数的构造函数A(int i);

一个类
public class A{
int i=1;//属性,默认的i为1
{
i=0;//静态语句块使i=0,它只会在本类“实例化”的时候才会被调用,所以它只被调用一次
}
public A(){}
public A(int i){
//注意我这里没有写this.i=i;所以就算你写new A(10),i还是等于0,而非10
}
}

当你把A a = new A()写进A类定义的时候
这个a,其实就是A的一个属性了,new A()是它的初始化过程,当然会被执行。

温馨提示:答案为网友推荐,仅供参考
第1个回答  2012-01-06

一看你就才开始学习,这东西建议你买本这方面的书看看。

1、这牵涉到内存的问题

2、new 就是在内存中创建一个对象

3、在你要用这个对象的时候直接调用他里面飞属性和方法就可以了

package com.demo;

public class Person{

public Person(){

System.out.println("-->"+name);

System.out.println("-->"+age);

System.out.println("-->"+sex);

}

public Person(String name1,int age1,String sex1){

name = name1;

age = age1;

sex = sex1;

}

public String getName(){

return name;

}

public int getAge(){

return age;

}

public String getSex(){

return sex;

}

private String name="Tom";

private int age=23;

private String sex="male";

{//动态的代码块

System.out.println("动态的代码块内容");

System.out.println("==>"+name);

System.out.println("==>"+age);

System.out.println("==>"+sex);

}

}

class TestPerson{

public static void main(String args[]){

//创建具体的对象并且通过构造方法将属性值设置;

//Person p = new Person("Tom",23,"male");

Person p = new Person();

/*System.out.println(p.getName());

System.out.println(p.getAge());

System.out.println(p.getSex());

System.out.println(p);*/

}

}

第2个回答  2012-01-06
实例化一个对象属性,如果在一个学习团队中存在一带一的辅导,即一个优秀学生带一个差生,优秀学生本身是个Student对象,差生也是个Student对象,要在Student对象中显示他所带的学生时就要新建一个Student对象表示,这时就需要Student类中存在Student b=new Student();的语句了;或者如上说的单例中,将构造方法私有化后,就需要这个语句了
第3个回答  2012-01-06
递归调用追问

递归的过程中会一直调用 A a = new A();这个过程?还是不再调用了?

追答

会一直new。。。 这个不能这样 有this关键字 还有 构造函数 你不能直接这样new自己

第4个回答  2012-01-06
他们都说了,递归调用,我就不献丑了
相似回答