見えなくても型はついている

private(package private、protectedでも可能)メンバクラスをそれよりも可視性の高いアクセス修飾子をもつメソッドの戻り値型や引数型にすると、使う側で「何だこの型は?」という不思議なメソッド*1になる。

簡単な実験で、スーパークラスやインターフェースなど、型階層もコンパイル時に使われることがわかる。
なので型付けには問題ない。

package test;

import java.util.HashMap;
import java.util.Map;

public class AccessibilityTest {
    public static void main(final String[] args) {
        // クラスは見えない
        // PrivateClass privateClass = PrivateHolder.getPrivateSomething();
        // スーパークラスで受けられる
        HashMap<String, Integer> map1 = PrivateHolder.getPrivateSomething();
        // インターフェースで受けられる
        Map<String, Integer> map = PrivateHolder.getPrivateSomething();
        
        // 他のメソッドに渡せる
        PrivateHolder.takePrivateSomething(PrivateHolder.getPrivateSomething());
    }
}

class PrivateHolder {

    // privateメンバクラス
    private static class PrivateClass extends HashMap<String, Integer> {
        public static PrivateClass getInstance() {
            return new PrivateClass();
        }
    }
    
    // publicメソッドがPrivateClassインスタンスを返す
    public static PrivateClass getPrivateSomething() {
        return PrivateClass.getInstance();
    }
    
    // PrivateClassを引数にとるpublicメソッド
    public static void takePrivateSomething(final PrivateClass arg) {
        System.out.println(arg);
    }
    
}

まあ普通は戻り値型や引数型をインターフェースにするところでしょうが。

*1:フィールドも同様