Java에서 커링을 적용하기 위한 사용자 지정 주석

6452 단어 java
메서드 또는 생성자에 커링을 적용하기 위해 사용자 지정 주석을 만들었습니다.

여기에서 전체 코드를 찾을 수 있습니다: curry .

커링에 대한 자세한 내용은 this 를 확인하고 Java의 주석에 대한 배경 정보는 this 를 확인하십시오.

먼저 주석을 만듭니다.

@Retention(RetentionPolicy.SOURCE)
@Target({ElementType.METHOD, ElementType.CONSTRUCTOR})
public @interface Curry {}


주석만 처리한 다음 폐기해야 하므로(런타임에 주석을 사용하거나 .class에 기록할 필요가 없음) @Retention(RetentionPolicy.SOURCE) 를 사용합니다.

이 주석은 메서드 및 생성자에서만 사용되므로 대상을 @Target({ElementType.METHOD, ElementType.CONSTRUCTOR}) 로 설정합니다.

그런 다음 주석에 대한 프로세서를 만듭니다.

@SupportedAnnotationTypes("dev.jsedano.curry.annotation.Curry")
@SupportedSourceVersion(SourceVersion.RELEASE_17)
@AutoService(Processor.class)
public class CurryProcessor extends AbstractProcessor {

@SupportedAnnotationTypes("dev.jsedano.curry.annotation.Curry")를 사용하면 이 프로세서가 해당 특정 주석만 찾습니다.
@SupportedSourceVersion(SourceVersion.RELEASE_17) 여기서는 지원되는 Java 버전을 말합니다.

마지막 것은 꽤 흥미로운데, @AutoService(Processor.class)auto-service이라는 Google 라이브러리에서 가져온 것입니다. Java 컴파일러가 프로세서를 사용하려면 클래스가 META-INF/services 파일의 javax.annotation.processing.Processor 디렉토리에 있는 jar 내에서 선언되어야 하며 자동 서비스 라이브러리가 이를 수행합니다.

그런 다음 사용자 지정 프로세서에서 process 메서드를 구현해야 합니다.

public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {


클래스 내에서 우리는 processingEnv와 같은 기능을 제공하는 getMessager() 개체를 얻습니다. 이 개체는 @Curry 주석이 1개 또는 10개 이상의 매개 변수가 있는 메서드에서 사용될 때 컴파일 시간에 경고 메시지를 인쇄하는 데 사용합니다.

otherMethods.stream()
    .forEach(
        e ->
            processingEnv
                .getMessager()
                .printMessage(
                    Diagnostic.Kind.MANDATORY_WARNING,
                    "incorrect number of parameters, allowed only between 2 and 1O, will not generate code for this one",
                    e));


Java 소스 파일을 생성할 수 있는 다음 항목getFiler()도 있습니다.

JavaFileObject builderFile = processingEnv.getFiler().createSourceFile(builderClassName);


프로젝트의 tests 모듈에서 @Curry 주석이 있는 몇 가지 메서드를 선언합니다. 예를 들어 이 생성자는 다음과 같습니다.

@Curry
public AnnotatedClass(
    boolean aBoolean, List<String> aStringList, int aNumber, char aChar, float aFloat) {
  this.aBoolean = aBoolean;
  this.aStringList = aStringList;
  this.aNumber = aNumber;
  this.aChar = aChar;
  this.aFloat = aFloat;
}


상위 모듈에서 mvn clean verify를 실행한 후 target/generated-sources/annotations/dev.jsedano.curry.tests에서 자동 생성된 코드를 볼 수 있습니다.

public static java.util.function.Function<java.lang.Boolean,java.util.function.Function<java.util.List<java.lang.String>,java.util.function.Function<java.lang.Integer,java.util.function.Function<java.lang.Character,java.util.function.Function<java.lang.Float,dev.jsedano.curry.tests.AnnotatedClass>>>>> pentaConstructor(dev.jsedano.curry.util.function.PentaFunction<java.lang.Boolean,java.util.List<java.lang.String>,java.lang.Integer,java.lang.Character,java.lang.Float,dev.jsedano.curry.tests.AnnotatedClass> function) {
    return v0->v1->v2->v3->v4-> function.apply(v0,v1,v2,v3,v4);
}


보기 좋지는 않지만 이를 사용하여 예제 클래스의 5개 매개변수 생성자를 커링할 수 있습니다.

var pentaConstructor = AnnotatedClassCurryer.pentaConstructor(AnnotatedClass::new);


다른 예here를 볼 수 있지만 컴파일하려면 curry의 curryer 모듈에서 mvn clean install를 수행해야 합니다.

@Curry
public static String wget(
    int connectionTimeout,
    int readTimeout,
    boolean followRedirects,
    String requestMethod,
    String address) {
  try {
    URL url = new URL(address);
    HttpURLConnection con = (HttpURLConnection) url.openConnection();
    con.setRequestMethod(requestMethod);
    con.setConnectTimeout(connectionTimeout);
    con.setReadTimeout(readTimeout);
    con.setInstanceFollowRedirects(followRedirects);
    BufferedReader in = new BufferedReader(new InputStreamReader(con.getInputStream()));
    String inputLine;
    StringBuffer content = new StringBuffer();
    while ((inputLine = in.readLine()) != null) {
      content.append(inputLine);
    }
    in.close();
    return address + " " + content.toString();
  } catch (Exception e) {
    StringWriter sw = new StringWriter();
    PrintWriter pw = new PrintWriter(sw);
    e.printStackTrace(pw);
    String stackTrace = sw.toString();
    return address + " " + stackTrace.substring(0, stackTrace.indexOf("\n"));
  }
}


그런 다음 커리 방식으로 필요한 값을 설정하고 사용할 수 있습니다.

public static void main(String[] args) {
  var get =
      WgetVersion2Curryer.wget(WgetVersion2::wget)
          .apply(100)
          .apply(100)
          .apply(false)
          .apply("GET");

  List.of(
          "https://www.google.com",
          "https://www.wikipedia.org",
          "asdf",
          "https://docs.oracle.com/javase/10/docs/api/java/net/package-summary.html",
          "https://jsedano.dev",
          "https://raw.githubusercontent.com/center-key/clabe-validator/main/clabe.ts")
      .parallelStream()
      .map(get)
      .forEach(System.out::println);
}


이 게시물에서 전체 코드를 다운로드하십시오: curry .

좋은 웹페이지 즐겨찾기