ฉันจะใช้พารามิเตอร์ทางเลือกใน Java ได้อย่างไร ข้อมูลจำเพาะอะไรรองรับพารามิเตอร์ทางเลือก
ฉันจะใช้พารามิเตอร์ทางเลือกใน Java ได้อย่างไร ข้อมูลจำเพาะอะไรรองรับพารามิเตอร์ทางเลือก
คำตอบ:
varargs สามารถทำได้ (ในทาง) นอกเหนือจากนั้นต้องระบุตัวแปรทั้งหมดในการประกาศวิธีการ หากคุณต้องการให้ตัวแปรเป็นทางเลือกคุณสามารถโหลดเมธอดมากเกินไปโดยใช้ลายเซ็นซึ่งไม่ต้องการพารามิเตอร์
private boolean defaultOptionalFlagValue = true;
public void doSomething(boolean optionalFlag) {
...
}
public void doSomething() {
doSomething(defaultOptionalFlagValue);
}
มีหลายวิธีในการจำลองพารามิเตอร์ทางเลือกใน 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");
ข้อเสียเปรียบหลักของวิธีนี้คือหากพารามิเตอร์ทางเลือกต่างประเภทกันคุณจะสูญเสียการตรวจสอบประเภทคงที่ นอกจากนี้หากแต่ละพารามิเตอร์มีความหมายแตกต่างกันคุณต้องใช้วิธีแยกแยะความแตกต่าง
nulls ในการจัดการข้อ จำกัด ของวิธีการก่อนหน้านี้คุณสามารถอนุญาตให้มีค่า Null และวิเคราะห์แต่ละพารามิเตอร์ในเมธอดเนื้อหา:
void foo(String a, Integer b, Integer c) {
b = b != null ? b : 0;
c = c != null ? c : 0;
//...
}
foo("a", null, 2);
ตอนนี้ต้องระบุค่าอาร์กิวเมนต์ทั้งหมด แต่ค่าเริ่มต้นอาจเป็นโมฆะ
คลาสตัวเลือก วิธีนี้คล้ายกับ nulls แต่ใช้ 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());
ตัวเลือกทำให้สัญญาวิธีการที่ชัดเจนสำหรับผู้โทร แต่อย่างใดอย่างหนึ่งอาจพบว่าลายเซ็นดังกล่าวเกินไป verbose
อัปเดต: Java 8 รวมคลาสjava.util.Optional
เอาต์เอาไว้แล้วดังนั้นจึงไม่จำเป็นต้องใช้ฝรั่งเนื่องจากเหตุผลนี้ใน Java 8 ชื่อวิธีการนั้นแตกต่างกันเล็กน้อย
รูปแบบการสร้าง รูปแบบตัวสร้างถูกใช้สำหรับตัวสร้างและนำไปใช้โดยแนะนำตัวสร้างคลาสแยก:
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 = (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"));
โปรดทราบว่าคุณสามารถรวมวิธีการเหล่านี้เพื่อให้ได้ผลลัพธ์ที่ต้องการ
a
ตัวแปรของคุณจะเป็นสตริง (cast ถูกต้อง)
Optional
เป็นพารามิเตอร์ในหนึ่งในตัวเลือก แต่คำตอบนี้ดีมาก
มีพารามิเตอร์ทางเลือกพร้อม Java 5.0 เพียงประกาศฟังก์ชั่นของคุณเช่นนี้:
public void doSomething(boolean... optionalFlag) {
//default to "false"
//boolean flag = (optionalFlag.length >= 1) ? optionalFlag[0] : false;
}
คุณสามารถโทรหาด้วยdoSomething();
หรือdoSomething(true);
ตอนนี้
doSomething() { doSomething(true); }
ไม่มีอาร์เรย์ที่จะจัดการกับไม่มีความกำกวม
คุณสามารถใช้สิ่งนี้:
public void addError(String path, String key, Object... params) {
}
params
ตัวแปรเป็นตัวเลือก มันจะถือว่าเป็นอาร์เรย์ที่ไม่มีค่าของวัตถุ
แปลกฉันไม่พบอะไรเกี่ยวกับเรื่องนี้ในเอกสาร แต่มันใช้งานได้!
นี่คือ "ใหม่" ใน Java 1.5 ขึ้นไป (ไม่รองรับใน Java 1.4 หรือเก่ากว่า)
ฉันเห็นผู้ใช้ bhoot พูดถึงเรื่องนี้ด้านล่าง
น่าเสียดายที่ 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 และการโอเวอร์โหลด ตัวเลือกอื่นคือรูปแบบตัวสร้างซึ่งจะมีลักษณะดังนี้:
MyObject my = new MyObjectBuilder().setParam1(value)
.setParam3(otherValue)
.setParam6(thirdValue)
.build();
แม้ว่ารูปแบบนั้นจะเหมาะสมที่สุดเมื่อคุณต้องการพารามิเตอร์ทางเลือกในตัวสร้าง
ใน JDK> 1.5 คุณสามารถใช้มันได้
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);
}
}
}
คุณสามารถทำสิ่งต่าง ๆ โดยใช้วิธีการมากไปเช่นนี้
public void load(String name){ }
public void load(String name,int age){}
นอกจากนี้คุณสามารถใช้คำอธิบายประกอบ @Nullable
public void load(@Nullable String name,int age){}
เพียงแค่ส่งค่า null เป็นพารามิเตอร์แรก
หากคุณผ่านตัวแปรประเภทเดียวกันคุณสามารถใช้สิ่งนี้
public void load(String name...){}
ใช้ สามจุด :
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);
(ขึ้นอยู่กับคำตอบของ @ VitaliiFedorenko)
การบรรทุกเกินพิกัดเป็นเรื่องปกติ แต่ถ้ามีตัวแปรจำนวนมากที่ต้องการค่าเริ่มต้นคุณจะพบกับ:
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) { }
ดังนั้นฉันขอแนะนำให้ใช้ Variable Argument ที่จัดทำโดย Java นี่คือลิงค์สำหรับคำอธิบาย
คุณสามารถใช้คลาสที่ทำงานคล้ายกับตัวสร้างเพื่อเก็บค่าทางเลือกของคุณเช่นนี้
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);
}
ใช้เหมือน
foo(o -> o.setSomeString("something").setSomeInt(5));
ผลผลิตคือ
someString = something, someInt = 5
หากต้องการข้ามค่าที่ไม่จำเป็นทั้งหมดที่คุณต้องเรียกว่าเป็นแบบที่foo(o -> {});
คุณชอบหรือคุณต้องการคุณสามารถสร้างfoo()
วิธีที่สองที่ไม่ใช้พารามิเตอร์ทางเลือก
การใช้วิธีการนี้คุณสามารถระบุค่าที่เป็นตัวเลือกในลำดับใดก็ได้โดยไม่ต้องมีความกำกวม นอกจากนี้คุณยังสามารถมีพารามิเตอร์ของคลาสที่แตกต่างจาก varargs วิธีนี้จะดียิ่งขึ้นถ้าคุณสามารถใช้คำอธิบายประกอบและการสร้างรหัสเพื่อสร้างคลาสตัวเลือก
Java ตอนนี้สนับสนุนตัวเลือกใน 1.8 ฉันติดอยู่กับการเขียนโปรแกรมบน Android ดังนั้นฉันใช้ nulls จนกว่าฉันจะ refactor รหัสเพื่อใช้ประเภทตัวเลือก
Object canBeNull() {
if (blah) {
return new Object();
} else {
return null;
}
}
Object optionalObject = canBeNull();
if (optionalObject != null) {
// new object returned
} else {
// no new object returned
}
อาร์กิวเมนต์เริ่มต้นไม่สามารถใช้ใน Java เราใช้ C #, C ++ และ Python ได้ที่ไหน
ใน Java เราต้องใช้ 2 เมธอด (ฟังก์ชั่น) แทนหนึ่งด้วยพารามิเตอร์เริ่มต้น
ตัวอย่าง:
Stash(int size);
Stash(int size, int initQuantity);
นี่เป็นคำถามเก่า ๆ ที่อาจจะเกิดขึ้นก่อนที่จะมีการแนะนำตัวเลือกประเภทจริง แต่วันนี้คุณสามารถพิจารณาบางสิ่ง: - ใช้วิธีการมากไป - ใช้ตัวเลือกชนิดที่มีข้อดีของการหลีกเลี่ยงการผ่าน NULLs จาก lib บุคคลที่สามเช่น Guava ของ Google การใช้ทางเลือกเป็นพารามิเตอร์ / อาร์กิวเมนต์สามารถพิจารณาได้ว่าเป็นการใช้งานเกินวัตถุประสงค์ตามวัตถุประสงค์หลักคือใช้เป็นเวลาส่งคืน
Ref: https://itcodehub.blogspot.com/2019/06/using-optional-type-in-java.html
เราสามารถสร้างพารามิเตอร์ทางเลือกโดยวิธีการบรรทุกเกินพิกัดหรือใช้ DataType ...
| * | วิธีการบรรทุกเกินพิกัด:
RetDataType NameFnc(int NamePsgVar)
{
// |* Code Todo *|
return RetVar;
}
RetDataType NameFnc(String NamePsgVar)
{
// |* Code Todo *|
return RetVar;
}
RetDataType NameFnc(int NamePsgVar1, String NamePsgVar2)
{
// |* Code Todo *|
return RetVar;
}
วิธีที่ง่ายที่สุดคือ
| * | DataType ... สามารถเป็นพารามิเตอร์เสริม
RetDataType NameFnc(int NamePsgVar, String... stringOpnPsgVar)
{
if(stringOpnPsgVar.length == 0) stringOpnPsgVar = DefaultValue;
// |* Code Todo *|
return RetVar;
}
RetDtaTyp
... อย่างจริงจัง? เป็นRetDataType
เรื่องยากที่จะพิมพ์ออกมา?
หากคุณกำลังวางแผนที่จะใช้อินเตอร์เฟซที่มีพารามิเตอร์หลายหนึ่งสามารถใช้ต่อไปนี้รูปแบบโครงสร้างและดำเนินการหรือแทนที่การใช้ - วิธีขึ้นอยู่กับความต้องการของคุณ
public abstract class Invoker<T> {
public T apply() {
return apply(null);
}
public abstract T apply(Object... params);
}
หากเป็นจุดสิ้นสุดของ API วิธีที่สวยงามคือการใช้คำอธิบายประกอบ "Spring":
@GetMapping("/api/foos")
@ResponseBody
public String getFoos(@RequestParam(required = false, defaultValue = "hello") String id) {
return innerFunc(id);
}
โปรดสังเกตว่าในกรณีนี้ innerFunc จะต้องการตัวแปรและเนื่องจากไม่ใช่จุดปลาย api จึงไม่สามารถใช้คำอธิบายประกอบ Spring นี้เพื่อให้เป็นตัวเลือก การอ้างอิง: https://www.baeldung.com/spring-request-param