Let's give the two versions different names to make them a little easier to talk about:
object Foo1 {
class Bar1
}
object Foo2 {
object Bar2 {
class Baz2
}
}
Now if you look at the class files, you'll see that the Scala compiler has created a Foo1 class. When you run javap -v on Foo1$Bar1, you'll see that that class is listed as the enclosing class:
InnerClasses:
public static #14= #2 of #13; //Bar1=class Foo1$Bar1 of class Foo1
This is exactly what would happen with a static nested class in Java, so the Java compiler is perfectly happy to compile new Foo1.Bar1() for you.
Now look at the javap -v output for Foo2$Bar2$Baz2:
InnerClasses:
public static #16= #13 of #15; //Bar2$=class Foo2$Bar2$ of class Foo2
public static #17= #2 of #13; //Baz2=class Foo2$Bar2$Baz2 of class Foo2$Bar2$
Now the enclosing class is Foo2$Bar2$, not Foo2$Bar2 (in fact the Scala compiler doesn't even generate a Foo2$Bar2 unless you add a companion class for object Bar2). The Java compiler expects a static inner class Baz2 of a enclosing class Foo2$Bar2$ to be named Foo2$Bar2$$Baz2, with two dollar signs. This doesn't match what it's actually got (Foo2$Bar2$Baz2), so it says no to new Foo2.Bar2.Baz2().
Java is perfectly happy to accept dollar signs in class names, and in this case since it can't figure out how to interpret Foo2$Bar2$Baz2 as an inner class of some kind, it'll let you create an instance with new Foo2$Bar2$Baz2(). So that's a workaround, just not a very pretty one.
Why does the Scala compiler treat Foo1 and Bar2 differently (in the sense that Bar2 doesn't get a Bar2 class), and why does the enclosing class listed in the InnerClasses attribute for Baz2 have a dollar sign on the end, while the one for Bar1 doesn't? I don't really have any idea. But that's the difference—you just need a little more verbosity to see it with javap.