다음과 같은 구조를 가진 일부 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가 이런 종류의 구문을 지원합니까? 이 두 단계 구문이 바람직한 이유가 있습니까?
답변
아니오, 발견 한 구조는 Java가 Java를 처리하는 방식입니다 (즉, 기본 매개 변수 대신 오버로드 사용).
생성자 가 오버로드가 복잡 해지는 경우 효과적인 Java : 프로그래밍 언어 안내서의 항목 1 팁 (생성자 대신 정적 팩토리 메소드 고려)을 참조하십시오. 다른 방법의 경우 일부 사례의 이름을 바꾸거나 매개 변수 객체를 사용하면 도움이 될 수 있습니다. 이것은 차별화가 어려운 복잡성이 충분할 때입니다. 명확한 경우는 숫자와 유형뿐만 아니라 매개 변수의 순서를 사용하여 차별화해야하는 경우입니다.
답변
아니요, 그러나이 스택 오버플로 답변에 설명 된대로 빌더 패턴을 사용할 수 있습니다 .
링크 된 답변에 설명 된 것처럼 빌더 패턴을 사용하면 다음과 같은 코드를 작성할 수 있습니다
Student s1 = new StudentBuilder().name("Eli").buildStudent();
Student s2 = new StudentBuilder()
.name("Spicoli")
.age(16)
.motto("Aloha, Mr Hand")
.buildStudent();
일부 필드는 기본값을 가질 수 있거나 그렇지 않은 경우 선택 사항입니다.
답변
Java에서 기본 매개 변수를 시뮬레이션하는 몇 가지 방법이 있습니다.
-
메서드 오버로딩
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");
이 방법의 한계 중 하나는 동일한 유형의 두 개의 선택적 매개 변수가 있고 작동하지 않을 경우 작동하지 않는다는 것입니다.
-
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");
이 방법의 주요 단점은 선택적 매개 변수가 다른 유형 인 경우 정적 유형 검사를 잃는다는 것입니다. 또한 각 매개 변수의 의미가 다르면이를 구별 할 방법이 필요합니다.
-
널. 이전 접근법의 한계를 해결하기 위해 널값을 허용 한 후 메소드 본문에서 각 매개 변수를 분석 할 수 있습니다.
void foo(String a, Integer b, Integer c) { b = b != null ? b : 0; c = c != null ? c : 0; //... } foo("a", null, 2);
이제 모든 인수 값을 제공해야하지만 기본 값은 null 일 수 있습니다.
-
선택적 수업. 이 방법은 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());
선택 사항은 호출자에게 메소드 계약을 명시 적으로 표시하지만, 그러한 서명이 너무 자세 할 수 있습니다.
-
빌더 패턴. 빌더 패턴은 생성자에 사용되며 별도의 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();
-
지도. 매개 변수 수가 너무 많고 대부분의 기본값이 일반적으로 사용되는 경우 메소드 인수를 해당 이름 / 값의 맵으로 전달할 수 있습니다.
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 ++의 내용 :
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를 사용하지 않는다고 생각합니다.
답변
이 작업은 Scala에서 수행되며, JVM에서 실행되며 Java 프로그램과 호환됩니다.
http://www.scala-lang.org/
즉
class Foo(var prime: Boolean = false, val rib: String) {}