ไวลด์การ์ดขอบเขตล่าง
? super T สำหรับผู้บริโภคข้อมูล
ไวลด์การ์ดขอบเขตล่าง เป็นบทเรียน Java Academy ฟรีบน CoddyKit นี่คือบทเรียนที่ 2 จากทั้งหมด 4 บทเรียน คุณสามารถอ่านบทเรียนทั้งหมดด้านล่างฟรี — จากนั้นลองปฏิบัติด้วยตัวคุณเองในเบราว์เซอร์พร้อมตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7 บทเรียนนี้เป็นส่วนหนึ่งของเส้นทางการเรียน Java Academy และความก้าวหน้าของคุณจะซิงค์ข้ามเว็บและแอป CoddyKit คอร์ส Java Academy มีบทเรียนทั้งหมด 4 บทเรียน
ไวลด์การ์ดที่มีขอบเขตล่าง
? super T คือไวลด์การ์ดที่มีขอบเขตล่าง หมายถึง “ชนิดข้อมูลบางชนิดที่ไม่ทราบแน่ชัด ซึ่งเป็น T หรือชนิดข้อมูลที่อยู่เหนือกว่า T”
List<? super Integer> อาจอ้างอิงถึง List<Integer>, List<Number> หรือ List<Object> ก็ได้
import java.util.ArrayList;
import java.util.List;
public class Main {
public static void main(String[] args) {
List<? super Integer> a = new ArrayList<Number>();
List<? super Integer> b = new ArrayList<Object>();
a.add(1);
b.add(2);
System.out.println(a + " " + b);
}
}การเขียนลงในผู้บริโภค
เมื่อใช้ ? super Integer คุณสามารถเพิ่มค่าจำนวนเต็มใด ๆ (หรือชนิดย่อยของค่าจำนวนเต็ม) ได้อย่างปลอดภัย
ไม่ว่าชนิดข้อมูลจริงของรายการจะเป็นอะไร รายการนั้นก็เป็นรายการของชนิดข้อมูลที่อยู่เหนือกว่าค่าจำนวนเต็มอย่างน้อย ดังนั้นค่าจำนวนเต็มจึงใส่ลงไปได้เสมอ
import java.util.ArrayList;
import java.util.List;
public class Main {
static void addNumbers(List<? super Integer> dest) {
for (int i = 1; i <= 3; i++) dest.add(i);
}
public static void main(String[] args) {
List<Number> nums = new ArrayList<>();
addNumbers(nums);
System.out.println(nums);
}
}การอ่านจะได้ Object
ข้อแลกเปลี่ยนคือ เมื่อคุณอ่านจากรายการ ? super T คอมไพเลอร์จะทราบเพียงว่าองค์ประกอบเป็นชนิดข้อมูลที่อยู่เหนือกว่า T บางชนิดที่ไม่ทราบแน่ชัด
ชนิดข้อมูลเดียวที่ปลอดภัยสำหรับการอ่านคือ Object
import java.util.ArrayList;
import java.util.List;
public class Main {
public static void main(String[] args) {
List<? super Integer> list = new ArrayList<Number>();
list.add(10);
Object o = list.get(0); // only Object is guaranteed
// Integer i = list.get(0); // would NOT compile
System.out.println(o);
}
}เหตุใดการอ่านจึงมีข้อจำกัด
List<? super Integer> อาจเป็น List<Object> ที่เก็บค่า String อยู่จริงก็ได้
ดังนั้นการอ่านจึงอาจคืนค่าออบเจ็กต์ใด ๆ ก็ได้ คอมไพเลอร์ไม่สามารถรับรองได้ว่าจะเป็นค่าจำนวนเต็ม จึงให้ผลการอ่านเป็น Object เท่านั้น
import java.util.ArrayList;
import java.util.List;
public class Main {
public static void main(String[] args) {
List<Object> raw = new ArrayList<>();
raw.add("a string");
List<? super Integer> view = raw; // legal: Object is a supertype of Integer
view.add(5);
System.out.println(view.get(0).getClass().getSimpleName());
}
}กรณีใช้งานสำหรับผู้บริโภค
ใช้ ? super T เมื่อเมธอดทำหน้าที่รับค่าเพียงอย่างเดียว (เขียนค่าเข้าไป)
เมธอดที่เติมข้อมูลลงในชุดข้อมูลปลายทางเป็นกรณีใช้งานแบบคลาสสิก
import java.util.ArrayList;
import java.util.List;
public class Main {
static void fill(List<? super String> dest, int count) {
for (int i = 0; i < count; i++) dest.add("item" + i);
}
public static void main(String[] args) {
List<Object> objs = new ArrayList<>();
fill(objs, 3);
System.out.println(objs);
}
}การเพิ่มชนิดย่อยก็ทำได้เช่นกัน
เมื่อใช้ ? super Number คุณสามารถเพิ่มค่าชนิดตัวเลขหรือชนิดย่อยของมันได้ทุกชนิด เช่น ค่าจำนวนเต็ม ค่าทศนิยม และจำนวนเต็มขนาดยาว
ขอบเขตล่างรับรองว่ารายการจะยอมรับชนิดตัวเลขเป็นอย่างน้อย ดังนั้นชนิดย่อยทั้งหมดจึงใส่ลงไปได้
import java.util.ArrayList;
import java.util.List;
public class Main {
public static void main(String[] args) {
List<? super Number> list = new ArrayList<Object>();
list.add(1); // Integer
list.add(2.5); // Double
list.add(3L); // Long
System.out.println(list);
}
}รูปแบบ Collections.addAll
JDK ใช้ขอบเขตล่างสำหรับส่วนรับข้อมูล ตัวอย่างเช่น เมธอดทั่วไปที่นำองค์ประกอบใส่ลงในปลายทาง
import java.util.ArrayList;
import java.util.List;
public class Main {
@SafeVarargs
static <T> void addAll(List<? super T> dest, T... items) {
for (T item : items) dest.add(item);
}
public static void main(String[] args) {
List<Object> sink = new ArrayList<>();
addAll(sink, "a", "b", "c");
System.out.println(sink);
}
}ตัวเปรียบเทียบกับ super
การใช้งานในโลกจริงคือ Comparator<? super T> ซึ่งทำให้การเรียงลำดับยอมรับตัวเปรียบเทียบที่เขียนไว้สำหรับชนิดข้อมูลที่อยู่เหนือกว่าได้
ตัวเปรียบเทียบที่เปรียบเทียบออบเจ็กต์ใด ๆ ด้วย toString สามารถเรียงรายการของ String ได้
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
public class Main {
public static void main(String[] args) {
Comparator<Object> byString = Comparator.comparing(Object::toString);
List<String> names = new ArrayList<>(List.of("Charlie", "Alice", "Bob"));
names.sort(byString); // List<String>.sort accepts Comparator<? super String>
System.out.println(names);
}
}ขอบเขตล่างและขอบเขตบนเป็นภาพสะท้อนกัน
ไวลด์การ์ดทั้งสองชนิดเป็นแนวคิดตรงข้ามกัน:
? extends T: อ่านค่าเป็น T แต่เขียนไม่ได้ เป็นผู้ผลิต? super T: เขียนค่าเป็น T และอ่านได้เพียง Object เป็นผู้บริโภค
ความสมมาตรนี้เป็นหัวใจของกฎ PECS ที่คุณจะได้เรียนรู้ต่อไป
import java.util.ArrayList;
import java.util.List;
public class Main {
public static void main(String[] args) {
List<? super Integer> consumer = new ArrayList<Number>();
consumer.add(1);
System.out.println("consumer can write: " + consumer);
}
}การคัดลอกระหว่างขอบเขต
เมธอด copy แสดงการใช้ไวลด์การ์ดทั้งสองชนิดพร้อมกัน: อ่านจาก ? extends T และเขียนลงใน ? super T
import java.util.ArrayList;
import java.util.List;
public class Main {
static <T> void copy(List<? extends T> src, List<? super T> dest) {
for (T t : src) dest.add(t);
}
public static void main(String[] args) {
List<Integer> src = List.of(1, 2, 3);
List<Number> dest = new ArrayList<>();
copy(src, dest);
System.out.println(dest);
}
}กรณีที่ไม่ควรใช้ไวลด์การ์ด
หากเมธอดทั้งอ่านและเขียนค่า T อย่าใช้ไวลด์การ์ด ให้ใช้ชนิดข้อมูลที่ระบุแน่นอนหรือพารามิเตอร์ชนิดข้อมูลที่มีชื่อ
ไวลด์การ์ดมีไว้โดยเฉพาะสำหรับกรณีที่อ่านอย่างเดียวหรือเขียนอย่างเดียว
import java.util.ArrayList;
import java.util.List;
public class Main {
static <T> void swapFirstTwo(List<T> list) {
T tmp = list.get(0);
list.set(0, list.get(1));
list.set(1, tmp);
}
public static void main(String[] args) {
List<String> list = new ArrayList<>(List.of("a", "b"));
swapFirstTwo(list);
System.out.println(list);
}
}ตรวจสอบความเข้าใจอย่างรวดเร็ว
ทดสอบความเข้าใจของคุณเกี่ยวกับขอบเขตล่าง
ทบทวน
คุณได้เรียนรู้เกี่ยวกับไวลด์การ์ดที่มีขอบเขตล่างแล้ว:
? super Tหมายถึงชนิดข้อมูลที่อยู่เหนือกว่า T ซึ่งไม่ทราบแน่ชัด- คุณสามารถเขียนค่า T และชนิดย่อยของมันได้ (ผู้บริโภค)
- การอ่านจะคืนค่าเป็น Object เท่านั้น
- แนวคิดนี้เป็นภาพสะท้อนของ
? extends Tโดยตรง
ถัดไปคือกฎที่เชื่อมโยงทั้งสองแนวคิดเข้าด้วยกัน: PECS
import java.util.ArrayList;
import java.util.List;
public class Main {
public static void main(String[] args) {
List<? super Integer> list = new ArrayList<Number>();
list.add(42);
System.out.println("Lower bound recap: " + list);
}
}เรียนรู้ Java ด้วย AI tutor — ฟรี
เขียนและเรียกใช้โค้ดจริงในเบราว์เซอร์ของคุณ รับความช่วยเหลือทันทีจาก AI tutor 24/7 และเรียนรู้ต่อจากที่คุณหยุดบนเว็บหรือในแอป
- คอร์ส
- 104
- บทเรียน
- 374
คำถามที่พบบ่อย
บทเรียน “ไวลด์การ์ดขอบเขตล่าง” ฟรีหรือไม่
ใช่ — ข้อความเต็มของ “ไวลด์การ์ดขอบเขตล่าง” ฟรีให้อ่านที่นี่บนเว็บ เพื่อปฏิบัติแบบโต้ตอบ (ตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7) และปลดล็อคส่วนที่เหลือของคอร์ส Java Academy ให้อัปเกรดเป็น CoddyKit PRO คอร์ส Java Academy มีบทเรียนทั้งหมด 4 บทเรียน
คุณจะเรียนรู้อะไรในบทเรียน “ไวลด์การ์ดขอบเขตล่าง”
? super T สำหรับผู้บริโภคข้อมูล คุณปฏิบัติ Java Academy ด้วยโค้ดที่ใช้งานได้จริงที่คุณเรียกใช้โดยตรงในเบราว์เซอร์ และติวเตอร์ AI ตลอด 24/7 ตอบคำถามของคุณขณะที่คุณไปผ่านบทเรียน
คุณต้องมีประสบการณ์ก่อนที่จะเริ่มเรียน Java Academy หรือไม่
ไม่จำเป็นต้องมีประสบการณ์มาก่อน Java Academy บน CoddyKit ออกแบบมาสำหรับผู้เริ่มต้นไปจนถึงผู้เรียนขั้นสูง คุณสามารถเริ่มต้นที่นี่หรือเริ่มจากตัวแรกและเรียนด้วยความเร็วของคุณเอง นี่คือบทเรียนที่ 2 จากทั้งหมด 4 บทเรียน
บทเรียน “ไวลด์การ์ดขอบเขตล่าง” ใช้เวลานานแค่ไหน
บทเรียน CoddyKit ส่วนใหญ่ใช้เวลาประมาณ 5–10 นาที แต่ละบทเรียนจึงสั้นและเป็นแบบโต้ตอบ คุณสามารถก้าวหน้าอย่างต่อเนื่องและกลับมาเรียนต่อจากตรงที่เพิ่งหยุดบนเว็บและแอปได้เลย
ฉันเขียนและรันโค้ดในบทเรียน Java Academy นี้ได้ไหม
ได้ บทเรียน Java Academy ทุกบทมีตัวแก้ไขโค้ดในตัว คุณจึงเขียนและรันโค้ดจริงได้เลยในเบราว์เซอร์ และได้รับข้อเสนอแนะจาก AI ในทันที — ไม่ต้องติดตั้งในเครื่องของคุณ
บทเรียนทั้งหมดในหลักสูตรนี้
- ไวลด์การ์ดขอบเขตบน
- ไวลด์การ์ดขอบเขตล่าง
- หลักการ PECS
- ไวลด์การ์ดใน API