Возможна ли передача ссылочного типа в экземпляр объекта, который нуждается в ссылочном типе динамически? - PullRequest
0 голосов
/ 28 февраля 2019

Например:

public void builCarManager(Car car) {
   Manager<car.getClass()> carManager = new Manager<>();
}

Какие-нибудь предложения по решению этой проблемы?

РЕДАКТИРОВАТЬ

Моя главная проблема заключается в следующем:

public class CustomSerializer<T> extends StdSerializer<T> {

    @Override
    public void serialize(T car, JsonGenerator gen, SerializerProvider sp) {
        // I get car.getClass() fine but I need add it
        Manager<T> carManager = new Manager<>();
        // Manager<car.getClass()> carManager = new Manager<>();
    }
}

Здесь я не могу пройти CustomSerializer<Lamborgini>.class.

@JsonSerialize(using = CustomSerializer.class)
private Lamborgini car; 

Ответы [ 3 ]

0 голосов
/ 28 февраля 2019

Правильный способ справиться с этим состоит в том, чтобы два класса (например, Car и Desk) реализовали общий интерфейс (например, Item) и связали этот интерфейс с классом Manager.

public class Instance {
    private static interface Item {
        String getName();
    }

    private static class Car implements Item {
        @Override
        public String getName() {
            return "Car";
        }
    }

    private static class Desk implements Item {
        @Override
        public String getName() {
            return "Desk";
        }
    }

    private static class Manager<T extends Item> {
        private T item;

        public Manager(T item) {
            this.item = item;
        }

        @Override
        public String toString() {
            return String.format("Manager[item=%s]", item.getName());
        }
    }

    public static <E extends Item> Manager<E> buildItemManager(E item) {
        return new Manager<E>(item);
     }

    public static void main(String[] args) {
        Item car  = new Car(), desk = new Desk();

        Manager<Item> manager1 = buildItemManager(car);
        System.out.println(manager1);

        Manager<Item> manager2 = buildItemManager(desk);
        System.out.println(manager2);
    }
}

Вывод

Manager[item=Car]
Manager[item=Desk]

Другой вариант ... создание экземпляра Manager путем передачи класса, представляющего Item.

public class Instance {
    public static interface Item {
        String getName();
    }

    public static class Car implements Item {
        @Override
        public String getName() {
            return "Car";
        }
    }

    public static class Desk implements Item {
        @Override
        public String getName() {
            return "Desk";
        }
    }

    public static class Manager<T extends Item> {
        private T item;

        public Manager(T item) {
            this.item = item;
        }

        @Override
        public String toString() {
            return String.format("Manager[item=%s]", item.getName());
        }
    }

    public static <E extends Item> Manager<E> buildItemManager(Class<E> item) throws InstantiationException, IllegalAccessException {
        return new Manager<E>(item.newInstance());
     }

    public static void main(String[] args) {
        try {
            /* Cannot initialize array with generic types... */
            @SuppressWarnings("unchecked")
            Manager<? extends Item>[] managers = new Manager[2];

            managers[0] = buildItemManager(Car.class);
            managers[1] = buildItemManager(Desk.class);

            for (Manager<?> manager : managers) {
                System.out.println(manager);
            }
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
    }
}
0 голосов
/ 28 февраля 2019

Предположим, у вас ниже POJO модель:

class Car {
}

class Lamborghini extends Car {
}

class Ferrari extends Car {
}

Ваш класс Manager выглядит следующим образом:

class Manager<T extends Car> {

    private Class<T> clazz;

    public Manager(Class<T> clazz) {
        this.clazz = clazz;
    }

    public String generateCustomCarName() {
        if (Lamborghini.class == clazz) {
            return "Lambooooo!";
        } else if (Ferrari.class == clazz) {
            return "Wild horse Ferrari!";
        }

        return "Not for everyone!";
    }

    @Override
    public String toString() {
        return String.format("Manager[clazz=%s]", clazz.getName());
    }
}

Теперь давайте создадим Store, который имеетодин Ferrari и один Lamborghini:

class Store {

    private Car ferrari = new Ferrari();
    private Car lamborghini = new Lamborghini();

    public Car getFerrari() {
        return ferrari;
    }

    public void setFerrari(Car ferrari) {
        this.ferrari = ferrari;
    }

    public Car getLamborghini() {
        return lamborghini;
    }

    public void setLamborghini(Car lamborghini) {
        this.lamborghini = lamborghini;
    }
}

Теперь нам нужно иметь class информацию во время выполнения.Из-за Java типа Erasure нам необходимо предоставить class:

class CustomCarSerializer<T extends Car> extends StdSerializer<T> {

    public CustomCarSerializer(Class<T> clazz) {
        super(clazz);
    }

    @Override
    public void serialize(T value, JsonGenerator jgen, SerializerProvider provider)
        throws IOException {
        Manager<T> manager = new Manager<>(_handledType);
        jgen.writeString(manager.generateCustomCarName());
    }
}

Обратите внимание, что StdSerializer также имеет конструктор, которому требуется class, и мы можем прочитать егопозже используя _handledType.Сейчас нам нужно сконфигурировать наши реализации с сериализаторами, используя SimpleModule:

import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.module.SimpleModule;
import com.fasterxml.jackson.databind.ser.std.StdSerializer;
import java.io.IOException;

public class Cars {

    public static void main(String[] args) throws Exception {
        SimpleModule carsModule = new SimpleModule("CarsModule");
        carsModule.addSerializer(Lamborghini.class, new CustomCarSerializer<>(Lamborghini.class));
        carsModule.addSerializer(Ferrari.class, new CustomCarSerializer<>(Ferrari.class));

        ObjectMapper mapper = new ObjectMapper();
        mapper.registerModule(carsModule);
        mapper.enable(SerializationFeature.INDENT_OUTPUT);

        System.out.println(mapper.writeValueAsString(new Store()));
    }
}

Над отпечатками кода:

{
  "ferrari" : "Wild horse Ferrari!",
  "lamborghini" : "Lambooooo!"
}
0 голосов
/ 28 февраля 2019

Да, вы можете использовать дженерики.

  public <T> void builCarManager(T car) {
    Manager<T> carManager = new Manager<>();
 }

Теперь вы можете передавать любой тип объекта.Созданный менеджер будет того же типа.

...