| [#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. |