java 清华大学_如何评价清华大学计算机系大二 java 小学期考试题?

清华的Java考试题居然这么难 >_<

本回答讲解的3个例子都用Sun JDK 1.0.2编译运行测试过,亲测有效,附上截图。

至于有同学说谈及Java不指定版本都是耍流氓…你们赢了。现在指定版本了:下面的解释从Java 1.0开始所有版本都适用。

=======================================

public class Main {

public void test(Object o) {

System.out.println("Object");

}

public void test(String s) {

System.out.println("String");

}

public static void main(String[] args) {

Main that = new Main();

that.test(null);

}

}

评论区有同学说编译通不过的…您用的具体怎样的代码,哪个版本的编译器来编译的?

这个考的是Java的method overload resolution。根据Java语言规范的规定:

Chapter 15. Expressions

15.12.2.5. Choosing the Most Specific Method

If more than one member method is both accessible and applicable to a method invocation, it is necessary to choose one to provide the descriptor for the run-time method dispatch. The Java programming language uses the rule that the most specific method is chosen.

The informal intuition is that one method is more specific than another if any invocation handled by the first method could be passed on to the other one without a compile-time error.

这里的that.test(null)可以匹配上两个重载版本的test()方法,但是String版本比Object版本更具体,所以匹配上String版。

如果此处要强制选择Object版,则可以写:that.test((Object) null);

=======================================

public class a {

static String s0, s1;

public static void main(String args[]) {

s0 = s0 + s1;

System.out.println(s0);

}

}

这个考察的是静态变量的默认初始化,以及String的连接(+)。

静态变量会在类加载过程中的linking阶段得到默认初始化。引用类型的静态变量会被默认初始化为null。

然后是String对象的连接。根据Java语言规范:

Chapter 15. Expressions

15.18.1. String Concatenation Operator +

If only one operand expression is of type String, then string conversion (§5.1.11) is performed on the other operand to produce a string at run time.

The result of string concatenation is a reference to a String object that is the concatenation of the two operand strings. The characters of the left-hand operand precede the characters of the right-hand operand in the newly created string.

The String object is newly created (§12.5) unless the expression is a constant expression (§15.28).

然后对null的情况规范也做了规定:The operators on references to objects are:

...

The string concatenation operator + (§15.18.1), which, when given a String operand and a reference, will convert the reference to a String by invoking the toString method of the referenced object (using "null" if either the reference or the result of toString is a null reference), and then will produce a newly created String that is the concatenation of the two strings

(抱歉之前我写这个回答的时候看漏了这规范的这部分。对null的规定居然跟string concat运算符的规定没写在一起…)

如果考虑Sun JDK 1.0 - 1.4.2的实现的话,s0 = s0 + s1;是一个语法糖,会被解糖为:

s0 = new StringBuffer().append(s0).append(s1).toString();

考虑Oracle/Sun JDK 5、6、7、8的实现的话,则会被解糖为:

s0 = new StringBuilder().append(s0).append(s1).toString();

根据规范,此处调用的StringBuffer / StringBuilder.append(String)方法会对null做特殊处理,把它当作"null"字符串。相关实现:jdk8u/jdk8u/jdk: 3dc438e0c8e1 src/share/classes/java/lang/AbstractStringBuilder.java

所以最后答案是"nullnull"。

(注意:Oracle/Sun JDK 9改变了String +的实现,解除语法糖后不再是对StringBuilder的调用了。可以参考JEP 280: Indify String Concatenation。但用户代码能观察到的行为不变,结果仍然是"nullnull"。)

=======================================

public class Test {

public static void main(String args[]) {

String a = "abc";

String b = "ab" + "c";

System.out.println(a == b);

}

}

这个考察的是Java的编译时常量、编译时常量折叠,以及String interning的知识。

"abc"、"ab"、"c"在Java里都是String类型的编译时常量。当+运算符的左右两个操作数都是编译时常量时,这个+表达式也会被认为是编译时常量表达式。

再看Java语言规范:

Chapter 15. Expressions

15.28. Constant Expressions

A constant expression is an expression denoting a value of primitive type or a String that does not complete abruptly and is composed using only the following:

Literals of primitive type and literals of type String (§3.10.1, §3.10.2, §3.10.3,§3.10.4, §3.10.5)

The additive operators + and - (§15.18)

…Constant expressions of type String are always "interned" so as to share unique instances, using the method String.intern.以及:

Chapter 3. Lexical Structure

A string literal is a reference to an instance of class String (§4.3.1, §4.3.3).

Moreover, a string literal always refers to the same instance of class String. This is because string literals - or, more generally, strings that are the values of constant expressions (§15.28) - are "interned" so as to share unique instances, using the method String.intern.String.intern的文档:

String (Java Platform SE 8 )

public String intern()Returns a canonical representation for the string object.

A pool of strings, initially empty, is maintained privately by the class String.

When the intern method is invoked, if the pool already contains a string equal to this String object as determined by the equals(Object) method, then the string from the pool is returned. Otherwise, this String object is added to the pool and a reference to this String object is returned.

It follows that for any two strings s and t, s.intern() == t.intern() is true if and only if s.equals(t) is true.

All literal strings and string-valued constant expressions are interned. String literals are defined in section 3.10.5 of the The Java™ Language Specification.

Returns:a string that has the same contents as this string, but is guaranteed to be from a pool of unique strings.

换句话说,上述代码等价于:

// ...public static void main(String args[]) {

String a = "abc";

String b = "abc";

System.out.println(a == b);

// ...}

结果就显而易见了。内容相同的String类型编译时常量会被intern为同一个对象,所以a与b都引用了这个对象,要检查它们是否引用相等,自然得到true。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值