Как использовать varargs в качестве параметров newInstance () для вызова конструктора и создания экземпляра? - PullRequest
0 голосов
/ 22 марта 2020

Я автодидакт, и я пытаюсь сделать это домашнее задание, но я не нашел никакого решения.

Я не знаю, как использовать varargs. Я не могу передать их в метод newInstance (), чтобы вызвать конструктор, который мне нужен. Но главная проблема в том, что я хотел бы написать их из командной строки, используя «args», но я не знаю, как это сделать.

Пожалуйста, какой-нибудь совет? Большое спасибо!

import java.lang.reflect.*;
import java.io.*;

public class VarargsTest{
    public static void main(String[] args)throws IOException{
        Class theClass = null;
        BufferedReader br = null;
        br = new BufferedReader(new InputStreamReader(System.in));
        try{
            theClass = Class.forName(args[0]); // what class I want to use ?
        }
        catch(ClassNotFoundException e){
            e.printStackTrace();
            System.exit(1);
        }
        System.out.println(theClass);
        Object obj = null;
        System.out.print("number of constructor's parameters :"); 
        String buf = null;
        try{
            buf = br.readLine(); //Waiting the number of parameters for the constructor
        }
        catch(IOException ioe){
            ioe.printStackTrace();
        }
        Constructor[] constructors = theClass.getConstructors(); // constructor of that class
        for(Constructor constructor : constructors) {
            if(constructor.getParameterCount() == Integer.parseInt(buf)) {//checking that the number of parameters are matching
                if(constructor.getParameterTypes()[0] == VarargsC.class){// IL PRIMO PARAMETRO DEL COSTRUTTORE DEVE ESSERE DEL TIPO DELLA CLASSE

                    try{

                        obj = constructor.newInstance(new Object[]{"first", "second"," more"}); // trying some elements, but I would like use args[1]
                    }
                    catch(InstantiationException | IllegalAccessException | InvocationTargetException e) {
                        e.printStackTrace();
                        System.exit(1);
                    }
                }
            }
        }
        System.out.println();
        System.out.println("There isn't a constructor with " + buf + " parameters");
        System.out.println();
        if(obj != null) {
            System.out.println("I have instantiate an object!");
            System.out.println(obj);
        }else{
            System.out.println("I'm not able to instantiate an object'");
        }
    }
}

class VarargsC{
    String str1;
    String str2;
    String str3;
        public VarargsC(String str1, String str2, String str3){
            this.str1 = str1;   
            this.str2 = str2;
            this.str3 = str3;
        }
        public String toString(){
            return "VarargsC{" +
                    "str1=" + str1 +"\n" +
                    "str2=" + str2 +"\n" +
                    "str3=" + str3 + "\n" + '\'' +
                    '}';
        }
}


/*class VarargsC{

    String[] data;
        public VarargsC(String... str){
            data = new String[5];
            for(int i= 0; i< str.length; i++)
                                for(String a: str)
                this.data[i] = a;
        }

        public void toString(String... str){
            for(String a: str)
                System.out.println(a + "\n");
        }
}*/

1 Ответ

2 голосов
/ 23 марта 2020

Функция varargs языка программирования Java позволяет вызывать метод, который поддерживает переменное число аргументов, как обычный метод с n аргументами в исходный код . Это не связано с вашим намерением разрешить произвольное количество аргументов в командной строке .

На самом деле, эта функция исходного кода даже не нужна для вашей операции. Вы получаете аргументы командной строки в массиве, длина которого отражает их число. Вы можете проверить длину массива, используя args.length.

public class Test {
    public static void main(String[] args) {
      if(args.length == 0) {
          System.err.println("specify <className> args...");
          System.exit(1);
      }

      String className = args[0];
      // remove the first element
      args = Arrays.copyOfRange(args, 1, args.length);

      Class<?> theClass;// don't initialize with null
      try {
          theClass = Class.forName(className);
      }
      catch(ClassNotFoundException e) {
          e.printStackTrace();
          System.exit(1);
          throw new AssertionError(); // unreachable point
      }

      // constructor accepting n strings
      Class<?>[] argTypes = new Class[args.length];
      Arrays.fill(argTypes, String.class);

      try {
          Constructor<?> c = theClass.getConstructor(argTypes);
          Object o = c.newInstance((Object[])args);
          System.out.println("created " + o);
      } catch(ReflectiveOperationException e) {
          e.printStackTrace();
          System.exit(1);
      }
    }
}

Вызов newInstance не использует функцию varargs, так как на уровне исходного кода у нас уже есть массив. Фактически, приведение (Object[]) существует, чтобы сделать явным то, что мы не хотим использовать функцию varargs, то есть мы не хотим вызывать конструктор, принимающий единственный аргумент массива, но конструктор, принимающий столько строковых аргументов, сколько массив содержит.

Обратите внимание, что код вашего примера newInstance(new Object[]{"first", "second"," more"}) также не использовал varargs, так как он явно создает массив, вызывая newInstance(Object[]) так же, как решение этого ответа. Вызов varargs будет newInstance("first", "second"," more"), который работает, только если мы знаем, что во время компиляции конструктор ожидает три строковых аргумента.

...