7

In the java example below, can anyone explain exactly why the output of the program is "Orange" ? (this is an interview question)

public class Finder {
  public static void main(String[] args){
    System.out.println(X.Y.Z);
  }
}

class X {
  static W Y = new W();
  static class Y {
    static String Z ="Apple";
  }
}

class W {
  String Z = "Orange";
}
Faraz
  • 383
  • 1
  • 6
  • class `W` is not static, nor is class `X`, **but** W was *declared* static which "over-wrote" the *inner* class inside `X` within the class `X` called `Y` which was declared static (look at `new` within the declaration inside class `X` which came before "attempted" declaration of class `Y`!). – t0mm13b Dec 25 '12 at 02:22
  • 3
    `X.Y` this expression points to the static variable `Y` defined in class `X`. `Y` variable in class `X` is object of type `W`, therefore, `X.Y.Z` must be `orange`. To get `Apple` you must use `new X.Y().Z` – Shivam Dec 25 '12 at 02:43
  • 3
    That's a nasty interview question. Note that `static W Y` violates the Java naming conventions for variables. (So do `static String Z` in class `Y` and `String Z` in class `W`.) @t0mm13b - the order of declarations has nothing to do with this case. – Ted Hopp Dec 25 '12 at 03:42
  • 2
    @TedHopp you've got me there, tbqh, was never asked that question before in an interview but from reading other's answers, it is a bloody nasty question to pose - in fairness, what was the interviewer's point? Picture yourself as an interviewer, knowing the pitfalls of that question - question is, would you pose that to a potential candidate? What does it have a bearing on the real world - you must be joking if that code was found in production? – t0mm13b Dec 25 '12 at 04:10
  • 2
    Also, I really do think the interviewer was *forgive* me, taking the p!ss, because who the hell would carry a java spec in their head prior to interview...clearly, it was easy for @fgb to google the spec straight away and post an answer which is enlightening - not knocking the answerer, in fairness that sums up one thing I can gather from the interviewer, he/she has lost a lot of potential candidates as a result of taking the p!ss out of someone with a question like that! – t0mm13b Dec 25 '12 at 04:29
  • 2
    Not even the compiler writers got these rules right: http://bugs.sun.com/bugdatabase/view_bug.do;jsessionid=dc3d7ac7e5c89ffffffffea41bef24e421b5?bug_id=6865517. I've never seen code like this, not even in examples of what not to do. – fgb Dec 25 '12 at 04:30
  • 1
    @fgb - I've never seen it in production code either, and I would not want to work with someone who wrote such garbage. However, I believe that some obfuscation tools use tricks like this. I don't recall seeing it used for a static field and a static nested class, but I have seen obfuscated code where a class and a package have the same name (e.g., a class `b` in package `a` and also a package `a.b`). This sends many (most?) decompilation tools off the tracks. If the job was to work on a decompilation tool or a JVM, then this _might_ be a justifiable interview question; otherwise...no way. – Ted Hopp Dec 25 '12 at 17:58

2 Answers2

10

The variable Y obscures the type Y. See the JLS:

6.4.2. Obscuring

A simple name may occur in contexts where it may potentially be interpreted as the name of a variable, a type, or a package. In these situations, the rules of §6.5 specify that a variable will be chosen in preference to a type, and that a type will be chosen in preference to a package. Thus, it is may sometimes be impossible to refer to a visible type or package declaration via its simple name. We say that such a declaration is obscured.

The qualified name X.Y.Z is resolved according to:

6.5.2. Reclassification of Contextually Ambiguous Names

...

If the name to the left of the "." is reclassified as a TypeName, then:

  • If the Identifier is the name of a method or field of the type denoted by TypeName, this AmbiguousName is reclassified as an ExpressionName.

  • Otherwise, if the Identifier is the name of a member type of the type denoted by TypeName, this AmbiguousName is reclassified as a TypeName.

  • Otherwise, a compile-time error occurs.

This is unlikely to occur in practice because of the normal naming conventions for types and variables.

Community
  • 1
  • 1
fgb
  • 18,439
  • 2
  • 38
  • 52
3

You're hiding the class Y with a static instance of W named Y. The class Y is still there and can be used. Try:

System.out.println(X.Y.Z);
System.out.println((new X.Y()).Z);

The output should be

Orange
Apple

Also see: Java Field Hiding

Community
  • 1
  • 1
Diego Basch
  • 12,764
  • 2
  • 29
  • 24
  • Aren't You trying to a access the static class Y in a non-static way by creating an object (new X.Y()).Z). Nothing technically wrong though – Jayamohan Dec 25 '12 at 02:46