• 清华大学计算机系大二 java 小学期考试题(摘自知乎)


     1 public class Main {
     2     public void test(Object o) {
     3         System.out.println("Object");
     4     }
     5     public void test(String s) {
     6         System.out.println("String");
     7     }
     8     public static void main(String[] args) {
     9         Main that = new Main();
    10         that.test(null);
    11     }
    12 }

    请写出运行输出

    String

    这个考的是Java的method overload resolution。根据Java语言规范的规定:
    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);
     

    1. 以下程序运行时是否会抛出异常, 以及程序输出.

    1 public class a {
    2     static String s0, s1;
    3     public static void main(String args[]) {
    4         s0 = s0 + s1;
    5         System.out.println(s0);
    6     }
    7 }
    这个考察的是静态变量的默认初始化,以及String的连接(+)。
     
    静态变量会在类加载过程中的linking阶段得到默认初始化。引用类型的静态变量会被默认初始化为null。
     
    然后是String对象的连接。根据Java语言规范:
    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"。)

    2.写出 `WindowAdapter.windowClosing, ActionListener.actionPerformed` 方法的参数类型.

    3.下列程序的输出:

    1 // ...
    2 public static void main(String args[]) {
    3         String a = "abc";
    4         String b = "ab" + "c";
    5         System.out.println(a == b);
    6 // ...
    7 }
     
    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语言规范:
    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:
    Constant expressions of type String are always "interned" so as to share unique instances, using the method String.intern.
    以及:
    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的文档:
    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。
    作者:RednaxelaFX
    链接:https://www.zhihu.com/question/50111592/answer/119694222
    来源:知乎
     
     
     
     
    附语,不会查询API,好像查了也得靠有道来看。。呜呜~加油~要看懂!!
    贵有恒何必三更眠五更起,最无益只怕一日曝十日寒。
  • 相关阅读:
    浏览器为何禁止跨域(同源策略)
    viewPager
    How to remove focus without setting focus to another control?
    android ANR
    解决Ubuntu系统中文乱码显示问题
    USB 3.0规范中译本 第6章 物理层
    库&框架-----CDN网络引用总结
    18_如何排错
    17_今日回顾
    16_sql注入的原理及处理
  • 原文地址:https://www.cnblogs.com/carazk/p/5853373.html
Copyright © 2020-2023  润新知