<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    Scott@JAVA

    Java, 一杯濃濃的咖啡伴你到深夜

    《Java 5.0 Tiger》Chapter 2

    Chapter 2. Generics

    2.1 Using Type-Safe Lists

    In pre-Tiger versions of Java, the method signature for add() in List looked like this:

    public boolean add(Object obj);

    In Tiger, though, things have changed:

    public boolean add(E o);

    Before you go looking up E in Javadoc, though, it's just a placeholder. It indicates that this method declares a type variable (E) and can be parameterized. The entire List class is generic:

    public interface List<E> extends Collection, Iterable {

    There's that E again. When you supply a type in the initialization of a List, you parameterize the type—you indicate what type its parameters can accept:

    List<String> onlyStrings = new LinkedList<String>();

    One way to understand this is to imagine that the compiler replaces every occurrence of E with the type you supplied—in this case, a String. Of course, this is just done for this particular instance of List. You can have multiple Lists, all with different types, and all in the same program block.

    2.2 Using Type-Safe Maps

    You use it just as you use List, but with two types (key-vaule) at declaration and initialization.

    2.3 Iterating Over Parameterized Types

    List<String> listOfStrings = new LinkedList<String>();
    listOfStrings.add(
    "Happy");
    listOfStrings.add(
    "Birthday");
    listOfStrings.add(
    "To");
    listOfStrings.add(
    "You");
    for (Iterator<String> i = listOfStrings.iterator(); i.hasNext();) {
        String s 
    = i.next();
        out.println(s);
    }
    You should always pair your Iterators with your collections like this—if the collection is parameterized, the Iterator should use the same parameter.

    2.4 Accepting Parameterized Types as Arguments

    private void printListOfStrings(List<String> list, PrintStream out)
            
    throws IOException {
        
    for (Iterator<String> i = list.iterator(); i.hasNext();) {
            out.println(i.next());
        }

    }
    This allows your method body to act on that parameterization, avoiding class casts and the like.

    2.5 Returning Parameterized Types

    private List<String> getListOfStrings() {
        List
    <String> list = new LinkedList<String>();
        list.add(
    "Hello");
        list.add(
    "World");
        list.add(
    "How");
        list.add(
    "Are");
        list.add(
    "You?");
        
    return list;
    }

    2.6 Using Parameterized Types as Type Parameters

    The Map interface takes two type parameters: one for the key, and one for the value itself. While the key is usually a String or numeric ID, the value can be anything—including a generic type, like a List of Strings.

    So List<String> becomes a parameterized type, which can be supplied to the Map declaration:

    Map<String, List<String>> map = new HashMap<String, List<String>>();

    If that's not enough angle brackets for you, here's yet another layer of generics to add into the mix:

    Map<String, List<List<int[]>>> map = getWeirdMap();

    Of course, where things get really nuts is actually accessing objects from this collection:

    int value = map.get(someKey).get(0).get(0)[0];

    2.7 Checking for Lint

    neglect

    2.8 Generics and Type Conversions


    The key in casting generic types is to understand that as with normal, non-generic types, they form a hierarchy. What's unique about generics, though, is that the hierarchy is based on the base type, not the parameters to that type. For example, consider this declaration:

    LinkedList<Float> floatList = new LinkedList<Float>();

    The conversion is based on LinkedList, not Float. So this is legal:

    List<Float> moreFloats = floatList;

    However, the following is not:

    LinkedList<Number> numberList = floatList;

    While Float is indeed a subclass of Number, it's the generic type that is important, not the parameter type.

    The second concept you'll want to grasp is erasure. Generics in Tiger is a compile-time process, and all typing information is handled at compiletime. Once the classes are compiled, the typing information is erased (thus the term erasure).

    You can also use erasure to break type-safety. Remember that at runtime, erasure removes all your parameterization. This means that when you access parameterized types with reflection, you get the effects of erasure, at compile-time

    2.9 Using Type Wildcards

    Still, here are times when you really do want a plain old List, or Map, or whatever, without parameterization. This is going to result in unchecked errors, unless you employ the generics wildcard.

    public void printList(List<?> list, PrintStream out) throws IOException {
        
    for (Iterator<?> i = list.iterator(); i.hasNext(); ) {
            out.println(i.next().toString());
        }

    }

    ...using List<Object> to get around this same problem? You might want to review Generics and Type Conversions, and see if you really want to do that. A List<Integer> cannot be passed to a method that takes a List<Object>, remember? So your printList( ) method would be limited to collections defined as List<Object>, which isn't much use at all. In these cases, the wildcard really is the only viable solution.

    2.10 Writing Generic Types

    import java.util.ArrayList;
    import java.util.List;

    public class Box<T> {
        
    protected List<T> contents;

        
    public Box() {
            contents 
    = new ArrayList<T>();
        }


        
    public int getSize() {
            
    return contents.size();
        }


        
    public boolean isEmpty() {
            
    return (contents.size() == 0);
        }


        
    public void add(T o) {
            contents.add(o);
        }


        
    public T grab() {
            
    if (!isEmpty()) {
                
    return contents.remove(0);
            }
     else
                
    return null;
        }

    }

    Just as you've seen in Tiger's pre-defined generic types, a single letter is used as the representative for a type parameter.

    You create a new instance of this type exactly as you might expect:

    Box<String> box = new Box<String>();

    This effectively replaces all the occurrences of T with String for that specific instance, and suddenly you've got yourself a String Box, so to speak.

    2.11 Restricting Type Parameters

    This is pretty simple—you can actually insert an extends className onto your type variable, and voila! Check out:

    import java.util.Iterator;

    public class NumberBox<extends Number> extends Box<N> {
        
    public NumberBox() {
            
    super();
        }


        
    // Sum everything in the box
        public double sum() {
            
    double total = 0;

            
    for (Iterator<N> i = contents.iterator(); i.hasNext();) {
                total 
    = total + i.next().doubleValue();
            }

            
    return total;
        }

    }

    The only types allowed here are extensions of the class Number (or Number itself).

    You can use this same syntax in method definitions:

        public static double sum(Box<? extends Number> box1,
                Box
    <? extends Number> box2) {
            
    double total = 0;
            
    for (Iterator<? extends Number> i = box1.contents.iterator(); i
                    .hasNext();) 
    {
                total 
    = total + i.next().doubleValue();
            }

            
    for (Iterator<? extends Number> i = box2.contents.iterator(); i
                    .hasNext();) 
    {
                total 
    = total + i.next().doubleValue();
            }

            
    return total;
        }

    This starts to get a little weird, I realize, but them's the breaks. It gets worse because you have to use the wildcard indicator, and then repeat the expression (? extends Number) in the method body. One way to clean this up is to declare your own type variable inline (and make your syntax even odder):

        public static <extends Number> double sum(Box<A> box1, Box<A> box2) {
            
    double total = 0;
            
    for (Iterator<A> i = box1.contents.iterator(); i.hasNext();) {
                total 
    = total + i.next().doubleValue();
            }

            
    for (Iterator<A> i = box2.contents.iterator(); i.hasNext();) {
                total 
    = total + i.next().doubleValue();
            }

            
    return total;
        }

    The portion of the method declaration right before the return value, <A extends Number>, provides a typing variable which is then used throughout the method declaration and body.

    posted on 2005-12-26 21:30 Scott@JAVA 閱讀(451) 評論(0)  編輯  收藏 所屬分類: Java 5.0 Tiger

    主站蜘蛛池模板: 亚洲hairy多毛pics大全| 亚洲视频在线观看视频| 亚洲爆乳无码精品AAA片蜜桃| 在线看片无码永久免费视频| 亚洲成无码人在线观看| 无码人妻一区二区三区免费看| 亚洲AV无码专区电影在线观看| 国产免费一区二区三区在线观看 | 日韩人妻无码精品久久免费一 | 日韩在线视频线视频免费网站| 亚洲福利中文字幕在线网址| 一边摸一边桶一边脱免费视频 | 久久笫一福利免费导航| 亚洲日韩国产精品乱-久| 爽爽日本在线视频免费| 黄网站色视频免费观看45分钟| 亚洲中文字幕无码久久综合网 | 一本无码人妻在中文字幕免费| 在线a亚洲老鸭窝天堂av高清| 四虎免费在线观看| 免费手机在线看片| 亚洲精品视频在线| 成人无遮挡裸免费视频在线观看 | 蜜芽亚洲av无码精品色午夜| 成人免费一级毛片在线播放视频| 亚洲国产精品99久久久久久| 亚洲成AⅤ人影院在线观看| 精品国产污污免费网站| 亚洲国产系列一区二区三区| 婷婷综合缴情亚洲狠狠尤物| 国产无遮挡裸体免费视频在线观看 | 亚洲综合国产精品第一页| 中文无码成人免费视频在线观看| 亚洲国产成人久久77| 四虎成人精品在永久免费| a级毛片视频免费观看| 亚洲 欧洲 自拍 另类 校园| 亚洲高清无码综合性爱视频| 最近免费中文字幕mv在线电影| 亚洲AV无码AV男人的天堂不卡| 精品国产_亚洲人成在线高清|