programing

Java는 디폴트 파라미터 값을 지원합니까?

prostudy 2022. 8. 29. 21:34
반응형

Java는 디폴트 파라미터 값을 지원합니까?

다음과 같은 구조를 가진 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는 이러한 구문을 지원합니까?이 2단계 구문이 바람직한 이유가 있습니까?

아니요, 찾은 구조는 Java가 처리하는 방식입니다(기본 파라미터 대신 오버로드 사용).

컨스트럭터에 대해서는 오버로드가 복잡해지는 경우 효과적인 Java: Programming Language Guide의 Item 1 힌트(컨스트럭터 대신 정적 팩토리 메서드 고려)를 참조하십시오.다른 방법으로는 일부 케이스의 이름을 변경하거나 파라미터 개체를 사용하면 도움이 됩니다.이 때 복잡성이 충분하기 때문에 구별이 어렵습니다.확실한 경우는 숫자와 유형뿐만 아니라 파라미터의 순서를 사용하여 구별해야 하는 경우입니다.

아니요, 하지만 이 스택 오버플로 응답에 설명대로 Builder 패턴을 사용할 수 있습니다.

링크된 답변에서 설명한 바와 같이 Builder Pattern을 사용하면 다음과 같은 코드를 작성할 수 있습니다.

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

일부 필드에는 기본값을 설정할 수도 있고 옵션일 수도 있습니다.

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개 있고 그 중 하나를 생략할 수 있는 경우에는 동작하지 않는다는 것입니다.

  2. 바라그스

    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. 이전 접근법의 한계를 해결하기 위해 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 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")); 
    

바람직한 결과를 얻기 위해 이러한 방법을 조합할 수 있습니다.

슬프게도, 아닙니다.

아쉽게도 그렇습니다.

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++ 구문에서는 파라미터 목록의 끝에 디폴트 파라미터만 사용할 수 있습니다.

구문 이외에도 실행 시간 유형에서 전달된 기본 파라미터가 있는지 확인하고 C++ 유형에서 컴파일 중에 해당 파라미터를 확인하는 차이가 있습니다.

아뇨, 하지만 아주 쉽게 따라 할 수 있어요.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를 사용하는 이유는 단순하기 때문이라고 생각하지 않습니다.

이는 JVM에서 실행되며 Java 프로그램과 호환되는 Scala에서 수행할 수 있습니다.http://www.scala-lang.org/

예.

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

사용하는 대신:

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
}

은 "Java"를 허용하려면 입니다.nulldiscloss.discloss.Booleanboolean,Integerint기타 등등.

아니요, 하지만 가장 간단한 구현 방법은 다음과 같습니다.

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

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

public myParameterizedFunction(String param1, int param2) {

    this(param1, param2, false);
}

또는 3진 연산자 대신if:

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

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

public myParameterizedFunction(String param1, int param2) {

    this(param1, param2, false);
}

여기서 당연한 말을 하고 있을 수도 있지만, "기본값" 파라미터를 직접 구현해 보는 것은 어떨까요?

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);

스칼라가 언급했듯이, 코틀린도 언급할 가치가 있다.Kotlin의 함수 파라미터는 기본값을 가질 수 있으며 다른 파라미터도 참조할 수 있습니다.

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

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

아니요. 자바어에는 통사설탕이 별로 없어요. 왜냐하면 그들은 간단한 언어를 만들려고 했기 때문이죠.

아니요.

스마트 기본값을 가진 개체를 전달하여 동일한 동작을 수행할 수 있습니다.하지만 다시 한 번 말씀드리지만, 어떤 사건이 다가오느냐에 따라 다르죠.

java에서는 ex의 다른 언어처럼 지원되지 않습니다.코틀린.

하실 수 .null:

public MyParameterizedFunction(String param1, int param2, boolean param3)
{
    if(param3 == null) {
        param3 = false;
    }
}

하지만 과부하나 정적 공장 같은 다른 것을 사용하는 것이 좋습니다.어쩌면 당신은 이 일을 피할 수 있을지 모르지만, 예상치 못한 행동으로 이어질 수 있습니다.예를 들어 코드에 오류가 있어서 부울 값을 얻지 못할 수 있습니다., 여러분은 , 신, 신, 신, 신, 신, 습, 습이 나오지 않습니다.NullPointerException대신 false로 설정되어 있는 것처럼 보여 디버깅이 매우 혼란스러울 수 있습니다.

지원되지 않지만 파라미터 오브젝트 패턴과 몇 가지 구문 sugar를 함께 사용하는 등 몇 가지 옵션이 몇 가지 옵션이 있습니다.

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[ Instance ]섹션에서 .{ param1 = 10; param2 = "bar";}

다음 솔루션을 사용해 보십시오.

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

    return score;
}

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

그냥 @GenerateMethod 추가클래스 또는 인터페이스에 대한 Invocation Builder 및 기본값인 메서드의 파라미터에 대한 @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);

Java 8에서 동작하는 https://stackoverflow.com/a/13864910/2323964과 같은 접근방식은 기본 getter를 가진 인터페이스를 사용하는 것입니다.이 방법은 좀 더 빈칸이 많지만 모킹이 가능하며 실제로 파라미터에 주의를 환기시키고 싶은 인스턴스가 많을 때 유용합니다.

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; }
        });
    }
}

값을 반환하는 메서드에서 이 기능을 사용하는 방법을 알아보는 데 오랜 시간이 걸렸지만, 지금까지 예시를 보지 못했습니다. 여기에 이 기능을 추가하면 도움이 될 것 같습니다.

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

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

이렇게 해서...정의된 파라미터에 대해 '옵션 인수'를 사용하는 것만큼 편리하지는 않지만 작업을 수행할 수 있습니다.

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 내의 모든 텍스트가 지정된 문자열로 대체됩니다.weepClean을 false로 설정하거나 모두 생략하면 제공된 텍스트가 TextArea에 추가됩니다.

또한 두 가지 메서드에서 코드를 반복하는 것이 아니라 추가된 부울로만 동일한 이름을 가진 새 메서드를 생성하여 TextArea를 리셋할 수 있는 기능을 추가할 뿐입니다.

이것은 Java가 파라미터에 대해 '옵션 인수'를 제공한 경우보다 조금 더 명확하다고 생각합니다.기본값 등을 코드화할 필요가 있기 때문입니다.이 예에서는 그런 걱정은 하지 않아도 됩니다.네, 저는 수업에 다른 방법을 추가했지만, 제 겸손한 의견으로는 장기적으로 읽기가 더 쉬워요.

아니요, 하지만 함수의 과부하 형태에 대한 대안이 있습니다.

매개 변수가 전달되지 않을 때 호출됨

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
} 

이와 같은 문제가 6개 이상 있습니다.결국, 정적인 공장 패턴에 도달합니다.crypto API 를 참조해 주세요.설명하기는 어렵지만 다음과 같이 생각해 주십시오.기본값 또는 그 외의 컨스트럭터가 있는 경우, 컬리 괄호를 넘어 상태를 전파하는 유일한 방법은 boolean isValid;(null과 함께 기본값 v failed constructor) 또는 필드 사용자로부터 반환할 때 전혀 도움이 되지 않는 예외를 던지는 것입니다.

코드 수정 젠장, 난 수천 개의 라인 컨스트럭터를 쓰고 내가 필요한 걸 해.isValid at object construction(즉, 2라인 컨스트럭터)을 사용하고 있는 것을 알 수 있습니다만, 어떤 이유에서인지, 저는 정적 공장 패턴으로 이행하고 있습니다.메서드 호출에서는 아직 sync() 문제가 있지만 디폴트는 더 나은 대체가 가능합니다(안전합니다).

여기서 필요한 것은 null의 문제를 string 1=new String("") 디폴트값으로 처리하고 멤버 변수로 null을 체크한 후 컨스트럭터에 전달된 문자열을 할당하는 것입니다.

자바에서 행해진 성층권 컴퓨터 과학은 놀라울 정도로 많습니다.

C++ 등에는 벤더 lib가 있습니다.Java는 거대한 툴박스이기 때문에 대규모 서버에서 이를 능가할 수 있습니다.정적 이니셜라이저 블록을 연구하고 정신 차려요

한 가지 아이디어는String... args

public class Sample {
   void demoMethod(String... args) {
      for (String arg : args) {
         System.out.println(arg);
      }
   }
   public static void main(String args[] ) {
      new Sample().demoMethod("ram", "rahim", "robert");
      new Sample().demoMethod("krishna", "kasyap");
      new Sample().demoMethod();
   }
}

산출량

ram
rahim
robert
krishna
kasyap

https://www.tutorialspoint.com/Does-Java-support-default-parameter-values-for-a-method 에서

메서드와 같은 컨스트럭터

static void popuping() {
    popuping("message", "title");
}
static void popuping(String message) {
    popuping(message, "title");
}
static void popuping(String message, String title){
    JOptionPane.showMessageDialog(null, message,
            title, JOptionPane.INFORMATION_MESSAGE);
}

다음을 사용할 수 있습니다.

public void mop(Integer x) {
  // Define default values
        x = x == null ? 200 : x;
}

언급URL : https://stackoverflow.com/questions/997482/does-java-support-default-parameter-values

반응형