论坛首页 Java企业应用论坛

请别再拿“String s = new String("xyz");创建了多少个String实例”来面试了吧

浏览 100962 次
该帖已经被评为精华帖
作者 正文
   发表时间:2010-09-30  
zx339 写道
iq527 写道
allskylove 写道
简直是一派胡言,这样的帖子也能评为精华?无语了。。。。。, 对jvm 的了解很是无语,还长篇大论的。就下面问题抛给楼主:你知道什么事字面量吗? 什么是常量吗? 什么是基本数据类型?什么是对象数据类型,什么是过渡类型?


比较讨厌这种带有"挑衅"性质的回复,如果您知道, 那请您来给大家解释下吧... 


allskylove本来就是反对低调对待技术问题的人,他认为“互相攻击”才能带来实质的内容,你可以看看他大部分的回复,
都是"挑衅"性的。所以别动不动就讨厌这个人,那个人,难道批评就一定是为了显得自己NB? 批评就不能不带目的性?



我看了他的大部分回复都没有"挑衅"性,只提这些范范的问题而又不给出自己的间接难道不是为了显得自己NB?
0 请登录后投票
   发表时间:2010-09-30  
allskylove 写道
aria 写道
zx339 写道
iq527 写道
allskylove 写道
简直是一派胡言,这样的帖子也能评为精华?无语了。。。。。, 对jvm 的了解很是无语,还长篇大论的。就下面问题抛给楼主:你知道什么事字面量吗? 什么是常量吗? 什么是基本数据类型?什么是对象数据类型,什么是过渡类型?


比较讨厌这种带有"挑衅"性质的回复,如果您知道, 那请您来给大家解释下吧... 


allskylove本来就是反对低调对待技术问题的人,他认为“互相攻击”才能带来实质的内容,你可以看看他大部分的回复,
都是"挑衅"性的。所以别动不动就讨厌这个人,那个人,难道批评就一定是为了显得自己NB? 批评就不能不带目的性?



我看了他的大部分回复都没有"挑衅"性,只提这些范范的问题而又不给出自己的间接难道不是为了显得自己NB?

中国名族真是郁闷的名族,闷骚的名族,你闷骚得还有道理了,连点刺激都受不了,搞什么飞机,钓鱼岛,你继续强烈谴责吧!打他娘的!还说个毛!

不要激动呀 我是针对zx339 他发这贴时您还没贴出长篇大论呢
赠您几句话 不偏谓之中,不易谓之庸 
谣言止于智者,您要是因为想发泄而喷算我什么都没说
0 请登录后投票
   发表时间:2010-09-30  
其实面试官也许只是为了考下,java中常量字符串放在哪的问题
0 请登录后投票
   发表时间:2010-09-30  
讨论这种问题没有任何意义
0 请登录后投票
   发表时间:2010-09-30  
被你们搞晕了。
0 请登录后投票
   发表时间:2010-09-30  
allskylove 写道
orcl_zhang 写道
引用
在Java语言里,“new”表达式是负责创建实例的,其中会调用构造器去对实例做初始化;构造器自身的返回值类型是void,并不是“构造器返回了新创建的对象的引用”,而是new表达式的值是新创建的对象的引用。

虽然java学的不好,也忘的差不多了。至少看到这,还是懂了。。


构造器自身的返回值类型是void? 构造器自身返回的类型是它自己本身,不然怎么构造实例呢?返回都没有返回!

请先阅读Java虚拟机规范第二版的相关内容:
The Java Virtual Machine Specification, Second Edition 写道
2.12 Constructors

A constructor is used in the creation of an object that is an instance of a class. The constructor declaration looks like a method declaration that has no result type.

3.9 Specially Named Initialization Methods

At the level of the Java virtual machine, every constructor (§2.12) appears as an instance initialization method that has the special name <init>. This name is supplied by a compiler. Because the name <init> is not a valid identifier, it cannot be used directly in a program written in the Java programming language. Instance initialization methods may be invoked only within the Java virtual machine by the invokespecial instruction, and they may be invoked only on uninitialized class instances. An instance initialization method takes on the access permissions (§2.7.4) of the constructor from which it was derived.

4.3.3 Method Descriptors

A method descriptor represents the parameters that the method takes and the value that it returns:

MethodDescriptor:
     ( ParameterDescriptor* ) ReturnDescriptor


A parameter descriptor represents a parameter passed to a method:

ParameterDescriptor:
     FieldType


A return descriptor represents the type of the value returned from a method. It is a series of characters generated by the grammar:

ReturnDescriptor:
     FieldType
    V


The character V indicates that the method returns no value (its return type is void).

4.4.2 CONSTANT_Fieldref, CONSTANT_Methodref, and CONSTANT_InterfaceMethodref
   ...
       name_and_type_index

The value of the name_and_type_index item must be a valid index into the constant_pool table. The constant_pool entry at that index must be a CONSTANT_NameAndType_info (§4.4.6) structure. This constant_pool entry indicates the name and descriptor of the field or method.

If the name of the method of a CONSTANT_Methodref_info or CONSTANT_InterfaceMethodref_info begins with a '<' ('u003c'), then the name must be one of the special internal methods (§3.8), either <init> or <clinit>. In this case, the method must return no value.

4.9.4 Instance Initialization Methods and Newly Created Objects

Creating a new class instance is a multistep process. The Java statement

    ...

    new myClass(i, j, k);
    ...

can be implemented by the following:

    ...

    new     #1                   // Allocate uninitialized space for myClass
    dup                          // Duplicate object on the operand stack
    iload_1                      // Push i
    iload_2                      // Push j
    iload_3                      // Push k
    invokespecial myClass.<init> // Initialize object
    ...

This instruction sequence leaves the newly created and initialized object on top of the operand stack. (More examples of compiling Java code to the instruction set of the Java Virtual Machine are given in Chapter 7, "Compiling for the Java Virtual Machine.")
The instance initialization method <init> for class myClass sees the new uninitialized object as its this argument in local variable 0. It must either invoke an alternative instance initialization method for class myClass or invoke the initialization method of a superclass on the this object before it is allowed to do anything else with this.


Java语言里类的实例构造器,在Class文件和JVM里方法名是<init>,返回值类型是void,这是规范里规定的。
如果您不愿意阅读规范,可以用您已经知道的javap工具来看看下面的代码对应的Class文件的内容:
public class CtorDemo {
    public static void main(String[] args) {
        new Object();
    }
}

main()的内容是:
0:   new     #2; //class java/lang/Object
3:   dup
4:   invokespecial   #1; //Method java/lang/Object."<init>":()V
7:   pop
8:   return

调用Object的默认构造器时,可以看到调用的java.lang.Object上的<init>()V方法。
()V是该构造器对应的初始化方法的描述符,在前面引用的规范里有写,意思是接受0个参数,返回值类型是void,也就是不返回任何值。

如果您仍然不相信,那么请看看上面例子里CtorDemo的默认构造器的内容:
0:   aload_0
1:   invokespecial   #1; //Method java/lang/Object."<init>":()V
4:   return

会返回内容的返回指令是带有类型前缀的,例如返回int类型的值的方法使用ireturn,返回引用类型的值的方法是用areturn,而无前缀的return指令则不返回任何值,对应的返回值类型为void。

正是因为实例构造器不返回值,所以new指令后才通常会跟着dup,将新创建对象的引用复制一份,这样在操作数栈顶就有两份指向刚创建的对象的引用;其中一份传给实例构造器作为隐藏参数this,另一份做后续用途,例如赋值给变量或用于调用别的方法等。
1 请登录后投票
   发表时间:2010-09-30  
其实这些是比较底层的东西,理想下Java程序员是不需要懂的,但是面试的时候如果大家知道的都一样,就比不出来了,就出了个这个问题,也能反映出这个人爱学习。
其实涉及到底层,东西多了去了,如果java设计的不好些,不仅需要了解jvm,bytecode,甚至c++实现或者汇编也会涉及。例如之前很著名的字符串循环+会造成系统变慢的事,那是jvm自己的问题,别的语言有这个问题嘛?新版本也fix了。搞的别人不知道就是菜鸟一样。
0 请登录后投票
   发表时间:2010-09-30  
allskylove 写道
兄弟你方向搞错了,<init> 方法只是jvm内部调用的,并不是语言级别的,而是虚拟机调用的!真正到语言级别方法(构造器调用的时候) 返回的是类本身 ,比如 MyClassA a=new MyClassA(); 明显返回了类本身,才赋值给了变量a, 另外如果没有返回值,不管是方法还是构造器 都应该有些void ,由此看来, 构造器自身返回的类型是它自己本身.

确实有只能由JVM调用、而不能由用户代码显式调用的初始化方法,不过那个是<clinit>,对应于Java语言中类的静态初始化器。
The Java Virtual Machine, Second Edition 写道
3.9 Specially Named Initialization Methods

...

A class or interface has at most one class or interface initialization method and is initialized (§2.17.4) by invoking that method. The initialization method of a class or interface is static and takes no arguments. It has the special name <clinit>. This name is supplied by a compiler. Because the name <clinit> is not a valid identifier, it cannot be used directly in a program written in the Java programming language. Class and interface initialization methods are invoked implicitly by the Java virtual machine; they are never invoked directly from any Java virtual machine instruction, but are invoked only indirectly as part of the class initialization process.

如果您能读懂规范的话。
0 请登录后投票
   发表时间:2010-09-30  
k看这自卑!!原来我这么菜!
0 请登录后投票
   发表时间:2010-09-30  
不讨论这个正确与否,我觉得很容易让人晕啊;
[
在Java语言里,“new”表达式是负责创建实例的,其中会调用构造器去对实例做初始化;构造器自身的返回值类型是void,并不是“构造器返回了新创建的对象的引用”,而是new表达式的值是新创建的对象的引用。
]

1, 在构造函数的理解上,我支持 allskylove;
2, new String("xyz"),无论执行多少次,它也是要去创建对象的;
只是被JVM做了优化而已;

0 请登录后投票
论坛首页 Java企业应用版

跳转论坛:
Global site tag (gtag.js) - Google Analytics