我可以将循环作为参数传递给构造函数

ang*_*ngz 5 java constructor

我有一个数组列表,其中包含构造函数所需的所有参数.引用数组中的每个项目然后分别提供参数似乎很多工作.我想知道我是否可以通过在构造函数的括号内迭代它来传递数组列表中的每个项目.

我问我是否可以这样做,或类似的东西传递参数.

constructor object =new constructor(for(String item: parts));
Run Code Online (Sandbox Code Playgroud)

parts是这里的数组列表.列表中的所有项目都是字符串.

bob*_*bah 0

// 我已将您的类“Constructor”重命名为“MyClass”,因为前者可能会令人困惑

Java 中没有直接的语法来执行此操作。但在工厂的帮助下,您可以实现以下目标:

final String[] args = {"one", "two", "three"};
final MyClass obj = newMyClass(args); // effect of new Constructor(args[0], args[1], args[2])
final MyClass obj = newMyClass(args[0], args[1], args[2]); // works too, thanks to the variadic declaration syntax
Run Code Online (Sandbox Code Playgroud)

为此,您将需要一个工厂,要么使用基于注释处理器的代码生成,要么在 sun.misc.Unsafe 的帮助下在应用程序初始化时构建(顺便说一句,这是一些高性能序列化器的做法)。

例子:

package net.bobah.uf4j;

import org.junit.Test;
import sun.misc.Unsafe;

import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.function.BiConsumer;

import static java.lang.System.out;
import static net.bobah.uf4j.MyTest.MyClassFactory.newMyClass;

public class MyTest {

    @Test
    public void runTest() throws Exception {
        final MyClass ctor = newMyClass("one", "two", "three");
        out.println(Arrays.asList(ctor.str1, ctor.str2, ctor.str3));
        // prints [one, two, three]
    }

    public static class MyClass {
        private final String str1;
        private final String str2;
        private final String str3;

        public MyClass(String str1, String str2, String str3) {
            this.str1 = str1;
            this.str2 = str2;
            this.str3 = str3;
        }

    }

    public static class MyClassFactory {
        private static Unsafe getUnsafe() {
            try {
                Field f = Unsafe.class.getDeclaredField("theUnsafe");
                f.setAccessible(true);
                return (Unsafe) f.get(null);
            } catch (IllegalAccessException | NoSuchFieldException cause) {
                throw new RuntimeException(cause);
            }
        }

        private static final Unsafe unsafe = getUnsafe();

        private static final List<BiConsumer<MyClass, String>> fieldInitializers = new ArrayList<>();

        static {
            // this can be extended to support one-to-many mappings from args to fields, or to do type transformation on the way
            for (Field field : MyClass.class.getDeclaredFields()) {
                if (String.class.equals(field.getType())) {
                    final long offset = unsafe.objectFieldOffset(field);
                    fieldInitializers.add((obj, val) -> {
                        unsafe.putObject(obj, offset, val);
                    });
                }
            }
        }

        public static MyClass newMyClass(String... args) throws InstantiationException {
            assert args.length == fieldInitializers.size();

            // create uninitialized instance
            final MyClass obj = (MyClass) unsafe.allocateInstance(MyClass.class);

            // inject final fields
            for (int i = 0; i < args.length; ++i) {
                fieldInitializers.get(i).accept(obj, args[i]);
            }

            return obj;
        }
    }

}
Run Code Online (Sandbox Code Playgroud)