your programing

Java 선택적 매개 변수

lovepro 2020. 9. 29. 08:16
반응형

Java 선택적 매개 변수


Java에서 선택적 매개 변수를 어떻게 사용합니까? 선택적 매개 변수를 지원하는 사양은 무엇입니까?


varargs는 그렇게 할 수 있습니다. 그 외에는 메서드 선언에있는 모든 변수를 제공해야합니다. 변수를 선택 사항으로 지정하려면 매개 변수가 필요하지 않은 서명을 사용하여 메서드를 오버로드 할 수 있습니다.

private boolean defaultOptionalFlagValue = true;

public void doSomething(boolean optionalFlag) {
    ...
}

public void doSomething() {
    doSomething(defaultOptionalFlagValue);
}

Java에서 선택적 매개 변수를 시뮬레이션하는 방법에는 여러 가지가 있습니다.

  1. 메서드 오버로딩.

    void foo(String a, Integer b) {
        //...
    }
    
    void foo(String a) {
        foo(a, 0); // here, 0 is a default value for b
    }
    
    foo("a", 2);
    foo("a");
    

    이 방법의 한계 중 하나는 동일한 유형의 두 개의 선택적 매개 변수가 있고 이들 중 하나를 생략 할 수있는 경우 작동하지 않는다는 것입니다.

  2. Varargs.

    a) 모든 선택적 매개 변수는 동일한 유형입니다.

    void foo(String a, Integer... b) {
        Integer b1 = b.length > 0 ? b[0] : 0;
        Integer b2 = b.length > 1 ? b[1] : 0;
        //...
    }
    
    foo("a");
    foo("a", 1, 2);
    

    b) 선택적 매개 변수의 유형은 다를 수 있습니다.

    void foo(String a, Object... b) {
        Integer b1 = 0;
        String b2 = "";
        if (b.length > 0) {
          if (!(b[0] instanceof Integer)) { 
              throw new IllegalArgumentException("...");
          }
          b1 = (Integer)b[0];
        }
        if (b.length > 1) {
            if (!(b[1] instanceof String)) { 
                throw new IllegalArgumentException("...");
            }
            b2 = (String)b[1];
            //...
        }
        //...
    }
    
    foo("a");
    foo("a", 1);
    foo("a", 1, "b2");
    

    이 접근 방식의 가장 큰 단점은 선택적 매개 변수의 유형이 다른 경우 정적 유형 검사가 손실된다는 것입니다. 또한 각 매개 변수의 의미가 다른 경우이를 구별 할 방법이 필요합니다.

  3. 널. 이전 접근 방식의 한계를 해결하기 위해 null 값을 허용 한 다음 메서드 본문의 각 매개 변수를 분석 할 수 있습니다.

    void foo(String a, Integer b, Integer c) {
        b = b != null ? b : 0;
        c = c != null ? c : 0;
        //...
    }
    
    foo("a", null, 2);
    

    이제 모든 인수 값을 제공해야하지만 기본값은 null 일 수 있습니다.

  4. 선택 클래스. 이 접근 방식은 null과 유사하지만 기본값이있는 매개 변수에 대해 Java 8 선택적 클래스를 사용합니다.

    void foo(String a, Optional<Integer> bOpt) {
        Integer b = bOpt.isPresent() ? bOpt.get() : 0;
        //...
    }
    
    foo("a", Optional.of(2));
    foo("a", Optional.<Integer>absent());
    

    선택 사항은 호출자에 대해 메서드 계약을 명시 적으로 지정하지만 이러한 서명이 너무 장황 할 수 있습니다.

    업데이트 : Java 8에는 java.util.Optional즉시 사용 가능한 클래스가 포함되어 있으므로 Java 8 에서 이러한 특정 이유로 guava를 사용할 필요가 없습니다. 메서드 이름은 약간 다릅니다.

  5. 빌더 패턴. 빌더 패턴은 생성자에 사용되며 별도의 빌더 클래스를 도입하여 구현됩니다.

     class Foo {
         private final String a; 
         private final Integer b;
    
         Foo(String a, Integer b) {
           this.a = a;
           this.b = b;
         }
    
         //...
     }
    
     class FooBuilder {
       private String a = ""; 
       private Integer b = 0;
    
       FooBuilder setA(String a) {
         this.a = a;
         return this;
       }
    
       FooBuilder setB(Integer b) {
         this.b = b;
         return this;
       }
    
       Foo build() {
         return new Foo(a, b);
       }
     }
    
     Foo foo = new FooBuilder().setA("a").build();
    
  6. 지도. 매개 변수의 수가 너무 많고 대부분의 기본값이 일반적으로 사용되는 경우 메서드 인수를 이름 / 값의 맵으로 전달할 수 있습니다.

    void foo(Map<String, Object> parameters) {
        String a = ""; 
        Integer b = 0;
        if (parameters.containsKey("a")) { 
            if (!(parameters.get("a") instanceof Integer)) { 
                throw new IllegalArgumentException("...");
            }
            a = (Integer)parameters.get("a");
        }
        if (parameters.containsKey("b")) { 
            //... 
        }
        //...
    }
    
    foo(ImmutableMap.<String, Object>of(
        "a", "a",
        "b", 2, 
        "d", "value")); 
    

    Java 9에서는이 접근 방식이 더 쉬워졌습니다.

        @SuppressWarnings("unchecked")
        static <T> T getParm(Map<String, Object> map, String key, T defaultValue)
        {
            return (map.containsKey(key)) ? (T) map.get(key) : defaultValue;
        }
    
        void foo(Map<String, Object> parameters) {
            String a = getParm(parameters, "a", "");
            int b = getParm(parameters, "b", 0);
            // d = ...
        }
    
        foo(Map.of("a","a",  "b",2,  "d","value"));
    

이러한 접근 방식을 결합하여 원하는 결과를 얻을 수 있습니다.


다음과 같이 사용할 수 있습니다.

public void addError(String path, String key, Object... params) { 
}

params변수는 선택 사항입니다. nullable 개체 배열로 처리됩니다.

이상하게도 문서에서 이것에 대해 아무것도 찾을 수 없었지만 작동합니다!

이것은 Java 1.5 이상에서 "새로운 기능"입니다 (Java 1.4 이하에서는 지원되지 않음).

나는 사용자 bhoot가 이것을 너무 아래에서 언급 한 것을 봅니다.


Java 5.0에는 선택적 매개 변수가 있습니다. 다음과 같이 함수를 선언하십시오.

public void doSomething(boolean... optionalFlag) {
    //default to "false"
    //boolean flag = (optionalFlag.length >= 1) ? optionalFlag[0] : false;
}

doSomething();또는 doSomething(true);지금 전화 할 수 있습니다.


불행히도 Java는 기본 매개 변수를 직접 지원하지 않습니다.

그러나 JavaBean 주석 세트를 작성했으며 그중 하나는 다음과 같은 기본 매개 변수를 지원합니다.

protected void process(
        Processor processor,
        String item,
        @Default("Processor.Size.LARGE") Size size,
        @Default("red") String color,
        @Default("1") int quantity) {
    processor.process(item, size, color, quantity);
}
public void report(@Default("Hello") String message) {
    System.out.println("Message: " + message);
}

주석 프로세서는이를 적절히 지원하기 위해 메서드 오버로드를 생성합니다.

http://code.google.com/p/javadude/wiki/Annotations 참조

http://code.google.com/p/javadude/wiki/AnnotationsDefaultParametersExample의 전체 예제


Java에는 선택적 매개 변수가 없습니다. 할 수있는 일은 함수를 오버로딩 한 다음 기본값을 전달하는 것입니다.

void SomeMethod(int age, String name) {
    //
}

// Overload
void SomeMethod(int age) {
    SomeMethod(age, "John Doe");
}

VarArgs and overloading have been mentioned. Another option is a Builder pattern, which would look something like this:

 MyObject my = new MyObjectBuilder().setParam1(value)
                                 .setParam3(otherValue)
                                 .setParam6(thirdValue)
                                 .build();

Although that pattern would be most appropriate for when you need optional parameters in a constructor.


In JDK>1.5 you can use it like this;

public class NewClass1 {

    public static void main(String[] args) {

        try {
            someMethod(18); // Age : 18
            someMethod(18, "John Doe"); // Age & Name : 18 & John Doe
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    static void someMethod(int age, String... names) {

        if (names.length > 0) {
            if (names[0] != null) {
                System.out.println("Age & Name : " + age + " & " + names[0]);
            }
        } else {
            System.out.println("Age : " + age);
        }
    }
}

It would depends on what you want to achieve, varargs or method overloading should solve most scenarios. Here some nice examples of how to use them:

http://blog.sleekface.com/in/java-core/method-with-optional-parameters/

but keep in mind not to over use method overloading. it brings confusion.


Short version :

Using three dots:

public void foo(Object... x) {
    String first    =  x.length > 0 ? (String)x[0]  : "Hello";
    int duration    =  x.length > 1 ? Integer.parseInt((String) x[1])     : 888;
}   
foo("Hii", ); 
foo("Hii", 146); 

(based on @VitaliiFedorenko's answer)


You can do thing using method overloading like this.

 public void load(String name){ }

 public void load(String name,int age){}

Also you can use @Nullable annotation

public void load(@Nullable String name,int age){}

simply pass null as first parameter.

If you are passing same type variable you can use this

public void load(String name...){}

Overloading is fine, but if there's a lot of variables that needs default value, you will end up with :

public void methodA(A arg1) {  }
public void methodA( B arg2,) {  }
public void methodA(C arg3) {  }
public void methodA(A arg1, B arg2) {  }
public void methodA(A arg1, C arg3) {  }
public void methodA( B arg2, C arg3) {  }
public void methodA(A arg1, B arg2, C arg3) {  }

So I would suggest use the Variable Argument provided by Java. Here's a link for explanation.


Java now supports optionals in 1.8, I'm stuck with programming on android so I'm using nulls until I can refactor the code to use optional types.

Object canBeNull() {
    if (blah) {
        return new Object();
    } else {
        return null;
    }
}

Object optionalObject = canBeNull();
if (optionalObject != null) {
    // new object returned
} else {
    // no new object returned
}

You can use a class that works much like a builder to contain your optional values like this.

public class Options {
    private String someString = "default value";
    private int someInt= 0;
    public Options setSomeString(String someString) {
        this.someString = someString;
        return this;
    }
    public Options setSomeInt(int someInt) {
        this.someInt = someInt;
        return this;
    }
}

public static void foo(Consumer<Options> consumer) {
    Options options = new Options();
    consumer.accept(options);
    System.out.println("someString = " + options.someString + ", someInt = " + options.someInt);
}

Use like

foo(o -> o.setSomeString("something").setSomeInt(5));

Output is

someString = something, someInt = 5

To skip all the optional values you'd have to call it like foo(o -> {}); or if you prefer, you can create a second foo() method that doesn't take the optional parameters.

Using this approach, you can specify optional values in any order without any ambiguity. You can also have parameters of different classes unlike with varargs. This approach would be even better if you can use annotations and code generation to create the Options class.


Default arguments can not be used in Java. Where in C#, C++ and Python, we can use them..

In Java, we must have to use 2 methods (functions) instead of one with default parameters.

Example:

Stash(int size); 

Stash(int size, int initQuantity);

http://parvindersingh.webs.com/apps/forums/topics/show/8856498-java-how-to-set-default-parameters-values-like-c-


We can make optional parameter by Method overloading or Using DataType...

|*| Method overloading :

RetDtaTyp NamFnc(String NamPsgVar)
{
    // |* CodTdo *|
    return RetVar;
}

RetDtaTyp NamFnc(String NamPsgVar)
{
    // |* CodTdo *|
    return RetVar;
}

RetDtaTyp NamFnc(int NamPsgVar1, String NamPsgVar2)
{
    // |* CodTdo *|
    return RetVar;
}

Easiest way is

|*| DataType... can be optional parameter

RetDtaTyp NamFnc(int NamPsgVar, String... SrgOpnPsgVar)
{
    if(SrgOpnPsgVar.length == 0)  SrgOpnPsgVar = DefSrgVar; 

    // |* CodTdo *|
    return RetVar;
}


This is an old question maybe even before actual Optional type was introduced but these days you can consider few things: - use method overloading - use Optional type which has advantage of avoiding passing NULLs around Optional type was introduced in Java 8 before it was usually used from third party lib such as Google's Guava. Using optional as parameters / arguments can be consider as over-usage as the main purpose was to use it as a return time.

Ref: https://itcodehub.blogspot.com/2019/06/using-optional-type-in-java.html

참고URL : https://stackoverflow.com/questions/965690/java-optional-parameters

반응형