[Java] 14.2. 通用字元?

通用字元 - ?,更好的擴充與限定泛型上型別。

 

image/svg+xml14.2. 通⽤字元-? import java.util.*; class Boss { public void pay ( List < Employee > emps){ for ( Employee e : emps){ System.out.print(e.name + " :取得薪⽔與獎⾦ " ); System.out.println(e.salary+e.getBonus()); } } } import java.util.*; class Main{ public static void main( String [] args){ List < Programmer > ps = new ArrayList < Programmer >(); ps.add ( new Programmer ( "K12345678" , “Jack" , 20 , " 男⽣ " , "048679" , 40000 )); ps.add ( new Programmer ( "K00000000" , “Eric" , 25 , " 男⽣ " , "041121" , 45000 )); List < Tester > ts = new ArrayList < Tester >(); ts.add ( new Tester ( "K11111111" , “Mary" , 18 , " 女⽣ " , "050021" , 30000 )); List < Artist > as = new ArrayList < Artist >(); as.add ( new Artist ( "K22222222" , “Jack" , 19 , " 男⽣ " , "051212" , 42000 )); Boss b = new Boss (); b.pay (ps); b.pay (ts); b.pay (as); } } 執⾏結果 Main.java:18: error: incompatible types: List<Programmer> cannot be converted to List<Employee> b.pay(ps); ^ Main.java:19: error: incompatible types: List<Tester> cannot be converted to List<Employee> b.pay(ts); ^ Main.java:20: error: incompatible types: List<Artist> cannot be converted to List<Employee> b.pay(as); ^ Note: Some messages have been simplified; recompile with -Xdiags:verbose to get full output 3 errors 通⽤字元的使⽤⽅式其實可份為三種: import java.util.*; class Boss { public void pay ( List < ? extends Employee > emps){ for ( Employee e : emps){ System.out.print(e.name + " :取得薪⽔與獎⾦ " ); System.out.println(e.salary+e.getBonus()); } } } import java.util.*; class Main{ public static void main( String [] args){ List < Programmer > ps = new ArrayList < Programmer >(); ps.add ( new Programmer ( "K12345678" , “Jack" , 20 , " 男⽣ " , "048679" , 40000 )); ps.add ( new Programmer ( "K00000000" , “Eric" , 25 , " 男⽣ " , "041121" , 45000 )); List < Tester > ts = new ArrayList < Tester >(); ts.add ( new Tester ( "K11111111" , “Mary" , 18 , " 女⽣ " , "050021" , 30000 )); List < Artist > as = new ArrayList < Artist >(); as.add ( new Artist ( "K22222222" , “Jack" , 19 , " 男⽣ " , "051212" , 42000 )); Boss b = new Boss (); b.pay (ps); b.pay (ts); b.pay (as); } } 執⾏結果 Jack :取得薪⽔與獎⾦ 200000.0 Eric :取得薪⽔與獎⾦ 225000.0 Mary :取得薪⽔與獎⾦ 75000.0 Jack :取得薪⽔與獎⾦ 168000.0 import java.util.*; class Main{ public static void main( String [] args){ List < Programmer > ps = new ArrayList < Programmer >(); ps.add ( new Programmer ( "K12345678" , "Jack" , 20 , " 男⽣ " , "048679" , 40000 )); ps.add ( new Programmer ( "K00000000" , "Eric" , 25 , " 男⽣ " , "041121" , 45000 )); Boss b = new Boss (); b.pay ( ps ); } } import java.util.*; class Boss { public void pay( List < ? extends Employee > emps ){ emps.add ( new Tester ( "K11111111" , “Mary" , 18 , " 女⽣ " , "050021" , 30000 )); } } 執⾏結果 ./Boss.java:5: error: no suitable method found for add(Tester) emps.add(new Tester("K11111111", "Mary", 18, " 女⽣ ", "050021", 30000)); ^ method Collection.add(CAP#1) is not applicable (argument mismatch; Tester cannot be converted to CAP#1) method List.add(CAP#1) is not applicable (argument mismatch; Tester cannot be converted to CAP#1) where CAP#1 is a fresh type-variable: CAP#1 extends Employee from capture of ? extends Employee Note: Some messages have been simplified; recompile with -Xdiags:verbose to get full output 1 error ? extends [ 型別 1] 代表可以接受型別1或繼承⾃型別1的泛型型別 ? super [ 型別 2] 代表可以接受型別 2 或型別 2 的⽗類別的泛型型別 ? 代表著只要是物件的泛型型別就可以接受,同等 “? extends Object” J14_2_1 Boss.java 1. 這是老闆類別( Boss )。 J14_2_1 Main.java 2. 很好,老闆也使⽤泛型,這樣將限制集合中的物件⼀定會 擁有員⼯的型別了。不怕連不是員⼯的⼈都來顉獎⾦了。 3. 準備專⾨裝載程式設計師( Programmer )的集合。 讓程式設計師可以組成⼀團去跟老闆領錢。 4. 這是專⾨裝載測試⼈員( Tester )的集合。 5. 這是專⾨裝載美⼯⼈員( Artist )的集合。 6. 建立老闆物件( Boss )。 7. 怎麼編譯器會發⽣錯誤,不讓老闆發放薪⽔給不同⾓⾊的員⼯呢? 還記得老闆類別( Boss )上的發放獎⾦⽅法( pay() )嗎?原因是發 放獎⾦⽅法上參數的泛型型別已經限定為員⼯類別了( Employee ), 因此這個參數將不能接受其他泛型型別的集合物件。 J14_2_2 Boss.java 1. 這是老闆類別( Boss )。 2. 現在我們的泛型型別,以使⽤通⽤字元(?)加上 extends 的⽅式,表 ⽰只要是繼承⾃員⼯類別( Employee )的泛型,都可以放入 emps 參數中。 J14_2_2 Main.java 1. 準備專⾨將裝程式設計師( Programmer )的集合。 讓程式設計師可以組成⼀團去跟老闆領錢。 2. 這是專⾨裝載測試⼈員( Tester )的集合。 3. 這是專⾨裝載美⼯⼈員( Artist )的集合。 4. 建立老闆物件( Boss )。 . 現在可以正常編譯成功了,因為不論是 ps ts as 集合物件, 它們的泛型型別皆是繼承⾃員⼯類別( Employee )的,因此可以直 接代入泛型型別為 <? extends Employee> 的參數中。 當然您也可以視需求使⽤ “? super” 或直接使⽤ “?” 的⽅式,來讓限定泛型 ⽀援多型的⽅式。 J14_2_3 Main.java J14_2_3 Boss.java 1. 只能裝入程式設計師( Programmer )的集合物件。 2. 建立老闆物件( Boss ),並呼叫發放⽅法( pay() )發放獎⾦。 3. 泛型中使⽤了通⽤字元(?)。 4. 啊~怎麼因為使⽤了通⽤字元( ? )的關係,因此讓 emps 變數可以加入 測試⼈員的物件到程式設計師的集合物件中呢?試看看吧。 5. 若想要透過使⽤通⽤字元( ? )的變數上,透過 add() ⽅法加入員⼯(任何⾓⾊的員⼯),這是會編譯錯誤的,因為 使⽤通⽤字元( ? )的變數必須以唯讀的⽅式來操作集合物件。 老闆認為只要是員⼯就可以發獎⾦了, 但怎麼泛型卻要嚴格的區分員⼯的⾓⾊呢? 使⽤通⽤字元(?) 讓發放獎⾦⽅法上的泛型也⽀援多型 1 2 3 1 2 3 測試通⽤字元(?)版本的發放獎⾦⽅法 1 2 3 1 2 3 通⽤字元(?)讓員⼯集合以唯讀的⽅式進⾏操作, 以防⽌不同⾓⾊的員⼯被加入 1 1

留言