programing

생성자에 인수가 있는 Java 8 공급업체

shortcode 2022. 10. 6. 22:26
반응형

생성자에 인수가 있는 Java 8 공급업체

공급업체는 왜 no-arg 컨스트럭터만 지원합니까?

기본 생성자가 있는 경우 다음을 수행할 수 있습니다.

create(Foo::new)

단, 컨스트럭터만 String을 사용할 경우 다음을 수행해야 합니다.

create(() -> new Foo("hello"))

, 1arg 컨스트럭터T은 a a가 필요하다.String는 와 이 있습니다.Function<String,T>:

Function<String, Foo> fooSupplier = Foo::new;

선택된 생성자는 대상 유형의 모양에 따라 오버로드 선택 문제로 처리됩니다.

이것은 메서드 참조 구문의 제한일 뿐이며, 어떤 인수에서도 전달할 수 없습니다.구문이 그렇게 되어 있어요.

에 드신다면, 이렇게 .bind사용자가 직접 방법을 사용하여 주십시오.

public static <T, R> Supplier<R> bind(Function<T,R> fn, T val) {
    return () -> fn.apply(val);
}

create(bind(Foo::new, "hello"));

Supplier<T> 시그니처를 .() -> T를 사용하지 않고 , 라, 라, 라, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,,T 하는 메서드 뒤에 인수로 제공하는 메서드 참조가 전달되려면 해당 시그니처 뒤에 와야 합니다.

「」를 Supplier<Foo>@Tagir Valeev가 제안하는 일반적인 바인드 방식을 사용하거나 보다 전문적인 방법을 만들 수 있습니다.

「 」를 Supplier<Foo> 그 말을 ."hello"메서드 String으로 할 수 .메서드로 정의할 수도 있고Supplier<Foo>★★★★★★ 。

방법:

static Foo makeFoo() { return new Foo("hello"); }

변수:

static Supplier<Foo> makeFoo = () -> new Foo("hello");

레퍼런스 레퍼런스)를 시킬 수 .create(WhateverClassItIsOn::makeFoo);할 수 .create(WhateverClassItIsOn.makeFoo);.

방법은 메서드 , 할 수 있기 더 됩니니다() -> T ★★★★★★★★★★★★★★★★★.() -> Foo체적적구

「 」를 합니다.Supplier할 수 는, 「String」, 「Bind」@Tagir」를 방식 @ 것을 가 있습니다.Function:

Supplier<Foo> makeFooFromString(String str) { return () -> new Foo(str); }

수 .create(makeFooFromString("hello"));

하지만 '만들기'는 전부 바꿔야 할 것 같은데.."공급.."에 대한 요청좀 더 명확하게 하기 위해 전화했다.

공급업체는 왜 no-arg 컨스트럭터와만 협력합니까?

에 1-arg 컨스트럭터는 1개의 반환값을 가집니다(예: 1개의 SAM 컨스트럭터).java.util.function.Function<T,R>의 »R apply(T)

★★★★★★★★★★★★★★★★.Supplier<T>T get()0 arg 컨스트럭터와 동형입니다.

그들은 단순히 호환성이 없다.둘 중 하나create()method는 다양한 기능 인터페이스를 받아들이기 위해 폴리모픽이어야 하며 어떤 인수가 제공되는지에 따라 다르게 동작해야 합니다.또는 두 시그니처 간에 글루코드로 동작하기 위해 람다 본문을 작성해야 합니다.

당신은 여기서 무엇을 기대합니까?어떻게 해야 할까요?

공급업체와 기능 조합인터페이스

다음은 특정 컨스트럭터에 대한 컨스트럭터 참조를 함수를 사용하여 "바인딩"하고 "공장" 컨스트럭터 참조를 정의하고 호출하는 다양한 방법을 설명하기 위해 제가 정리한 샘플 코드입니다.

import java.io.Serializable;
import java.util.Date;

import org.junit.Test;

public class FunctionalInterfaceConstructor {

    @Test
    public void testVarFactory() throws Exception {
        DateVar dateVar = makeVar("D", "Date", DateVar::new);
        dateVar.setValue(new Date());
        System.out.println(dateVar);

        DateVar dateTypedVar = makeTypedVar("D", "Date", new Date(), DateVar::new);
        System.out.println(dateTypedVar);

        TypedVarFactory<Date, DateVar> dateTypedFactory = DateVar::new;
        System.out.println(dateTypedFactory.apply("D", "Date", new Date()));

        BooleanVar booleanVar = makeVar("B", "Boolean", BooleanVar::new);
        booleanVar.setValue(true);
        System.out.println(booleanVar);

        BooleanVar booleanTypedVar = makeTypedVar("B", "Boolean", true, BooleanVar::new);
        System.out.println(booleanTypedVar);

        TypedVarFactory<Boolean, BooleanVar> booleanTypedFactory = BooleanVar::new;
        System.out.println(booleanTypedFactory.apply("B", "Boolean", true));
    }

    private <V extends Var<T>, T extends Serializable> V makeVar(final String name, final String displayName,
            final VarFactory<V> varFactory) {
        V var = varFactory.apply(name, displayName);
        return var;
    }

    private <V extends Var<T>, T extends Serializable> V makeTypedVar(final String name, final String displayName, final T value,
            final TypedVarFactory<T, V> varFactory) {
        V var = varFactory.apply(name, displayName, value);
        return var;
    }

    @FunctionalInterface
    static interface VarFactory<R> {
        // Don't need type variables for name and displayName because they are always String
        R apply(String name, String displayName);
    }

    @FunctionalInterface
    static interface TypedVarFactory<T extends Serializable, R extends Var<T>> {
        R apply(String name, String displayName, T value);
    }

    static class Var<T extends Serializable> {
        private String name;
        private String displayName;
        private T value;

        public Var(final String name, final String displayName) {
            this.name = name;
            this.displayName = displayName;
        }

        public Var(final String name, final String displayName, final T value) {
            this(name, displayName);
            this.value = value;
        }

        public void setValue(final T value) {
            this.value = value;
        }

        @Override
        public String toString() {
            return String.format("%s[name=%s, displayName=%s, value=%s]", getClass().getSimpleName(), this.name, this.displayName,
                    this.value);
        }
    }

    static class DateVar extends Var<Date> {
        public DateVar(final String name, final String displayName) {
            super(name, displayName);
        }

        public DateVar(final String name, final String displayName, final Date value) {
            super(name, displayName, value);
        }
    }

    static class BooleanVar extends Var<Boolean> {
        public BooleanVar(final String name, final String displayName) {
            super(name, displayName);
        }

        public BooleanVar(final String name, final String displayName, final Boolean value) {
            super(name, displayName, value);
        }
    }
}

매개 변수화된 솔루션에 대한 검색 시Supplier저는 위의 답변이 도움이 된다는 것을 알고 제안사항을 적용했습니다.

private static <T, R> Supplier<String> failedMessageSupplier(Function<String,String> fn, String msgPrefix, String ... customMessages) {
    final String msgString = new StringBuilder(msgPrefix).append(" - ").append(String.join("\n", customMessages)).toString();
    return () -> fn.apply(msgString);
}

다음과 같이 호출됩니다.

failedMessageSupplier(String::new, msgPrefix, customMsg);

풍부한 static function 파라미터에 아직 만족하지 못하고 Function.identity()사용하여 다음 결과를 얻었습니다.

private final static Supplier<String> failedMessageSupplier(final String msgPrefix, final String ... customMessages) {
    final String msgString = new StringBuilder(msgPrefix).append(" - ").append(String.join("\n", customMessages)).toString();
    return () -> (String)Function.identity().apply(msgString);
}; 

static function 매개 변수가 없는 호출:

failedMessageSupplier(msgPrefix, customMsg)

부터Function.identity()유형의 함수를 반환합니다.Object의 후속 콜도 마찬가지입니다.apply(msgString), 출연자:String필수입니다.또는 apply()가 공급되고 있는 타입이 무엇이든 상관없습니다.

이 방법에서는 예를 들어 다중 파라미터, 동적 문자열 처리, 문자열 상수 접두사, 접미사 등을 사용할 수 있습니다.

아이덴티티를 사용하면 이론적으로 String::new보다 약간 엣지가 있어야 합니다.이거는 항상 새로운 스트링이 생성됩니다.

제이콥 짐머만이 이미 지적했듯이, 더 간단한 매개 변수화된 형태는

Supplier<Foo> makeFooFromString(String str1, String str2) { 
    return () -> new Foo(str1, str2); 
}

항상 가능합니다.이것이 문맥에서 이치에 맞는지 아닌지는, 에 의해서 다릅니다.

위에서 설명한 바와 같이 스태틱메서드 레퍼런스콜에서는 함수 소비형(스트림) 메서드에서 예상되는 것과 일치하도록 대응하는 메서드의 수와 리턴/파라미터 타입이 필요합니다.

컨스트럭터가 있는 경우new Klass(ConstructorObject)그 후 를 사용할 수 있습니다.Function<ConstructorObject, Klass>다음과 같습니다.

interface Interface {
    static Klass createKlass(Function<Map<String,Integer>, Klass> func, Map<String, Integer> input) {
        return func.apply(input);
    }
}
class Klass {
    private Integer integer;
    Klass(Map<String, Integer> map) {
        this.integer = map.get("integer");
    }
    public static void main(String[] args) {
        Map<String, Integer> input = new HashMap<>();
        input.put("integer", 1);
        Klass klazz = Interface.createKlass(Klass::new, input);
        System.out.println(klazz.integer);
    }
}

언급URL : https://stackoverflow.com/questions/31251629/java-8-supplier-with-arguments-in-the-constructor

반응형