0

I have two a conditions in the method:

if(urlSendModel.isHasPhoto()) {
    ArrayList<InputMediaPhoto> inputMediaPhotos = new ArrayList<>();

    for(String photoUrl : urlSendModel.getPhotos()){
        inputMediaPhotos.add(new InputMediaPhoto(photoUrl));
    }

    SendMediaGroup sendMediaGroup = new SendMediaGroup(message.chat().id(),
            inputMediaPhotos.toArray(new InputMediaPhoto[0]));

    bot.execute(sendMediaGroup);
}
if(urlSendModel.isHasVideo()){
    ArrayList<InputMediaVideo> inputMediaVideos = new ArrayList<>();

    for(String videoUrl : urlSendModel.getVideos()){
        inputMediaVideos.add(new InputMediaVideo(videoUrl));
    }

    SendMediaGroup sendMediaGroup = new SendMediaGroup(message.chat().id(),
            inputMediaVideos.toArray(new InputMediaVideo[0]));

    bot.execute(sendMediaGroup);
}

How can I create something like this or solve the problem in another way.

private <T extends InputMedia<T>> void sendMedia(Message message, ArrayList<String> urls) {
    ArrayList<T> inputMedia = new ArrayList<>();

    for(String url : urls){
        inputMedia.add(new T(url));
    }

    SendMediaGroup sendMediaGroup = new SendMediaGroup(message.chat().id(),
        inputMedia.toArray(new T[0]));

    bot.execute(sendMediaGroup);
}

I will be glad to any proposed solution.

3
  • You can get around new T by having the client specify a class literal, then calling getConstructor(...).newInstance(...). But this will not work for creating a generic array. You'd have to pass the responsibility of creating these objects to the client: sendMedia(message, urls, InputMediaVideo::new, () -> new InputMediaVideo[0]);, declaring the method as <T extends InputMedia<T>> void sendMedia(Message, Function<String, T>, Supplier<T[]>) Commented May 1, 2020 at 13:53
  • @VinceEmigh: You can also use Array.newInstance(klass, length); (and pass in the class) which might be more understandable when reading. Commented May 1, 2020 at 13:58
  • @BeUndead Nice. Deleted my answer because I believe what you suggested would be the proper/easiest way. Haven't looked into reflection for a while, so I must have overlooked that. Feel free to write an answer, will get an upvote from me. Commented May 1, 2020 at 14:04

2 Answers 2

1

Both of the requirements here can be gotten around by passing the class into the method. I'll skip the additional details of what your method does, but, for instance:

<T> void doSomething(final Class<T> klass, final int length) {
    // Replace 'new T[10]'
    final T[] array = Array.newInstance(klass, length);

    final Constructor<T> constructor = klass.getConstructor();
    for (int i = 0; i < length; i++) {
        // Replace 'new T()'
        array[i] = constructor.newInstance();
    }
}

  • Note 1: The replacement for new T() was provided by @Vince Emigh.
  • Note 2: Exception handling is not considered here, so this will not compile as-is.
  • Note 3: If you need to use a different constructor to the one with no arguments, then it may well be simpler to accept a Function<Object[], T> which will convert the arguments you provide to an instance of the type.
Sign up to request clarification or add additional context in comments.

Comments

0

You can do something like creating the generic class first :

public class ClassList<T extends Object>{ private ArrayList<T> list; .... }
// or
public class ClassList<T extends InputMedia>{ private ArrayList<T> list; .... }

and then you cas use constructor or setter to affect a value to your attribute list of T

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.