[#382] | project: compiler | priority: low | category: bug | |
---|---|---|---|---|
submitter | assigned to | status | date submitted | |
Michel | Martin | fixed | 2004-12-03 16:03:00.0 | |
subject | "null" considered as a valid prefix | |||
code |
trait C { type T; class D { var f: T = _; } } object Main { def main(args: Array[String]) = { val c: C = null; System.out.println((new c.D).f); } } |
|||
what happened | No compilation (or execution) error. |
|||
what expected | An error at compile time. It should not be legal to create an instance of C.D before having created an instance of (some concrete subclass) of C , yet this is precisely what I do here. This enables me to create a field of type T without defining T first. |
|||
[back to overview] |
Martin edited on 2004-12-03 17:36:07.0 |
I fail to see how this can be detected at compile time. This is clearly a run-time violation. How does Java behave in situations like that? |
Michel edited on 2004-12-06 10:27:00.0 |
Hm, indeed that's pretty hard to detect at compile time. Sorry for that.
Anyway, Java handles that in a pretty strange fashion. It does a NPE as soon as one tries to create an inner class with class C { void h() { System.out.println("C.h"); } public class D { void f() { System.out.println("C.D.f"); } void g() { h(); } } } class Main { public static void main(String[] args) { C c = null; C.D d = c.new D(); d.f(); d.g(); } }
And here is the relevant excerpt from the disassembly of class public static void main(java.lang.String[]); Code: 0:aconst_null 1:astore_1 2:new#2; //class C$D 5:dup 6:aload_1 7:dup 8:invokevirtual#3; //Method java/lang/Object.getClass:()Ljava/lang/Class; 11:pop 12:invokespecial#4; //Method C$D."<init>":(LC;)V 15:astore_2 |
Martin edited on 2006-03-30 18:38:46.0 |
You now get an error at run time:
Exception in thread "main" java.lang.NullPointerException
at C$D. |