1

How does the java accessibility (or perhaps, scope) work with respect to type import multi-level nested classes? An example:

ClassA.java:

package com.oracle.javatests;

public class ClassA {

    public static class NestedAA {
        public void printSomething() {
            System.out.println("inside " + this.getClass().getName());
        }
        
        public static class NestedAB{
            public void printSomethingAB() {
                System.out.println("inside " + this.getClass().getName());  
            }
        }
    }
    
    public void printSomething() {
        System.out.println("inside " + this.getClass().getName());
    }
}

Main.java

package com.oracle.javatests;

import com.oracle.javatests.ClassA.*;
// import com.oracle.javatests.ClassA.NestedAA.*; // Adding this will resolve NestedAB

public class Main {

    public static void main (String[] args){
        ClassA objA = new ClassA();
        objA.printSomething();
        
        NestedAA nestedAA = new NestedAA(); // Ok
        NestedAB nestedAB = new NestedAB(); // Compiler error- NestedAB cannot be resolved to a type
    }
}

The import statement does not import NestedAB type when using wildcards. A perhaps similar question led me to the java spec sheet which clarifies Type-Import-on-Demand Declarations :

A type-import-on-demand declaration allows all accessible types of a named package or type to be imported as needed.

The accepted answer to the question implies that the on demand import declarations are not recursive. The reasoning is perhaps what Java considers "all accessible types of a named type", and the general concept of packages but I am falling short of connecting the dots and understand what accessible types means with respect to nested classes.

Can please anyone help explain how the type import and accessibility seem to work in java (while ignoring the arguable use of wildcard imports)

viacea
  • 25
  • 7
  • If you want to access an innerclass, you need to be able to access both the outer and the inner class. – dan1st May 25 '21 at 19:36
  • Ok, but why the import wildcard statement is not able to the same? – viacea May 25 '21 at 19:51
  • 1
    The classes need to be accessible to the class with the import statement, but that's not the issue here since the class and inner classes are public. The issue is that import is non-recursive. So you either need to import ClassA.NestedAA.NestedAB or you need to specify new NestedAA.NestedAB(). – Neil Coffey May 25 '21 at 19:51
  • P.S. It's incredibly rare to import (or even use) a class nested more than 1 level deep within an outer class, though. – Neil Coffey May 25 '21 at 19:52
  • Thank you. I wanted to understand whether import is non-recursive by design because that is not explicitly mentioned in any doc i could find. Or, is it limited by java's scope or package 'safety' or something else. I agree, inner classes are incredibly rare, and definitely not intentionally designed. In our use case, this came up as a result of parsing a very large xsd with each new type being parsed as an inner class resulting in greater than 10 levels of nesting in some cases. – viacea May 25 '21 at 20:03

1 Answers1

0

It's not heard to understand. import static com.foo.bar.*; is the exact same thing as import static com.foo.bar.[everything you can imagine here but without dots].

In other words, in your example, with import static pkg.ClassA.*; you can just write NestedAA without qualifiers and that works, because import static pkg.ClassA.NestedAA; would have made that work just the same.

You cannot write NestedAB unqualified and expect that to work; there is nothing you could possibly write instead of a * (which doesn't include dots) that would make that work, therefore, a star import doesn't make it work either.

rzwitserloot
  • 85,357
  • 5
  • 51
  • 72
  • Thank you. It's clear java is not accepting this... i wanted to understand why. – viacea May 25 '21 at 20:04
  • How do you do "everything you can imagine here but WITH dots"? – user433342 Mar 24 '23 at 01:18
  • @user433342 As in, `import static com.foo.bar.abc.def;` is different (wouldn't be covered by `import static com.foo.bar.*;` - because `abc.def` itself contains a dot. – rzwitserloot Mar 24 '23 at 11:51
  • @rzwitserloot exactly, is there some way to do that? `superimport com.foo.bar.*`? lol – user433342 Mar 24 '23 at 13:17
  • There is no way to import in a way that includes all 'subpackages', because 'subpackages' isn't actually a thing java supports. As per java rules, there is __no relationship whatsoever__ between package `java.lang` and `java.lang.ref`. One is not 'a subpackage of the other', there is no such thing as a 'subpackage'. Hence, there is no semantic way to explain what `superimport java.*;` should mean. You'd think "imports everything in the java package and all subpackages of that package", but as a sentence you might intuit what that means, but the java lang spec says that is gobbledygook. – rzwitserloot Mar 24 '23 at 15:53