Сопоставление Java generics Class с Parser

У меня есть класс, который анализирует поток данных. Каждый фрагмент данных называется Box. Существует много различных видов Boxэс. Я хочу иметь разные Parserдля каждого типа коробки. Так что в основном мне нужен Registryили что-то вроде того, который позволит мне выбрать правильный синтаксический анализатор для каждого Box. Вот упрощенная версия моей проблемы:

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;


public class GenericsTest {
    class Box {
        private String data;

        public String getData() {
            return data;
        }
    }

    class BoxA extends Box {
        private String adata;

        BoxA( String adata ) {
            this.adata = adata;
        }

        public String getAData() {
            return adata;
        }
    }

    class BoxB extends Box {
        private String bdata;

        BoxB( String bdata ) {
            this.bdata = bdata;
        }

        public String getBData() {
            return bdata;
        }
    }

    interface Parser<T> {
        public void parse( T box );
    }

    class ParserA implements Parser<BoxA> {
        @Override
        public void parse( BoxA box ) {
            System.out.print( "BoxA: " + box.getAData() );
        }
    }

    class ParserB implements Parser<BoxB> {
        @Override
        public void parse( BoxB box ) {
            System.out.print( "BoxB: " + box.getBData() );
        }
    }

    class Registry {
        Map<Class<?>, Parser<?>> unsafeMap = new HashMap<>();

        <T extends Box, S extends Parser<T>> void add( Class<T> clazz, S parser ) {
            unsafeMap.put( clazz, parser );
        }

        <T extends Box> boolean containsKey( Class<T> clazz ) {
            return unsafeMap.containsKey( clazz );
        }

        @SuppressWarnings( "unchecked" )
        <T extends Box, S extends Parser<T>> S get( Class<T> clazz ) {
            return (S) unsafeMap.get( clazz );
        }
    }

    public void runTest() {
        Registry registry = new Registry();
        registry.add( BoxA.class, new ParserA() );
        registry.add( BoxB.class, new ParserB() );

        List<Box> boxes = new ArrayList<>();
        boxes.add( new BoxA( "Silly" ) );
        boxes.add( new BoxB( "Funny" ) );
        boxes.add( new BoxB( "Foo" ) );
        boxes.add( new BoxA( "Bar" ) );

        for ( Box box : boxes ) {
            Class<? extends Box> clazz = box.getClass();
            registry.get( clazz ).parse( clazz.cast( box ) );
        }
    }

    public static void main( String[] args ) {
        new GenericsTest().runTest();
    }
}

Если вы возьмете этот код и попытаетесь его скомпилировать, вы увидите эту ошибку:

The method parse(capture#4-of ? extends GenericsTest.Box) in the type GenericsTest.Parser is not applicable for the arguments (capture#5-of ? extends GenericsTest.Box)

Итак, вопрос в том, как

(capture#4-of ? extends GenericsTest.Box)

отличается от

(capture#5-of ? extends GenericsTest.Box)

?

И есть ли лучший способ, чем мой Registryподход, который не требует использования @SuppressWarnings( "unchecked" )?

5
задан Lucas 15 July 2012 в 00:47
поделиться