Мне нужно получить список общих ленивых загрузчиков, которые будут создавать экземпляры своего предполагаемого типа - PullRequest
0 голосов
/ 11 апреля 2011

Извините за загадочный заголовок, но это трудно объяснить.Общее правило заключается в том, что мне нужен ленивый загрузчик, который даст мне N экземпляров типа с подстановочными знаками.Я называю ленивый загрузчик единицей хранения.

import java.util.ArrayList;
import java.util.List;

public class StorageUnit<T extends MyInterface> implements Storable<T> {

    private int count;

    public StorageUnit(int count) {
        this.count = count;
    }

    private List<T> storables = new ArrayList<T>();

    public List<T> getInstances(Class<T> c) {
        try {
            if (storables.size() == 0) {
                for (int i = 0; i < count; i++) {
                    storables.add(c.newInstance());
                }
            } else {
                return storables;
            }
        }catch (IllegalAccessException illegalAccessException) {
            illegalAccessException.printStackTrace();
        } catch (InstantiationException instantiationException) {
            instantiationException.printStackTrace();
        }

        return storables;
    }
}

В другом месте в моем приложении у меня есть другой класс, который имеет ссылку на несколько таких единиц хранения.Мне нужно получить экземпляры типа блока хранения, а затем я сделаю что-то с этим типом.

import java.util.ArrayList;
import java.util.List;

public class MyStorageUnitContainer {

    private List<StorageUnit<? extends MyInterface>> storageUnits;

    public MyStorageUnitContainer(List<StorageUnit<? extends MyInterface>> storageUnits) {
        this.storageUnits = storageUnits;
    }

    public List<StorageUnit<? extends MyInterface>> getInstances() {
        List<StorageUnit<? extends MyInterface>> instances = new ArrayList<StorageUnit<? extends MyInterface>>();
        for (StorageUnit<? extends MyInterface> storageUnit : storageUnits) {

            storageUnit.getInstances(/* I can't get the bound wildcard... */);
            // Now loop through those instances and do something with them...

        }
        return instances;
    }
}

Этот код отстой, поэтому лучшая аналогия, которую я могу придумать, - это фактический контейнер блока хранения.В этом контейнере единиц хранения есть несколько отдельных единиц хранения.Каждая из этих коробок содержит предметы определенного типа (например, бейсбольные карточки).Я знаю, что в коробке 100 бейсбольных карточек, но пока я не открою коробку, я ничего не знаю о деталях каждой бейсбольной карточки.Я в основном пытаюсь рассматривать каждую коробку как ленивый загрузчик.Открытие поля загружает N реализаций, если они еще не существуют.

Ответы [ 2 ]

1 голос
/ 24 мая 2011

Пауло верен, и (также согласно ответу Пауло) я часто просто передаю объект класса в конструктор, чтобы обойти эту проблему. Он позволяет методу getInstances() отображаться так, как вы хотите - т.е. без параметров. Внутри экземпляр хранит ссылку на общий класс, поэтому он может вызывать newInstance().

Этот код иллюстрирует это на вашем примере. Я проверил это, он выполняет ОК.

import java.util.ArrayList;
import java.util.List;

public class Sandbox
{
    static interface MyInterface
    {
    }

    static interface Storable<T>
    {
        List<T> getInstances();
    };

    static abstract class MyStorableImpl implements MyInterface
    {
        @Override
        public String toString()
        {
            return "I'm a " + getClass() + " with hashcode " + hashCode();
        }
    }

    static class MyStorable1 extends MyStorableImpl
    {
    }

    static class MyStorable2 extends MyStorableImpl
    {
    }

    static class StorageUnit<T extends MyInterface> implements Storable<T>
    {
        private final int count;

        private final Class<T> clazz;

        public StorageUnit(Class<T> clazz, int count)
        {
            this.count = count;
            this.clazz = clazz;
        }

        private List<T> storables = new ArrayList<T>();

        public List<T> getInstances()
        {
            try
            {
                if (storables.size() == 0)
                {
                    for (int i = 0; i < count; i++)
                    {
                        storables.add(clazz.newInstance());
                    }
                }
                else
                {
                    return storables;
                }
            }
            catch (IllegalAccessException illegalAccessException)
            {
                illegalAccessException.printStackTrace();
            }
            catch (InstantiationException instantiationException)
            {
                instantiationException.printStackTrace();
            }

            return storables;
        }
    }

    static class MyStorageUnitContainer
    {

        private List<StorageUnit<? extends MyInterface>> storageUnits;

        public MyStorageUnitContainer(List<StorageUnit<? extends MyInterface>> storageUnits)
        {
            this.storageUnits = storageUnits;
        }

        public List<MyInterface> getAllInstances()
        {
            List<MyInterface> instances = new ArrayList<MyInterface>();
            for (StorageUnit<? extends MyInterface> storageUnit : storageUnits)
            {
                List<? extends MyInterface> list = storageUnit.getInstances();
                instances.addAll(list);
            }
            return instances;
        }
    }

    public static void main(String[] args)
    {
        StorageUnit<? extends MyInterface> box1 = new StorageUnit<MyStorable1>(MyStorable1.class, 2);
        StorageUnit<? extends MyInterface> box2 = new StorageUnit<MyStorable2>(MyStorable2.class, 3);
        List<StorageUnit<? extends MyInterface>> boxes = new ArrayList<Sandbox.StorageUnit<? extends MyInterface>>();
        boxes.add(box1);
        boxes.add(box2);

        MyStorageUnitContainer container = new MyStorageUnitContainer(boxes);
        List<MyInterface> allInstances = container.getAllInstances();
        for (MyInterface myInterface : allInstances)
        {
            System.out.println(myInterface.toString());
        }
    }

}
0 голосов
/ 12 апреля 2011

С помощью Java Generics вы не можете перейти от переменной типа (или даже меньше от подстановочного знака) к реальному объекту класса.

Причина в том, как реализованы шаблоны: по стиранию типов.Это означает, что на самом деле во время выполнения ваших универсальных типов больше нет, они стираются в необработанные типы.Только компилятор проверяет, что вы используете правильные типы в нужном месте.

В вашем случае объекты StorageUnit<T> не содержат никакой информации об используемом здесь T, если вы не предоставите имОбъект класса правильного типа.Все они также имеют один и тот же объект класса.

Таким образом, лучше всего было бы дать объектам StorageUnit объект класса своего класса параметров в конструкторе, тогда метод getInstances() не должен был бы приниматьЭто.Конечно, это только переносит проблему необходимости иметь объект класса в другом месте, но где-то это необходимо.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...