Java가 기본 매개 변수 값을 지원합니까?


1661

다음과 같은 구조를 가진 일부 Java 코드를 발견했습니다.

public MyParameterizedFunction(String param1, int param2)
{
    this(param1, param2, false);
}

public MyParameterizedFunction(String param1, int param2, boolean param3)
{
    //use all three parameters here
}

C ++에서 매개 변수에 기본값을 할당 할 수 있다는 것을 알고 있습니다. 예를 들면 다음과 같습니다.

void MyParameterizedFunction(String param1, int param2, bool param3=false);

Java가 이런 종류의 구문을 지원합니까? 이 두 단계 구문이 바람직한 이유가 있습니까?


85
그러나 빌더 패턴이 도움이 될 수 있습니다.
Dave Jarvis

50
이 기능이 정말 그립습니다. 기존 코드를 수정하여 함수 나 생성자에 추가 매개 변수를 가져 오면 많은 도움이됩니다.
Jatin

4
@Jatin Eclipse "Change method signature"리팩토링을 사용하면 매개 변수를 추가하고 기존 호출자가 사용할 기본값을 제공 할 수 있습니다.
Erwin Bolwidt

2
@ErwinBolwidt 감사합니다. Android Studio를 사용하고 있으며 메소드를 리팩토링하고 기본값을 제공하는 옵션도 있습니다. 매우 유용합니다.
Jatin

3
@temporary_user_name public MyParameterizedFunction(String param1, int param2)은 메소드 선언이 아닌 생성자입니다.
마리오 Ishac

답변:


955

아니오, 발견 한 구조는 Java가 Java를 처리하는 방식입니다 (즉, 기본 매개 변수 대신 오버로드 사용).

생성자 가 오버로드가 복잡 해지는 경우 효과적인 Java : 프로그래밍 언어 안내서의 항목 1 팁 (생성자 대신 정적 팩토리 메소드 고려)을 참조하십시오. 다른 방법의 경우 일부 사례의 이름을 바꾸거나 매개 변수 객체를 사용하면 도움이 될 수 있습니다. 이것은 차별화가 어려운 복잡성이 충분할 때입니다. 명확한 경우는 숫자와 유형뿐만 아니라 매개 변수의 순서를 사용하여 차별화해야하는 경우입니다.


25
이것은 2009 년에 이루어졌으며 static2015 년에는 거의 해로운 것으로 간주됩니다. 완전하고 유효한 건설 계약을 시행하는 안전하고 유창한 유형의 Builder인스턴스가 훨씬 나은 솔루션입니다.

135
@JarrodRoberson : 정적 팩토리 메소드는 new. 그들은되어 사용되는 모든 시간을 새로운 코드. 단순한 가치 객체의 빌더는 종종 과도한 엔지니어링의 결과입니다.
Lii

12
@JarrodRoberson : 컴파일러를 통해 올바른 사용을 강요하는 재미있는 방법입니다. 공유해 주셔서 감사합니다! 향후 게시물에 대한 친절한 제안 : 주석 처리되지 않은 소스 코드 300 줄은 아마도 대부분의 사람들에게 소화하기에 다소 도움이 될 것입니다 (결국 코드를 ​​작성하는 것보다 읽기가 더 어렵습니다). 다시 감사합니다!
Christian Aichinger

17
@JarrodRoberson : 멋져요! 내가 의사 소통하고 싶었던 것 : 블로그 독자로서 진행중인 상황에 대한 간단한 텍스트 설명이 포함 된 50 줄의 예는 문맥없이 300 줄 이상을 도와줍니다.
Christian Aichinger

8
@ user177800 동의하지 않음-순수한 함수로 작성된 정적 메소드는 완벽합니다. 정적 함수가 문제가되는 상태를 변경하는 경우입니다.
Levi Fuller

641

아니요, 그러나이 스택 오버플로 답변에 설명 된대로 빌더 패턴을 사용할 수 있습니다 .

링크 된 답변에 설명 된 것처럼 빌더 패턴을 사용하면 다음과 같은 코드를 작성할 수 있습니다

Student s1 = new StudentBuilder().name("Eli").buildStudent();
Student s2 = new StudentBuilder()
                 .name("Spicoli")
                 .age(16)
                 .motto("Aloha, Mr Hand")
                 .buildStudent();

일부 필드는 기본값을 가질 수 있거나 그렇지 않은 경우 선택 사항입니다.


141
마지막으로 빌더 패턴의 2 페이지 미만의 훌륭한 예입니다.
nevvermind

14
그래도 궁금합니다. 빌더 패턴을 사용할 때 빌더 클래스가 필요한 이유는 무엇입니까? 나는 Student s1 = new Student (). name ( "Spicolo"). age (16) .motto ( "Aloha, Mr Hand);
ivanceras를

52
@ivanceras : 클래스에 필드가 필요한 경우와 관련이 있으며 유효하지 않은 상태에서 해당 클래스를 인스턴스화하지 않으려는 경우. 따라서 방금 말하면 Student s1 = new Student().age(16);이름이없는 학생이 남게 될 것입니다. 나쁘지 않으면 솔루션이 좋습니다.
Eli Courtwright

57
@ivanceras : 또 다른 이유는 생성 후 클래스를 변경할 수 없기 때문에 값을 변경하는 메소드를 원하지 않을 것입니다.
Jules

3
@ivanceras : 여러 인수와 유창한 초기화, 불변성을 제거하고 가장 중요한 것은 build () 메소드에서 도메인 객체의 유효성을 검사하는 느낌을 갖는 3 가지 이유로 빌더를 사용했습니다. 유효하지 않은 경우 객체 인스턴스를 만드는 이유는 무엇입니까? 위의 경우와 같은 팩토리 메소드 buildFreshman (), buildSenior () 등
Abhijeet Kushe

485

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. 널. 이전 접근법의 한계를 해결하기 위해 널값을 허용 한 후 메소드 본문에서 각 매개 변수를 분석 할 수 있습니다.

    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 Optional 클래스를 사용합니다.

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

    선택 사항은 호출자에게 메소드 계약을 명시 적으로 표시하지만, 그러한 서명이 너무 자세 할 수 있습니다.

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

     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 = (String)parameters.get("a");
        } else if (parameters.containsKey("b")) { 
            //... 
        }
        //...
    }
    
    foo(ImmutableMap.<String, Object>of(
        "a", "a",
        "b", 2, 
        "d", "value")); 

이러한 방법 중 하나를 결합하여 원하는 결과를 얻을 수 있습니다.


1
좋은 설명입니다. 이런 식으로 반환 값을 본 적이 없습니다. 5) 무엇을 return this합니까? 또한 FooBuilder().setA("a").build();(정의 적으로) 생성자가 먼저 호출 FooBuilder()되지 않고 값을 반환하지 .setA("a"):않습니까? 이것이 호출 될 기회를 얻지 못합니까?
Celeritas

3
@Celeritas return this는 메소드가 호출 된 동일한 오브젝트 (예 :)를 리턴합니다 FooBuilder. 이를 통해 하나의 명령문에서 동일한 오브젝트에 대해 작동하는 메소드를 연결할 수 있습니다 new FooBuilder().setA(..).setB(..).setC(..). 개별 메소드에서 각 메소드를 호출하는 것과는 달리
ADTC

2
@Celeritas new FooBuilder()는 메소드가 호출 된 FooBuilder오브젝트를 리턴합니다 setA. 으로 setB호출되지 않습니다, this.b기본 값을 유지합니다. 마지막 build으로이 FooBuilder객체 에서 메소드가 호출됩니다 . 이 build메서드 Foo는 변수로 설정된 객체를 만들어 반환 합니다 Foo foo. 것을 알 FooBuilder객체가 어떤 변수에 저장되지 않습니다.
ADTC

주석은 기본 매개 변수를 만드는데도 사용할 수 있으며 다형성 컬렉션에 필요할 때 가장 유용합니다. docs.oracle.com/javase/tutorial/java/annotations/declaring.html
Martin Spamer

1
두 가지 질문에 걸쳐 900 개가 넘는 답변이 동일한 답변에 찬성합니다. 감동합니다 : stackoverflow.com/questions/965690/java-optional-parameters/…
AdamMc331

256

안타깝게도


34
너무 슬프나요? 그렇게하면 잠재적으로 모호한 함수 서명이 생길 수 있습니다.
Trey

69
@Trey : 기본 매개 변수가있는 언어는 기능 과부하가 적기 때문에 그다지 매력적이지 않습니다. 모호하지 않습니다. Scala는 2.8에서이 기능을 추가했으며 호환성 문제로 인해 오버로드가 계속 유지되어 모호성 문제를 해결했습니다.
PhiLho

32
매개 변수 기본값으로 인해 함수 오버로드를 방지하는 방법을 알 수 없습니다. 예를 들어 C #은 재정의를 허용하고 기본 초기화도 허용합니다. 제한이 아닌 임의의 선택처럼 보입니다.
FlavorScape

51
예, 컴파일러가 추가적인 작업을하게하는 대신 라이브러리 사용자에게 편의를 제공하기 위해 모두 100000 개의 과부하를 작성하게하십시오. 좋은 생각.

28
@ user562566 : 나는 자바 프로젝트에 대한 작업을 할 때마다, 나는 그들이 하루에 생산하는 몇 줄의 코드 자바 개발자들에 의해 / 지불 측정하고 있다는 인상을 얻을
마크 K 코완

83

불행히도, 그렇습니다.

void MyParameterizedFunction(String param1, int param2, bool param3=false) {}

Java 1.5에서 다음과 같이 작성할 수 있습니다.

void MyParameterizedFunction(String param1, int param2, Boolean... params) {
    assert params.length <= 1;
    bool param3 = params.length > 0 ? params[0].booleanValue() : false;
}

그러나 컴파일러가 컴퓨터를 생성하는 것에 대한 느낌에 의존 해야하는지 여부

new Boolean[]{}

각 통화마다.

여러 기본 매개 변수의 경우 :

void MyParameterizedFunction(String param1, int param2, bool param3=false, int param4=42) {}

Java 1.5에서 다음과 같이 작성할 수 있습니다.

void MyParameterizedFunction(String param1, int param2, Object... p) {
    int l = p.length;
    assert l <= 2;
    assert l < 1 || Boolean.class.isInstance(p[0]);
    assert l < 2 || Integer.class.isInstance(p[1]);
    bool param3 = l > 0 && p[0] != null ? ((Boolean)p[0]).booleanValue() : false;
    int param4 = l > 1 && p[1] != null ? ((Integer)p[1]).intValue() : 42;
}

이는 C ++ 구문과 일치하며 매개 변수 목록 끝에 기본 매개 변수 만 허용합니다.

구문 외에도 전달 된 기본 매개 변수에 대한 런타임 유형 검사와 컴파일 중 C ++ 유형 검사에 차이가 있습니다.


14
영리하지만 varargs (...)는 최종 매개 변수에만 사용할 수 있으며 기본 매개 변수를 지원하는 언어가 제공하는 것보다 더 제한적입니다.
CurtainDog

6
즉, 영리하지만 약간의 혼란은 C ++ 버전과 비교
어딘가의 누군가가

5
Java는 C #과 다른 사람들이 허용하는 것처럼 선택적 기본 매개 변수가 필요합니다 ... 구문은 분명하며 가능한 모든 조합을 컴파일하여도 이것을 간단하게 구현할 수 있다고 가정합니다 ... 왜 언어에 추가하지 않은지 상상할 수 없습니다. 아직!
jwl

10
assert프로덕션 코드를 절대로 사용해서는 안됩니다 . 예외를 던지십시오.
Michael Dorst

5
-1 이것은 실제로 varargs가 아닙니다. 이것은 해킹입니다. 이 경우, 과부하를 사용하는 것이 훨씬 더 읽기 쉬워집니다 (불행하게도, 3 개의 추가 문자가 5 개의 추가 라인 소스보다 더 읽기 쉬우므로 ...). -그러나 Java는 기본 매개 변수를 지원하지 않습니다.
BrainSlugs83

38

아니요, 그러나 매우 쉽게 에뮬레이션 할 수 있습니다. C ++의 내용 :

public: void myFunction(int a, int b=5, string c="test") { ... }

Java에서는 오버로드 된 함수가됩니다.

public void myFunction(int a, int b, string c) { ... }

public void myFunction(int a, int b) {
    myFunction(a, b, "test");
}

public void myFunction(int a) {
    myFunction(a, 5);
}

이전에는 기본 매개 변수로 인해 함수 오버로드가 모호한 경우가 발생했습니다. 그것은 사실이 아닙니다. C ++의 경우에서 볼 수 있습니다. 예, 모호한 경우를 만들 수 있지만 이러한 문제는 쉽게 처리 할 수 ​​있습니다. C ++처럼 훨씬 간단한 언어를 원했기 때문에 Java로 개발되지 않았을 것입니다. 그러나 대부분의 사람들은 단순성 때문에 Java를 사용하지 않는다고 생각합니다.


8
C # 기본값 표기법의 주된 아이디어는이 상용구 코딩을 피하고 다수 대신에 하나의 생성자를 갖는 것입니다.
Kolya Ivankov

1
@ KolyaIvankov 나는 C #을 모르지만 추론이 동일한 C ++을 알고 있습니다. 더 나은 것이 무엇인지 모르겠지만 실제로 C ++ / C #의 경우 컴파일러에서 동일한 상용구 코드가 생성되고 최종 바이너리로 들어가고 있다고 생각합니다.
peterh-복원 모니카

5
모든 프로그래밍 언어는 (특히) 어셈블러 상용구를 피하는 수단입니다. 틀렸습니까? 문제는 편리한 기능을 제공하는지 여부입니다.
Kolya Ivankov

2
첫 번째 문장은 수사 학적 질문입니다. 두 번째 문장에서 "질문"이라는 단어는 첫 번째 수사 학적 질문과 관련이 없습니다.
Kolya Ivankov

1
좀 더 구체적으로 설명하자면 : 언어는 작성되는 내용을 제어 할 수있는 방식으로 프로그램을 작성할 수있는 도구이며, 컴파일은 기계에 원하는 것을 알려주는 방법입니다. 상용구를 피할 수있는 도구가 더 유용합니다. 실제로 gnavi는 C #에서 허용하는 보일러 플레이트 코드 유형을 정확하게 피할 수 있는지 물었습니다.
Kolya Ivankov

24

이 작업은 Scala에서 수행되며, JVM에서 실행되며 Java 프로그램과 호환됩니다. http://www.scala-lang.org/

class Foo(var prime: Boolean = false, val rib: String)  {}

58
하나의 공통된 기능을 갖지 못하도록 완전히 새로운 언어를 사용합니까?
om-nom-nom

8
@ om-nom-nom : Java가 존재하지 않아야합니다. 기능이 사용되지 않는다고 말하는 것은 아무도 필요하지 않다는 것입니다. Java가 발명되기 전에 널리 사용되지 않았다는 것은 Gosling이 설계를 시작해서는 안된다는 것을 의미합니다.
Val

28
단지이 대포와 새를 촬영처럼 말하는 @val
OM-NOM-NOM을

8
그것은 OP의 질문과 관련이 없습니다
destan

코 틀린에서도 작동합니다. 그리고 그루비. 그리고 C #. 그리고 자바 스크립트. 그리고 실제 사람들과 문제를 위해 만들어진 거의 모든 다른 언어들.
spyro

17

아니요 , 그러나 이것을 구현하는 가장 간단한 방법 은 다음과 같습니다.

public myParameterizedFunction(String param1, int param2, Boolean param3) {

    param3 = param3 == null ? false : param3;
}

public myParameterizedFunction(String param1, int param2) {

    this(param1, param2, false);
}

또는 삼항 연산자 대신 다음을 사용할 수 있습니다 if.

public myParameterizedFunction(String param1, int param2, Boolean param3) {

    if (param3 == null) {
        param3 = false;
    }
}

public myParameterizedFunction(String param1, int param2) {

    this(param1, param2, false);
}

2
예,이 방법은 다른 대안 중에서 가장 좋은 것 같습니다. 여전히 Java가 기본값을 채택하는 것이 좋습니다. Kotlin은 이것이 가능하다는 것을 보여 주었으므로 Oracle이 왜 현대에 들어오지 않았는지 확실하지 않으며 1990 년대처럼 Java를 계속 설계하고 있습니다. : D
shevy

13

여기에 명백한 내용이 있지만 "default"매개 변수를 직접 구현하지 않는 이유는 무엇입니까?

public class Foo() {
        public void func(String s){
                func(s, true);
        }
        public void func(String s, boolean b){
                //your code here
        }
}

기본적으로는

func("my string");

기본값을 사용하지 않으려면

func("my string", false);

11
포스터는이 (추악한) 패턴을 피할 수 있는지 물었습니다 ... ;-) 더 현대적인 언어 (c #, 스칼라와 같은)에서는 더 많은 코드 줄을 생성하는 여분의 과부하가 필요하지 않습니다. 어느 시점까지는 varargs를 사용할 수 있지만 (정적 int max (int ... array) {}), 매우 추악한 해결 방법입니다.
Offler

2
오버로드는 추악하지 않으며 서명이 다른 메소드 호출이 다른 기능을 수행 할 수있는 등 많은 이점이 있습니다. //This is better public class Foo() { /* This does something */ public void func(String s){ //do something } /* This does something else with b */ public void func(String s, boolean b){ // b was passed } } //Than this public class Foo() { /* This does something unless b = value, then it does something else */ public void func(String s, boolean b = value){ If (b){ // Do Something } else{ // Do something else } } }
Antony Booth

다른 행동을 원한다면 유일한 차이가 계산 등에 약간의 변화가있는 경우, 여러 서명을 작성하는 데 많은 노력이 필요합니다. 기본값은 어디에서 필요한지 이해하는 것입니다. 부족한 것이 "무용지물"요구 사항으로 분류되어서는 안됩니다.
Kapil

@Offler 기본 매개 변수는 "현대 언어"와 관련이 없습니다. 나는 20 년 전에 델파이에서 사용했고 아마도 터보 파스칼에 이미 존재했을 것입니다.
놀라운 1

나는 Offler에 동의하고 Antony Booth에 동의하지 않습니다. 나는 그것이 추한뿐만 아니라 상당히 비효율적이라는 것을 알았습니다. 루비 또는 파이썬과 같은 언어는 기본 매개 변수를 사용하는 것이 쉽지 않습니다. Java가 요구하는 것은 해결 방법을 찾고 사용하는 것입니다. 명시 적 검사 대 null은 명령 줄에서 호출 할 수 있기 때문에 가장 추악한 선택 인 것 같습니다 (아무 것도 제공하지 않고 제정신 변형을 처리하십시오). 연산자 오버로드 접근법은 ... 매우 장황하게 보입니다 (널 체크와 비교하여 최소 +3 줄, 코드가 더 복잡한 경우 더 많은 줄).
shevy

8

Scala가 언급 되었 듯이 Kotlin 도 언급 할 가치가 있습니다. Kotlin 함수에서 매개 변수는 기본값을 가질 수 있으며 다른 매개 변수를 참조 할 수도 있습니다.

fun read(b: Array<Byte>, off: Int = 0, len: Int = b.size) {
    ...
}

Scala와 마찬가지로 Kotlin은 JVM에서 실행되며 기존 Java 프로젝트에 쉽게 통합 될 수 있습니다.


6

아니.

스마트 기본값을 가진 객체를 전달하여 동일한 동작을 달성 할 수 있습니다. 그러나 다시 한 번 귀하의 사례가 무엇인지에 달려 있습니다.


5

아니요. 일반적으로 Java는 간단한 언어를 만들려고 시도했기 때문에 많은 구문 설탕이 없습니다.


26
좀 빠지는. 쓰라린 진실은 팀이 일정이 빡빡하고 구문 설탕을 먹을 시간이 없다는 것입니다. 왜 다른 사람은 것 const하고 goto있는 더 구현 키워드를 예약되지? -특히 const내가 몹시 그리워하는 부분입니다 – final대체물이 아니며 그것을 알고있었습니다. - 그리고 당신은 한 경우 의식이 구현 결코 결정 goto을 키워드를 예약 할 필요가 없습니다. - 그리고 나중에 자바 팀에 따라 라벨을 만들어 사기 breakcontinue파스칼과 같은 강력한으로 goto.
Martin

참조 - "단순는 객체 지향과 친숙한"참으로 설계 목표였다 oracle.com/technetwork/java/intro-141325.html
mikera

1
tomjen은 "아니오. 일반적으로 Java는 단순한 언어를 만들려고 시도했기 때문에 많은 구문 설탕을 가지고 있지 않다"고 말했다. C ++에서 불필요한 기능을 많이 제거하면 Java가 간단한 언어가되고 왜 Java에 가변 방식이 있습니까? 왜 varargs가 있습니까? 단순히 객체 배열을 대신 사용할 수 있다면 필요하지 않습니다. 따라서 varargs는 불필요하기 때문에 언어에서 제거 할 수 있습니다. 이것은 Java를 지금보다 더 단순하게 만듭니다. 내가 맞아? 각 메소드마다 이름이 무한하므로 오버로드도 제거 할 수 있습니다.

1
그래서 우리는 간단한 언어를 사용하고 실제 Java 프로젝트를 구문과 상용구로 바꾸는 봄과 물건을 얻었습니다. :-)
matanster

개발자가 상용구 코드와 복잡한 해결 방법을 강요하는 것은 "쉬운"이라는 단어를 이해하지 못합니다. myFunction (a, b = false, c = 3), 이것이 내가 쉽게 부르는 것입니다.
spyro

5

사용하는 대신:

void parameterizedMethod(String param1, int param2) {
    this(param1, param2, false);
}

void parameterizedMethod(String param1, int param2, boolean param3) {
    //use all three parameters here
}

단일 메소드를 사용하여 java의 선택적 기능을 활용할 수 있습니다.

void parameterizedMethod(String param1, int param2, @Nullable Boolean param3) {
    param3 = Optional.ofNullable(param3).orElse(false);
    //use all three parameters here
}

주요 차이점은 null입력 을 허용하려면 기본 Java 유형 대신 랩퍼 클래스를 사용해야한다는 것 입니다. Boolean대신에 boolean, Integer대신에 int등등.


4

지원되지 않지만 일부 구문 설탕과 함께 매개 변수 객체 패턴을 사용하는 것과 같은 몇 가지 옵션이 있습니다.

public class Foo() {
    private static class ParameterObject {
        int param1 = 1;
        String param2 = "";
    }

    public static void main(String[] args) {
        new Foo().myMethod(new ParameterObject() {{ param1 = 10; param2 = "bar";}});
    }

    private void myMethod(ParameterObject po) {
    }
}

이 샘플에서는 ParameterObject기본값으로 구성 하고 클래스 인스턴스 초기화 섹션에서이를 재정의합니다.{ param1 = 10; param2 = "bar";}


3

이 솔루션을 사용해보십시오 :

public int getScore(int score, Integer... bonus)
{
    if(bonus.length > 0)
    {
        return score + bonus[0];
    }

    return score;
}

3

Java 메소드 호출 빌더 를 사용 하여 기본값으로 빌더 를 자동으로 생성 할 수 있습니다 .

@GenerateMethodInvocationBuilder를 클래스 또는 인터페이스에 추가하고 @Default를 기본값을 원하는 메소드의 매개 변수에 추가하십시오. 어노테이션으로 지정한 기본값을 사용하여 컴파일시 빌더가 생성됩니다.

@GenerateMethodInvocationBuilder
public class CarService {
 public CarService() {
 }

 public String getCarsByFilter(//
   @Default("Color.BLUE") Color color, //
   @Default("new ProductionYear(2001)") ProductionYear productionYear,//
   @Default("Tomas") String owner//
 ) {
  return "Filtering... " + color + productionYear + owner;
 }
}

그런 다음 메소드를 호출 할 수 있습니다.

CarService instance = new CarService();
String carsByFilter = CarServiceGetCarsByFilterBuilder.getCarsByFilter()//
  .invoke(instance);

또는 기본값을 다른 것으로 설정하십시오.

CarService instance = new CarService();
String carsByFilter = CarServiceGetCarsByFilterBuilder.getCarsByFilter()//
  .withColor(Color.YELLOW)//
  .invoke(instance);

2

Java 8에서 작동 하는 https://stackoverflow.com/a/13864910/2323964에 대한 비슷한 접근 방식 은 기본 게터가있는 인터페이스를 사용하는 것입니다. 이것은 더 많은 공백이 될 것이지만 조롱 할 수 있으며 실제로 매개 변수에주의를 기울이려는 인스턴스가 많은 경우에 좋습니다.

public class Foo() {
    public interface Parameters {
        String getRequired();
        default int getOptionalInt(){ return 23; }
        default String getOptionalString(){ return "Skidoo"; }
    }

    public Foo(Parameters parameters){
        //...
    }

    public static void baz() {
        final Foo foo = new Foo(new Person() {
            @Override public String getRequired(){ return "blahblahblah"; }
            @Override public int getOptionalInt(){ return 43; }
        });
    }
}

2

나는 값을 반환하는 메소드로 이것을 사용하는 방법을 알아내는 데 꽤 많은 시간을 보냈으며, 지금까지 어떤 예제도 보지 못했지만 여기에 이것을 추가하는 것이 유용 할 것이라고 생각했습니다.

int foo(int a) {
    // do something with a
    return a;
}

int foo() {
    return foo(0); // here, 0 is a default value for a
}

1

이것은 내가 한 방법입니다 ... 정의 된 매개 변수에 대해 '선택적 인수'를 갖는 것만 큼 편리하지는 않지만 작업을 완료합니다.

public void postUserMessage(String s,boolean wipeClean)
{
    if(wipeClean)
    {
        userInformation.setText(s + "\n");
    }
    else
    {
        postUserMessage(s);
    }
}

public void postUserMessage(String s)
{
    userInformation.appendText(s + "\n");
}

문자열로 동일한 메소드 이름을 호출하거나 문자열 및 부울 값으로 호출 할 수 있습니다. 이 경우 wipeClean을 true로 설정하면 TextArea의 모든 텍스트가 제공된 문자열로 바뀝니다. wipeClean을 false로 설정하거나 모두 함께두면 제공된 텍스트가 TextArea에 추가됩니다.

또한 두 가지 방법으로 코드를 반복하지 않는다는 점에 주목하십시오. 부울이 추가 된 동일한 이름의 새 메소드를 작성하여 TextArea를 재설정 할 수있는 기능을 추가하는 것입니다.

필자는 Java가 매개 변수에 '선택적 인수'를 제공 한 경우보다 기본값을 코딩해야하기 때문에 실제로 이것이 더 깨끗하다고 ​​생각합니다.이 예에서는 그에 대해 걱정할 필요가 없습니다. 예, 수업에 또 다른 방법을 추가했지만 장기적으로 겸손한 견해로 읽는 것이 더 쉽습니다.


1

아니요, 그러나 우리는 기능 과부하의 형태로 대안이 있습니다.

매개 변수가 전달되지 않으면 호출

void operation(){

int a = 0;
int b = 0;

} 

"a"매개 변수가 전달 될 때 호출

void operation(int a){

int b = 0;
//code

} 

매개 변수 b가 전달 될 때 호출

void operation(int a , int b){
//code
} 

1

이와 같은 십여 가지 이상의 문제가 있습니다. 결국 정적 팩토리 패턴에 도달합니다 ... 암호 API를 참조하십시오. 설명하기는 어렵지만 다음과 같이 생각하십시오. 기본 또는 기타 생성자가있는 경우 중괄호를 넘어서 상태를 전파하는 유일한 방법은 부울 isValid입니다. (기본값 v 실패 생성자로 널과 함께) 또는 필드 사용자로부터 다시 가져올 때 정보가없는 예외를 발생시킵니다.

Code Correct는 저주를 받았으며 수천 줄의 생성자를 작성하고 필요한 작업을 수행합니다. 객체 구성에서 isValid를 사용한다는 것을 알 수 있습니다. 다시 말하면 2 줄 생성자입니다. 그러나 어떤 이유로 정적 팩토리 패턴으로 마이그레이션하고 있습니다. 메소드 호출에서 여전히 많은 작업을 수행 할 수 있지만 여전히 sync () 문제가 있지만 기본값은 더 나은 '대체'될 수 있습니다 (더 안전합니다)

여기에서해야 할 일은 null 문제를 기본값으로 표시하는 것입니다. string one = new String ( ""); 멤버 변수로, 생성자에 전달 된 문자열을 할당하기 전에 null을 확인합니다.

Java로 수행 된 원시, 성층권 컴퓨터 과학의 양이 매우 뛰어납니다.

C ++ 등에는 공급 업체 라이브러리가 있습니다. Java는 대규모 도구 상자로 인해 대규모 서버에서이를 능가 할 수 있습니다. 정적 초기화 블록을 연구하고 우리와 함께하십시오.



0

다음을 사용할 수 있습니다

public void mop(Integer x) {
  // Define default values
        x = x == null ? 200 : x;
}
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.