อะไรคือวิธีที่ถูกต้องในการส่งคืนVoid
ประเภทเมื่อไม่ใช่แบบดั้งเดิม เช่น. ปัจจุบันฉันใช้ null ดังต่อไปนี้
interface B<E>{ E method(); }
class A implements B<Void>{
public Void method(){
// do something
return null;
}
}
อะไรคือวิธีที่ถูกต้องในการส่งคืนVoid
ประเภทเมื่อไม่ใช่แบบดั้งเดิม เช่น. ปัจจุบันฉันใช้ null ดังต่อไปนี้
interface B<E>{ E method(); }
class A implements B<Void>{
public Void method(){
// do something
return null;
}
}
คำตอบ:
คลาส Void เป็นคลาสตัวยึดที่ไม่คงที่เพื่อเก็บการอ้างอิงไปยังอ็อบเจ็กต์คลาสที่เป็นตัวแทนของคีย์เวิร์ด Java เป็นโมฆะ
ดังนั้นสิ่งต่อไปนี้จะเพียงพอ:
Object
และส่งคืนnew Object()
หรือnull
Void
และการส่งคืนnull
NullObject
ของคุณคุณไม่สามารถทำให้วิธีนี้void
และสิ่งอื่น ๆ ผลตอบแทนบางสิ่งบางอย่าง เนื่องจากสิ่งนั้นถูกละเว้นคุณสามารถส่งคืนทุกอย่างได้
return (Void)null;
Java 8 ได้เปิดตัวคลาสใหม่Optional<T>
ที่สามารถใช้ได้ในกรณีเช่นนี้ ในการใช้งานคุณต้องแก้ไขโค้ดของคุณเล็กน้อยดังนี้:
interface B<E>{ Optional<E> method(); }
class A implements B<Void>{
public Optional<Void> method(){
// do something
return Optional.empty();
}
}
สิ่งนี้ช่วยให้คุณมั่นใจได้ว่าคุณจะได้รับค่าตอบแทนที่ไม่เป็นค่าว่างจากวิธีการของคุณเสมอแม้ว่าจะไม่มีสิ่งใดที่จะส่งคืน ซึ่งมีประสิทธิภาพเป็นพิเศษเมื่อใช้ร่วมกับเครื่องมือที่ตรวจจับว่าเมื่อnull
ใดที่สามารถส่งคืนได้หรือไม่ได้เช่น Eclipse @NonNull
และ@Nullable
คำอธิบายประกอบ
Optional<Void>
นั้นไม่จำเป็นด้วยเหตุผลเดียวกับที่คุณให้คุณจะได้รับOptional<Void>
สิ่งนั้นว่างเปล่าเสมอดังนั้นวิธีการอื่น ๆ ทั้งหมดจึงไม่มีจุดหมาย นี่คือสิ่งที่ตรงกันข้ามกับเหตุผลที่ควรใช้ค่าที่เป็นทางเลือก คุณใช้มันเพราะมันอาจมีหรือไม่มีค่าก็ได้ นอกจากนี้คอมไพลเลอร์ไม่สามารถบังคับใช้ว่าmethod()
ดำเนินการอย่างถูกต้อง return Optional.of(null)
นี้จะล้มเหลวที่รันไทม์:
หากคุณไม่ต้องการอะไรเป็นประเภทของคุณคุณสามารถใช้โมฆะได้ สามารถใช้สำหรับการใช้งานฟังก์ชันหรือการดำเนินการ จากนั้นคุณสามารถทำสิ่งนี้:
interface Action<T> {
public T execute();
}
abstract class VoidAction implements Action<Void> {
public Void execute() {
executeInternal();
return null;
}
abstract void executeInternal();
}
หรือคุณสามารถละเว้นคลาสนามธรรมและทำ return null ในทุกการกระทำที่ไม่ต้องการค่าตอบแทนด้วยตัวคุณเอง
จากนั้นคุณสามารถใช้การกระทำเหล่านั้นดังนี้:
กำหนดวิธีการ
private static <T> T executeAction(Action<T> action) {
return action.execute();
}
เรียกได้ว่าชอบ
String result = executeAction(new Action<String>() {
@Override
public String execute() {
//code here
return "Return me!";
}
});
หรือสำหรับการกระทำที่เป็นโมฆะ (โปรดทราบว่าคุณไม่ได้กำหนดผลลัพธ์ให้กับสิ่งใดเลย)
executeAction(new VoidAction() {
@Override
public void executeInternal() {
//code here
}
});
เพื่อประโยชน์ของมันแน่นอนว่ามีความเป็นไปได้ที่จะสร้างVoid
อินสแตนซ์โดยใช้การสะท้อน:
interface B<E>{ E method(); }
class A implements B<Void>{
public Void method(){
// do something
try {
Constructor<Void> voidConstructor = Void.class.getDeclaredConstructor();
voidConstructor.setAccessible(true);
return voidConstructor.newInstance();
} catch (Exception ex) {
// Rethrow, or return null, or whatever.
}
}
}
คุณอาจจะไม่ทำเช่นนั้นในการผลิต
ไม่มีประเภททั่วไปที่จะบอกคอมไพเลอร์ว่าเมธอดไม่คืนค่าอะไรเลย
ฉันเชื่อว่าหลักการคือการใช้ Object เมื่อสืบทอดเป็นพารามิเตอร์ประเภท
หรือ
เผยแพร่พารามิเตอร์ type ขึ้นจากนั้นให้ผู้ใช้ในคลาสของคุณสร้างอินสแตนซ์โดยใช้ Object และกำหนดอ็อบเจ็กต์ให้กับตัวแปรที่พิมพ์โดยใช้ type-wildcard ?
:
interface B<E>{ E method(); }
class A<T> implements B<T>{
public T method(){
// do something
return null;
}
}
A<?> a = new A<Object>();
A<?>
ๆ method()