这个问题没有必要纠结,因为这与虚拟机实现方式有关系,不同虚拟机可能不一样。关键是对于使用java语言程序员而言,无论结论如何,都毫无影响。

解决方案 »

  1.   

    Car c = null 先占位也是可以的。
      

  2.   

    个人觉着 看虚拟机了,而且如过=null的话 一定是变量先进了
      

  3.   

    建底:作为新手的你不必要去纠结这个!因为很累!低层东西太多了!但是你既然问了我们就会回答!
    Car c = new Car();
    Car c术语:字面量!
    new Car();术语:匿名对象,返回的是一引用地址!
    根据JAVA分编译期.运行期原理(编译期.运行期请另行百度.)
    一个CLASS文件执行会在编译期先编译;然后把CLASS文件的内容分别放到方法区跟栈!
    也就是说字面量在编译期就已经有了! new String("a")是在运行期才有的!所以字面量C先进栈!
    下面一个例子说明以上论据:
    String a = "a"+1;
    String b = new String("a")+1;
    String c = "a"+1;
    System.out.println(a==b);//输入结果为FALSE,B因为在编译期无法确所以为FALSE;
    System.out.println(a==c);//输入结果为TRUE,a和C在编译期已经确定所以为TRUE
      

  4.   

    楼上 好像 说的不对好像是和虚拟机无关的吧应该是和 Javac 有关的。不管哪种虚拟机实现,都必须保证字节码的兼容。如果 字节码 是先 new 再 store ,虚拟机是不会先store 再 new的。public class java{    public static void main(){
    Integer i = new Integer(90);
    int c = 9+8;
            i.toString();
        }
    }Compiled from "java.java"
    public class java {
      public java();
        Code:
           0: aload_0                  // 为什么没有 new呢? 下面 你就知道 new 在哪里了!
           1: invokespecial #1                  // Method java/lang/Object."<init>":()V
           4: return        
        LineNumberTable:
          line 1: 0  public static void main();
        Code:
           0: new           #2                  // class java/lang/Integer   这个时候应该是分配对象的空间
           3: dup           
           4: bipush        90
           6: invokespecial #3                  // Method java/lang/Integer."<init>":(I)V   用90做参数 但只是<Init>  这么说来 new 其实是分两步的
           9: astore_0                                // 这个时候才保存到变量中
          10: bipush        17
          12: istore_1      
          13: aload_0       
          14: invokevirtual #4                  // Method java/lang/Integer.toString:()Ljava/lang/String;
          17: pop           
          18: return        
        LineNumberTable:
          line 4: 0
          line 5: 10
          line 6: 13
          line 7: 18
    }其实可以  java j = new java(); 看看到底他是怎么调用Object的init的
    public class java{    public static void main(){ int c ;
    int b = 9;
    System.out.println(b);
    c = 0;
    java j = new java();
        }}Compiled from "java.java"
    public class java {
      public java();
        Code:
           0: aload_0       
           1: invokespecial #1                  // Method java/lang/Object."<init>":()V
           4: return        
        LineNumberTable:
          line 1: 0  public static void main();
        Code:
           0: bipush        9
           2: istore_1      
           3: getstatic     #2                  // Field java/lang/System.out:Ljava/io/PrintStream;
           6: iload_1       
           7: invokevirtual #3                  // Method java/io/PrintStream.println:(I)V
          10: iconst_0      
          11: istore_0      
          12: new           #4                  // class java
          15: dup           
          16: invokespecial #5                  // Method "<init>":()V
          19: astore_2      
          20: return        
        LineNumberTable:
          line 6: 0
          line 7: 3
          line 8: 10
          line 9: 12
          line 10: 20
    }楼上 好像 说的不对好像是和虚拟机无关的吧应该是和 Javac 有关的。不管哪种虚拟机实现,都必须保证字节码的兼容。如果 字节码 是先 new 再 store ,虚拟机是不会先store 再 new的。public class java{    public static void main(){
    Integer i = new Integer(90);
    int c = 9+8;
            i.toString();
        }
    }Compiled from "java.java"
    public class java {
      public java();
        Code:
           0: aload_0                  // 为什么没有 new呢? 下面 你就知道 new 在哪里了!
           1: invokespecial #1                  // Method java/lang/Object."<init>":()V
           4: return        
        LineNumberTable:
          line 1: 0  public static void main();
        Code:
           0: new           #2                  // class java/lang/Integer   这个时候应该是分配对象的空间
           3: dup           
           4: bipush        90
           6: invokespecial #3                  // Method java/lang/Integer."<init>":(I)V   用90做参数 但只是<Init>  这么说来 new 其实是分两步的
           9: astore_0                                // 这个时候才保存到变量中
          10: bipush        17
          12: istore_1      
          13: aload_0       
          14: invokevirtual #4                  // Method java/lang/Integer.toString:()Ljava/lang/String;
          17: pop           
          18: return        
        LineNumberTable:
          line 4: 0
          line 5: 10
          line 6: 13
          line 7: 18
    }其实可以  java j = new java(); 看看到底他是怎么调用Object的init的
    public class java{    public static void main(){ int c ;
    int b = 9;
    System.out.println(b);
    c = 0;
    java j = new java();
        }}Compiled from "java.java"
    public class java {
      public java();
        Code:
           0: aload_0       
           1: invokespecial #1                  // Method java/lang/Object."<init>":()V
           4: return        
        LineNumberTable:
          line 1: 0  public static void main();
        Code:
           0: bipush        9
           2: istore_1      
           3: getstatic     #2                  // Field java/lang/System.out:Ljava/io/PrintStream;
           6: iload_1       
           7: invokevirtual #3                  // Method java/io/PrintStream.println:(I)V
          10: iconst_0      
          11: istore_0      
          12: new           #4                  // class java
          15: dup           
          16: invokespecial #5                  // Method "<init>":()V
          19: astore_2      
          20: return        
        LineNumberTable:
          line 6: 0
          line 7: 3
          line 8: 10
          line 9: 12
          line 10: 20
    }楼上 好像 说的不对好像是和虚拟机无关的吧应该是和 Javac 有关的。不管哪种虚拟机实现,都必须保证字节码的兼容。如果 字节码 是先 new 再 store ,虚拟机是不会先store 再 new的。public class java{    public static void main(){
    Integer i = new Integer(90);
    int c = 9+8;
            i.toString();
        }
    }Compiled from "java.java"
    public class java {
      public java();
        Code:
           0: aload_0                  // 为什么没有 new呢? 下面 你就知道 new 在哪里了!
           1: invokespecial #1                  // Method java/lang/Object."<init>":()V
           4: return        
        LineNumberTable:
          line 1: 0  public static void main();
        Code:
           0: new           #2                  // class java/lang/Integer   这个时候应该是分配对象的空间
           3: dup           
           4: bipush        90
           6: invokespecial #3                  // Method java/lang/Integer."<init>":(I)V   用90做参数 但只是<Init>  这么说来 new 其实是分两步的
           9: astore_0                                // 这个时候才保存到变量中
          10: bipush        17
          12: istore_1      
          13: aload_0       
          14: invokevirtual #4                  // Method java/lang/Integer.toString:()Ljava/lang/String;
          17: pop           
          18: return        
        LineNumberTable:
          line 4: 0
          line 5: 10
          line 6: 13
          line 7: 18
    }其实可以  java j = new java(); 看看到底他是怎么调用Object的init的
    public class java{    public static void main(){ int c ;
    int b = 9;
    System.out.println(b);
    c = 0;
    java j = new java();
        }}Compiled from "java.java"
    public class java {
      public java();
        Code:
           0: aload_0       
           1: invokespecial #1                  // Method java/lang/Object."<init>":()V
           4: return        
        LineNumberTable:
          line 1: 0  public static void main();
        Code:
           0: bipush        9
           2: istore_1      
           3: getstatic     #2                  // Field java/lang/System.out:Ljava/io/PrintStream;
           6: iload_1       
           7: invokevirtual #3                  // Method java/io/PrintStream.println:(I)V
          10: iconst_0      
          11: istore_0      
          12: new           #4                  // class java
          15: dup           
          16: invokespecial #5                  // Method "<init>":()V
          19: astore_2      
          20: return        
        LineNumberTable:
          line 6: 0
          line 7: 3
          line 8: 10
          line 9: 12
          line 10: 20
    }
      

  5.   

    Car c = new Car(); 
    从运算符优先级和同级时的先后顺序来说,先有c,然后再指向new Car() 后来创建的内存地址。
    不过我还是同意1楼说的,没必要纠结这个问题。
    现在用的大多数都是sun的jdk,如果换之前BEA公司的jrockit 或者换IBM的J9(jrockit和j9分别是BEA公司为WebLogic和IBM公司为产品WebSphere用的jdk) ,可能得到的是另外的答案了。
    这个涉及java虚拟机的实现和java虚拟机规范,劝楼主不要纠结这个问题了,没有太大的意义。
      

  6.   

    当然是先分配堆,再设置栈变量的值为堆的地址。楼上洋洋洒洒一大堆opcode,却本末倒置,得出错误结论:“应该是和 Javac 有关的”——言下之意,换个javac,就有可能先栈后堆?(否则如果换了N种,顺序还不变,怎么叫“和Javac有关”?)堆中的好比是一座火车站,栈里面的好比是一块指路牌。一座正常运行的城市,怎么可能先建立指路牌再造火车站?
      

  7.   

    你这句话"当然是先分配堆,再设置栈变量的值为堆的地址。"并没有错,不知道是否我理解有误,我觉得楼主问的是栈变量(或者叫字面量)C先存在还是堆对象先存在,楼主的意思是先new对象然后再创建创建字面量C,把引用地址存入创建字面量C
    我认为先创建字面量C,然后new出对象,然后再把把引用地址给字面量C!我也用你的例子来说明:
    堆中的好比是一座火车站,栈里面的好比是一副设计图纸。我(指代虚拟机)看到设计图上有一个车站标识!我去创建一个车站对象!然后再把车站的地址写在设计图车站标识里!
      

  8.   

    回复楼上我一共说了四句话 : “应该是和 Javac 有关的”   是第二句后面还有两句:“不管哪种虚拟机实现,都必须保证字节码的兼容。如果 字节码 是先 new 再 store ,虚拟机是不会先store 再 new的。”字节码是虚拟机产生的吗?
      

  9.   


    你说的全是废话。javac还是根据JLS来的呢。大家现在讨论的是,为什么javac会这么编译。你还在说javac这样编译,java自然照着javac编译的结果运行。有什么意义?
      

  10.   

    回复楼上 恕我眼拙我找了半天也没有找到你所说的“大家现在讨论的是 ,为什么javac会这么编译”
      

  11.   

    太抠细节了吧反正只要知道 
    c在栈里面
    new Car()在堆里面
    c指向它
    就够了.
      

  12.   

    你这个问题问得有问题。。
    你所谓的进内存指的是那块内存被申请了可以使用,还是那块内存上存有了有效数据?我简单说下运行过程吧。。
    首先这个c楼主的意思应该是某个方法内的局部变量,那么当这个方法被调用时,会在栈内存区新建一个Frame(具体是什么请看JVM规范,反正不是窗体那个Frame),它包括局部变量区和操作符栈(operators stack),所以理论上当一个方法被调用时,他的局部变量就已经存在了。然后运行到c = new Car()这里,首先是在堆内存上申请一块内存,申请完成后会把内存地址push到Frame里的操作符栈上,然后调用Car的构造函数,然后才是将在操作符栈上的地址保存到局部变量里。
    所以如果你的意思是哪个内存先被申请,那答案是c所使用的局部变量内存。
    如果你的意思是哪个先存入了有效数据,那答案是对象所在的堆内存。上面的运行过程其实还有很多细节,比如编译期如何决定局部变量数量,操作符栈大小,如何创建的Frame,如何传递的参数,以及创建对象new dup invoke astore的过程,如果感兴趣,简单的介绍JVM规范里写得很清楚,具体的过程那就只能直接看源码了。。
      

  13.   

    才看到是“刚学”。。话说你不好好写代码积累经验,纠结这些有何用?要说是与实际开发有关系的还说得过去,这种东西你懂了没一点用途。。
    如果你真是感兴趣喜欢钻研,那为何不去看JVM规范等权威文献,权威的你不静下心来去钻研,跑到这里问别人,别人要么是道听途说毫无根据的胡乱猜测,要么也只能去翻翻JVM规范查证,查到了还不一定讲得清,你想真正了解还是要亲自去看一遍权威文献原文,不然就纯粹问个热闹,过一阵子就全忘光了,再过一阵可能你问的什么问题都不记得了。
      

  14.   

    java虚拟机规范没定义这个东西。自己写个虚拟机 怎么搞都行
      

  15.   

    分析1:
    我从理论上来分析一下,java运算都是从右到左进行的。
    如:String a="1"+"1";正确
    String a="";
    "1"+"1"=a;错误
    如此从理论上来说,应该是第二种。
    分析2:
    String a;
    a=new String("1"+"1");
    这种不用解释,根据代码执行顺序,a肯定先被创建。
    实际上应该是你说的那种,但是没有测试过,待考证。
      

  16.   

    去查结合性表,等号是右结合的
    其实很好理解:Car c = new Car();  //别管这行
    c = new Car();  //如果构造函数异常,c难道会清空吗= =