2015-11-04 18 views
8

Użycie Guava's ClassPath Próbuję zainicjować klasy znajdujące się w określonym pakiecie, ale chcę użyć konstruktora do zainicjowania, ponieważ nie propaguje wyjątków. Więc to, co wypracowałem dostać konstruktorów:Cykliczny błąd interfejsu podczas korzystania z orElseThrow

ClassPath.from(classLoader).getTopLevelClasses("test.package").stream() 
    .map(ClassPath.ClassInfo::load) 
    .map(Class::getConstructors) 
    .map(Arrays::stream) 
    .map(constructorStream -> constructorStream 
     .filter(constructor -> constructor.getParameterCount() == 0) 
     .findAny() 
     .orElseThrow(RuntimeException::new) 
    ); 

to jednak daje błąd w InteliJ po prostu stwierdzając cykliczne interfejs. Myślę, że wiem, co to jest interfejs cykliczny, ale nie jestem pewien, dlaczego spowodowałby ten błąd. O ile wiem, tak długo, jak znany jest typ zwracany (który dla orElseThrow ma wartość zwracaną w tym przypadku jako Constructor<?>), to wyrzucenie niesprawdzonego wyjątku powinno być w porządku. Jeśli użyję orElse(null), błąd zniknie. Co tu się dzieje i jak mogę rzucić wyjątek RuntimeException, który chcę rzucić?

+1

Co się stanie, jeśli przedrostek 'orElseThrow' zostanie podany w określonym typie? '. orElseThrow (RuntimeException :: new)' – RealSkeptic

+0

Błąd został usunięty i teraz działa zgodnie z przeznaczeniem. Dlaczego jednak? Czy "X" nie powinien już być zdefiniowany przez podany wyjątek? – danthonywalker

+1

Zgaduję, że korzystasz z kompilatora, który nie wykonuje bardzo ścisłego wnioskowania typu. W środowisku Eclipse działa bez jawnego argumentu typu. W 'javac' firmy Oracle skarży się na niezgłoszony wyjątek. – RealSkeptic

Odpowiedz

0

Wyjątek czasu wykonywania jest generowany z mapy lambda. Acual wyjątek może być obsługiwany wewnątrz api Stream.

Aby tego uniknąć, można użyć metody flatMap, aby zastąpić bieżący strumień połączonymi strumieniami dostarczonymi do metody flatMap. Jest to powszechnie stosowane przy łączeniu strumieni. Zobacz także: adam bien's example on flatmap.W tym przykładzie wyjątek nie musi przechodzić przez api strumieniowania - więc możesz również użyć sprawdzonych wyjątków i nie być ograniczonym przez podpis w interfejsie Stream, który nie ma klauzuli throws.

ClassPath.from(classloader).getTopLevelClasses("test.package").stream() 
      .map(ClassPath.ClassInfo::load) 
      .map(Class::getConstructors) 
      .flatMap(Arrays::stream) 
      .filter(constructor -> constructor.getParameterCount() == 0) 
        .findAny() 
        .orElseThrow(RuntimeException::new); 
Powiązane problemy