etc./StackOverFlow

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

청렴결백한 만능 재주꾼 2021. 12. 21. 22:08
반응형

질문자 :gnavi


다음 구조를 가진 일부 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가 이를 처리하는 방식입니다(즉, 기본 매개변수 대신 오버로딩 사용).

생성자 의 경우 오버로딩이 복잡해지면 Effective Java: 프로그래밍 언어 가이드의 항목 1 팁(생성자 대신 정적 팩토리 메서드 고려)을 참조하세요. 다른 방법의 경우 경우에 따라 이름을 바꾸거나 매개변수 개체를 사용하면 도움이 될 수 있습니다. 이것은 당신이 차별화하기 어려울 만큼 충분히 복잡할 때입니다. 확실한 경우는 숫자와 유형이 아닌 매개변수의 순서를 사용하여 구별해야 하는 경우입니다.


Kathy Van Stone

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

연결된 답변에 설명된 대로 빌더 패턴을 사용하면 다음과 같은 코드를 작성할 수 있습니다.

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

여기서 일부 필드는 기본값을 가지거나 선택 사항일 수 있습니다.


Eli Courtwright

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. 바르그.

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

    Optional은 호출자에 대해 메서드 계약을 명시적으로 만들지만 그러한 서명이 너무 장황하다는 것을 알 수 있습니다.

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

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


Vitalii Fedorenko

슬프게도, 아닙니다.


Rob H

불행히도, 그렇습니다.

 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++ 유형이 이를 검사하는 차이점이 있습니다.


ebelisle

아니요, 하지만 아주 쉽게 에뮬레이션할 수 있습니다. 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++의 경우를 볼 수 있습니다. 예, 아마도 모호한 경우를 만들 수 있지만 이러한 문제는 쉽게 처리할 수 있습니다. 그것은 단순히 Java로 개발되지 않았습니다. 아마도 제작자가 C++처럼 훨씬 더 간단한 언어를 원했기 때문일 것입니다. 그들이 옳다면 또 다른 질문입니다. 그러나 우리 대부분은 단순하기 때문에 그가 Java를 사용한다고 생각하지 않습니다.


peterh

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

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

lythic

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

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

simhumileco

사용하는 대신:

 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 , int 대신 Integer .


Viktor Taranenko

여기에서 분명히 말할 수 있지만 단순히 "기본" 매개변수를 직접 구현하지 않는 이유는 무엇입니까?

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

IronWolf

Scala가 언급된 것처럼 Kotlin 도 언급할 가치가 있습니다. Kotlin에서 함수 매개변수는 기본값도 가질 수 있으며 다른 매개변수를 참조할 수도 있습니다.

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

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


mrts

아니요. 일반적으로 Java는 단순한 언어를 만들려고 했기 때문에 구문상의 설탕이 많지 않습니다.


tomjen

아니요.

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


Santosh Gokak

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

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


hoaz

이 솔루션을 사용해 보세요.

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

Hamzeh Soboh

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

Tomas Bjerre

예를 들어 다른 언어와 마찬가지로 Java에서는 지원되지 않습니다. 코틀린.


Virendra Pal Singh

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

Novaterata

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

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

AAGD

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

 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가 매개변수에 대해 '선택적 인수'를 제공하는 것보다 이것이 기본 값 등에 대한 코드를 작성해야 하기 때문에 실제로 이것이 조금 더 깨끗하다고 생각합니다. 이 예에서는 그 어떤 것도 걱정할 필요가 없습니다. 예, 수업에 또 다른 방법을 추가했지만 내 겸손한 의견으로는 장기적으로 더 읽기 쉽습니다.


Michael Sims

아니요, 하지만 함수 오버로딩의 형태로 대안이 있습니다.

전달된 매개변수가 없을 때 호출됨

 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 }

Umair Khalid

이와 같은 6가지 이상의 문제가 있으며 결국에는 정적 팩토리 패턴에 도달하게 됩니다. 이에 대한 암호화 API를 참조하십시오. 정렬은 설명하기 어렵지만 다음과 같이 생각하십시오. 기본 생성자이든 아니든 생성자가 있는 경우 중괄호를 넘어 상태를 전파하는 유일한 방법은 부울 isValid를 갖는 것입니다. (기본값으로 null과 함께 v failed 생성자) 또는 필드 사용자로부터 다시 가져올 때 정보를 제공하지 않는 예외를 throw합니다.

Code Correct 젠장, 나는 수천 개의 라인 생성자를 작성하고 필요한 것을 수행합니다. 객체 생성 시 isValid를 사용하는 것을 발견했습니다. 즉, 두 줄 생성자입니다. 하지만 어떤 이유로 정적 팩토리 패턴으로 마이그레이션하고 있습니다. 메서드 호출에서 여전히 sync() 문제가 있지만 기본값이 더 나은(더 안전한) '대체'될 수 있는 경우 많은 작업을 수행할 수 있는 것 같습니다.

여기서 우리가 해야 할 일은 null을 기본값으로 사용하는 문제를 해결하는 것입니다. String one=new String(""); 멤버 변수로 생성자에 전달된 문자열을 할당하기 전에 null 검사를 수행합니다.

Java에서 수행된 원시 성층권 컴퓨터 과학의 양은 매우 놀랍습니다.

C++ 등에는 공급업체 라이브러리가 있습니다. Java는 방대한 도구 상자로 인해 대규모 서버에서 이를 능가할 수 있습니다. 정적 이니셜라이저 블록을 연구하고 저희와 함께 하세요.


Nicholas Jordan

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에서


Inês Gomes

null 을 사용하여 수동으로 확인할 수 있습니다.

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

그러나 과부하 또는 정적 팩토리와 같은 다른 것을 사용하는 것이 좋습니다. 이 문제를 피할 수는 있지만 예기치 않은 행동으로 이어질 수 있습니다. 예를 들어 코드에 오류가 있어서 부울 값을 절대 얻지 못할 수 있습니다. NullPointerException 이 발생하지 않습니다. 대신 false로 설정된 것처럼 보일 것이므로 디버그하기가 매우 혼란스러울 수 있습니다.


Tobias

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

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

Sobhit Sharma

출처 : http:www.stackoverflow.com/questions/997482/does-java-support-default-parameter-values

반응형