java編程思想讀書筆記二

泛型

  • 對象和實(shí)例是一個(gè)意思陵究,類與對象的關(guān)系就像數(shù)據(jù)類型和變量一樣琴庵。

  • 泛型的主要目的之一就是用來指定類(如:容器)要持有什么類型的對象衰抑,代碼解釋如下:

    
    public class Holder3<T> {
      private T a;//持有了T的對象,此處可以持有任何對象秋泄,可以用Object代替但是要向下轉(zhuǎn)型
      public Holder3(T a) { this.a = a; }
      public void set(T a) { this.a = a; }
      public T get() { return a; }
      public static void main(String[] args) {
        Holder3<Automobile> h3 =
          new Holder3<Automobile>(new Automobile());
        Automobile a = h3.get(); // No cast needed
        // h3.set("Not an Automobile"); // Error
        // h3.set(1); // Error
      }
    } ///:~
    
  • 在有些場景中會有一個(gè)方法返回多個(gè)對象悼瘾,你可以使用創(chuàng)建類用它來持有返回的多個(gè)對象,如果再 加上泛型技術(shù)就會在編譯期確保類型安全书闸。代碼解釋如下:

    //: net/mindview/util/TwoTuple.java
    package net.mindview.util;
    
    public class TwoTuple<A,B> {
      public final A first;
      public final B second;
      public TwoTuple(A a, B b) { first = a; second = b; }
      public String toString() {
        return "(" + first + ", " + second + ")";
      }
    } ///:~
    
  • 如果泛型用得好尼变,基本上不用強(qiáng)制性轉(zhuǎn)換

  • 泛型也可以應(yīng)用于接口,比如public interface Generator<T>,在寫繼承的時(shí)候T可以寫成任意類型,比如構(gòu)造一個(gè)咖啡工廠public class CoffeeGenerator implements Generator<Coffee>,構(gòu)造一個(gè)生成Fibonacci數(shù)列的類public class Fibonacci implements Generator<Integer>嫌术,咖啡代碼如下:

    //... 省略處為一些簡單類哀澈,如Latte,Mocha,Cappuccino,Americano,Breve這些類都繼承于coffee,coffee.java如下
    package com.generics.coffee;
    public class Coffee {
      private static long counter = 0;
      private final long id = counter++;
      public String toString() {
        return getClass().getSimpleName() + " " + id;
      }
    } ///:~
    
    //: generics/coffee/CoffeeGenerator.java
    // Generate different types of Coffee:
    package com.generics.coffee;
    import java.util.*;
    import net.mindview.util.*;
    
    public class CoffeeGenerator implements Generator<Coffee> ,Iterable<Coffee> {
      @SuppressWarnings("rawtypes")
      private Class[] types = { Latte.class, Mocha.class,
        Cappuccino.class, Americano.class, Breve.class, };
      private static Random rand = new Random(47);
      public CoffeeGenerator() {}
      // For iteration:
      private int size = 0;
      public CoffeeGenerator(int sz) { size = sz; } 
      public Coffee next() {
        try {
          return (Coffee)
            types[rand.nextInt(types.length)].newInstance();
          // Report programmer errors at run time:
        } catch(Exception e) {
          throw new RuntimeException(e);
        }
      }
      //解釋:內(nèi)部類實(shí)現(xiàn)迭代器,該實(shí)現(xiàn)了Iterator而CoffeeGenerator實(shí)現(xiàn)的是Iterable,要實(shí)現(xiàn)foreach循環(huán)必須實(shí)現(xiàn)這兩個(gè)接口,
    //從代碼看起來foreach循環(huán)是看出來了度气,要理解其本質(zhì)的原理需要看jvm里面的字節(jié)碼割按,new CoffeeGenerator(5)調(diào)用后,首先產(chǎn)生
    //CoffeeIterator的實(shí)例磷籍,執(zhí)行hasNext()->next()
    //此處可以也可以用匿名內(nèi)部類
      class CoffeeIterator implements Iterator<Coffee> {
        int count = size;
        public boolean hasNext() { return count > 0; }
        public Coffee next() {
          count--;
          return CoffeeGenerator.this.next();
        }
        public void remove() { // Not implemented
          throw new UnsupportedOperationException();
        }
      };    
      public Iterator<Coffee> iterator() {
        return new CoffeeIterator();
      }
      public static void main(String[] args) {
        CoffeeGenerator gen = new CoffeeGenerator();
        for(int i = 0; i < 5; i++)
          System.out.println(gen.next());
        for(Coffee c : new CoffeeGenerator(5))
          System.out.println(c);
      }
    } /* Output:
    Americano 0
    Latte 1
    Americano 2
    Mocha 3
    Mocha 4
    Breve 5
    Americano 6
    Latte 7
    Cappuccino 8
    Cappuccino 9
    *///:~
    
    Fibonacci數(shù)列的代碼如下:
    
    package com.generics;
      import net.mindview.util.*;
    
      public class Fibonacci implements Generator<Integer> {
        private int count = 0;
        public Integer next() { return fib(count++); }
        private int fib(int n) {
          if(n < 2) return 1;
          return fib(n-2) + fib(n-1);
        }
        public static void main(String[] args) {
          Fibonacci gen = new Fibonacci();
          for(int i = 0; i < 18; i++)
            System.out.print(gen.next() + " ");
        }
      } /* Output:
      1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987 1597 2584
      *///:~
    

    如果想要實(shí)現(xiàn)迭代适荣,而且要不用內(nèi)部類的方式(CoffeeGenerator.java使用的是內(nèi)部類實(shí)現(xiàn)的迭代器模式),用適配器模式實(shí)現(xiàn)院领,適配器模式即把兩個(gè)互不相關(guān)的接口或者類相連接弛矛,所以可以使用繼承或者組合,UML如下:

    ![](https://www.processon.com/chart_image/thumb/58aaf16ee4b071585833fd96.png)
    
    迭代如下:
    
    package com.generics;
      // Adapt the Fibonacci class to make it Iterable.
      import java.util.*;
      //組合來創(chuàng)建適配器
      public class IterableFibonacci implements Iterable<Integer> {
        private Fibonacci fibonacci = new Fibonacci();
        private int n;
        public IterableFibonacci(int count) { n = count; }
        public Iterator<Integer> iterator() {
        //匿名內(nèi)部類的形式
        return new Iterator<Integer>() {
        @Override
        public Integer next() {
            // TODO Auto-generated method stub
            n--;
        
            return fibonacci.next();//invoke next() in Fibonacci,for this extends Fibonacci
        }
        @Override
        public boolean hasNext() {
            // TODO Auto-generated method stub
            return n > 0; 
        }
        public void remove() { // Not implemented
                throw new UnsupportedOperationException();
              }
        };
        }   
        public static void main(String[] args) {
          for(int i : new IterableFibonacci(18))
            System.out.print(i + " ");
        }
      } /* Output:
      1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987 1597 2584
      *///:~ 
    
  • 泛型應(yīng)用于方法

    • 應(yīng)用于方法public <T> void f(T x){}比然,其中<T>一定要寫丈氓,不然編譯器是無法識別出參數(shù)的T

    • 當(dāng)可變參數(shù)與方法結(jié)合:

      package com.generics;
      
      //: generics/GenericVarargs.java
      import java.util.*;
      
      public class GenericVarargs {
        //此處的makeList就像是java.util.Arrays里面的asList(T... args);
        public static <T> List<T> makeList(T... args) {
          List<T> result = new ArrayList<T>();
          for(T item : args)
            result.add(item);
          return result;
        }
        public static void main(String[] args) {
          List<String> ls = makeList("A");
          System.out.println(ls);
          ls = makeList("A", "B", "C");
          System.out.println(ls);
          ls = makeList("ABCDEFFHIJKLMNOPQRSTUVWXYZ".split(""));
          System.out.println(ls);
        }
      } /* Output:
                                                  [A]
                                                  [A, B, C]
                                                  [, A, B, C, D, E, F, F, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z]
                                                  *///:~
      

      從上面代碼注釋可以看到makeList和asList方法很像,下面來看看asList的源碼分析

        public static <T> List<T> asList(T... a) {
            return new ArrayList<>(a);//此處的ArrayList不是你想的java.util.ArrayList,他是Arrays里面的一個(gè)靜態(tài)內(nèi)部類
          }
          //此處是靜態(tài)內(nèi)部類的構(gòu)造器强法,返回一個(gè)數(shù)組万俗,需要說明的是該內(nèi)部類并沒有實(shí)現(xiàn)add,remove等方法,因?yàn)閍sList()方法在大多數(shù)使用場景中是不用改變的饮怯,所以要構(gòu)造一個(gè)可編輯的ArrayList()用類似下面的代碼即可List<WaiterLevel> levelList = new ArrayList<WaiterLevel>(Arrays.asList("a", "b", "c"));  
          ArrayList(E[] array) {
            a = Objects.requireNonNull(array);//判斷array是否為空
          }
      
  • 利用泛型方法對前一章的生成器進(jìn)行更一步的抽象闰歪,代碼如下:

    //: net/mindview/util/BasicGenerator.java
    // Automatically create a Generator, given a class
    // with a default (no-arg) constructor.
    package net.mindview.util;
    //this class can generate any Class which have default constructor by create() function,but there is a limit which is that constructor cannot pass argument(傳參) 
    public class BasicGenerator<T> implements Generator<T> {
      private Class<T> type; 
      public BasicGenerator(Class<T> type){ this.type = type; }
      public T next() {
        try {
          // Assumes type is a public class:
          return type.newInstance();
        } catch(Exception e) {
          throw new RuntimeException(e);
        }
      }
      // Produce a Default generator given a type token:
      public static <T> Generator<T> create(Class<T> type) {
        return new BasicGenerator<T>(type);
      }
    } ///:~
    

    更多的,我們可以對前面提到的元組進(jìn)行進(jìn)一步的抽象

    //: net/mindview/util/Tuple.java
    // Tuple library using type argument inference.
    package net.mindview.util;
    
    public class Tuple {
      public static <A,B> TwoTuple<A,B> tuple(A a, B b) {
        return new TwoTuple<A,B>(a, b);
      }
      public static <A,B,C> ThreeTuple<A,B,C>
      tuple(A a, B b, C c) {
        return new ThreeTuple<A,B,C>(a, b, c);
      }
      public static <A,B,C,D> FourTuple<A,B,C,D>
      tuple(A a, B b, C c, D d) {
        return new FourTuple<A,B,C,D>(a, b, c, d);
      }
      public static <A,B,C,D,E>
      FiveTuple<A,B,C,D,E> tuple(A a, B b, C c, D d, E e) {
        return new FiveTuple<A,B,C,D,E>(a, b, c, d, e);
      }
    } ///:~
    
  • java對泛型的擦除有四句話

    • 泛型類型在運(yùn)行時(shí)都是Object類型
    • 模板只在編譯階段有效是為了提供編譯期的類型安全蓖墅,通過反射操作可以繞過編譯階段
    • 在編譯期就可以知道的類型信息是可以操作的
    • 所有在運(yùn)行時(shí)才能知道類型信息的操作都將無法工作
    package com.generics;
    
    import java.lang.reflect.InvocationTargetException;
    import java.lang.reflect.Method;
    import java.util.ArrayList;
    import java.util.List;
    class Manipulator<T> {
      public T obj;
      public Manipulator(T x) { obj = x; }
      // Error: cannot find symbol: method f():
      public void manipulate() { 
    //    (obj).f();
      }
      
      public void erase2(){
          //T[] t = new T[4]; 
          //a instanceof T;
      }
    }
    
    public class Manipulation {
      public static void main(String[] args) {
        //1.模板只在編譯階段有效是為了提供編譯期的類型安全库倘,通過反射操作可以繞過編譯階段
        List<String> list1 = new ArrayList<>();
        List list = new ArrayList<>();
        list1.add("s");
        //list1.add(2);
        try {
            Method m = ArrayList.class.getMethod("add",Object.class);
            m.invoke(list1, 2);
            System.out.println(list1);
        } catch (NoSuchMethodException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (SecurityException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IllegalArgumentException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        //2.在編譯期就可以知道的類型信息是可以操作的
        HasF hf = new HasF();
        Manipulator<HasF> manipulator =
          new Manipulator<HasF>(hf);
        manipulator.obj.f();
       //在這個(gè)函數(shù)里面調(diào)用的obj.f(),是不可能考慮客戶端的類型,即是單獨(dú)去編譯的置媳,在客戶端沒有調(diào)用時(shí)于樟,他并不知道T是什么類型,所以有錯(cuò)
        manipulator.manipulate();
      
        //3.所有在運(yùn)行時(shí)才能知道類型信息的操作都將無法工作
        manipulator.erase2();
        
      }
    } ///:~
    
  • 不能創(chuàng)建泛型類型數(shù)組的,一般的解決方案是在任何想要?jiǎng)?chuàng)建泛型數(shù)組的地方都是用ArrayList去創(chuàng)建拇囊。

  • 泛型的主要目標(biāo)之一是將錯(cuò)誤檢測移入到編譯期

  • 編譯器直接拒絕對參數(shù)列表中涉及到的通配符的方法迂曲,即add(? extends fruit)如果變成了這樣結(jié)果如下圖

    ?
  • 下面代碼能夠?qū)崿F(xiàn)只能存水果的集合,且在編譯期內(nèi)就能檢查類型信息,其中第二種方式稱之為逆變寥袭。為什么逆變的方式可以實(shí)現(xiàn)路捧?答:super關(guān)鍵字表示下界,List<? super Apple> fruit = new ArrayList<>();传黄,而?必須要表示一個(gè)確切的類型杰扫,準(zhǔn)確來講應(yīng)該是這樣聲明一個(gè)實(shí)例即:List<? super Apple> fruit = new ArrayList<在這個(gè)括號內(nèi)部必須是Apple的父類>();即在比如List<? super Apple> fruit = new ArrayList<Fruit>(),所以當(dāng)add()的時(shí)候膘掰,可以插入Apple的子類章姓,同樣的道理分析List<? extends Apple> flist2 = new ArrayList<這里面要插入的是Apple的子類>();所以當(dāng)add(new Apple())時(shí)候佳遣,會失敗,比如List<? extends Apple> flist2 = new ArrayList<Jonathan>();Jonathan = new Apple()//error;

    //1.想要實(shí)現(xiàn)一個(gè)集合里面能裝所有類型的水果凡伊,但是在編譯期不允許裝除了水果以外的其他對象
    List<Fruit> flist3 = new ArrayList<>();
    flist3.addAll(Arrays.asList(new Apple()));
    flist3.addAll(Arrays.asList(new Orange()));
    System.out.println(flist3.get(1));
    //2.第一種方式太復(fù)雜,下面用逆變的方式實(shí)現(xiàn)
    List<? super Fruit> fruit = new ArrayList<>();
    fruit.add(new Apple());
    fruit.add(new Orange());
    
  • 混型即Timestamped<Serialnumbered<Basic>> mixin其中mixin能夠調(diào)用基類的所有函數(shù)零渐,在C++中,這是顯然的系忙,但是在java中可以這樣聲明诵盼,但不能調(diào)用基類的任何函數(shù)只能調(diào)用Timestamped類中的函數(shù),所以必須使用有些設(shè)計(jì)模式來代替,其中涉及到裝飾器模式银还,和用動(dòng)態(tài)代理(即我們可以動(dòng)態(tài)注入類方法)來實(shí)現(xiàn)混合风宁,但是結(jié)果都沒有C++中方便直接。

    implementsextends關(guān)鍵字實(shí)現(xiàn):

    package com.generics;
    //: generics/Mixins.java
    import java.util.*;
    
    interface TimeStamped { long getStamp(); }
    
    class TimeStampedImp implements TimeStamped {
      private final long timeStamp;
      public TimeStampedImp() {
        timeStamp = new Date().getTime();
      }
      public long getStamp() { return timeStamp; }
    }
    
    interface SerialNumbered { long getSerialNumber(); }
    
    class SerialNumberedImp implements SerialNumbered {
      private static long counter = 1;
      private final long serialNumber = counter++;
      public long getSerialNumber() { return serialNumber; }
    }
    
    interface Basic {
      public void set(String val);
      public String get();
    }
    
    class BasicImp implements Basic {
      private String value;
      public void set(String val) { value = val; }
      public String get() { return value; }
    }
    // for Mixin2.java,Timestamped<Serialnumbered<Basic>> mixin = new Timestamped();,mixin can not invoke set() function of Basic,but c++ is capable to do it.
    //so in java, use implements and extends keywords to realize it.
    class Mixin extends BasicImp
    implements TimeStamped, SerialNumbered {
    
     //if use this,you must have a instance of response to interface
    
      private TimeStamped timeStamp = new TimeStampedImp();
      private SerialNumbered serialNumber =
        new SerialNumberedImp();
      public long getStamp() { return timeStamp.getStamp(); }
      public long getSerialNumber() {
        return serialNumber.getSerialNumber();
      }
    }
    
    public class Mixins {
      public static void main(String[] args) {
        Mixin mixin1 = new Mixin(), mixin2 = new Mixin();
        mixin1.set("test string 1");
        mixin2.set("test string 2");
        System.out.println(mixin1.get() + " " +
          mixin1.getStamp() +  " " + mixin1.getSerialNumber());
        System.out.println(mixin2.get() + " " +
          mixin2.getStamp() +  " " + mixin2.getSerialNumber());
      }
    } /* Output: (Sample)
    test string 1 1132437151359 1
    test string 2 1132437151359 2
    *///:~
    

    裝飾器模式實(shí)現(xiàn)(并沒有完全實(shí)現(xiàn)):

    package com.generics.decorator;
    
    //: generics/decorator/Decoration.java
    
    import java.util.*;
    
    class Basic {
      private String value;
      public void set(String val) { value = val; }
      public String get() { return value; }
    }
    
    class Decorator extends Basic {
      protected Basic basic;
      public Decorator(Basic basic) { this.basic = basic; }
      public void set(String val) { basic.set(val); }
      public String get() { return basic.get(); }
    }   
    
    class TimeStamped extends Decorator {
      private final long timeStamp;
      public TimeStamped(Basic basic) {
        super(basic);
        timeStamp = new Date().getTime();
      }
      public long getStamp() { return timeStamp; }
    }
    
    class SerialNumbered extends Decorator {
      private static long counter = 1;
      private final long serialNumber = counter++;
      public SerialNumbered(Basic basic) { super(basic); }
      public long getSerialNumber() { return serialNumber; }
    }   
    
    //this is decoration design patterns
    
    public class Decoration {
      public static void main(String[] args) {
        TimeStamped t = new TimeStamped(new Basic());
      // because timestamped extends Basic
     t.set("fasdfa");
      //realize such as TimeStamped<SerialNumbered<Basic>> mixin1, mixin2
        TimeStamped t2 = new TimeStamped(
          new SerialNumbered(new Basic()));
        //! t2.getSerialNumber(); // Not available, obviously
        SerialNumbered s = new SerialNumbered(new Basic());
        SerialNumbered s2 = new SerialNumbered(
          new TimeStamped(new Basic()));
        //! s2.getStamp(); // Not available
      }
    } ///:~
    

    動(dòng)態(tài)代理模式實(shí)現(xiàn):

    package com.generics;
    
    //: generics/DynamicProxyMixin.java
    import java.lang.reflect.*;
    import java.util.*;
    import net.mindview.util.*;
    import static net.mindview.util.Tuple.*;
    
    class MixinProxy implements InvocationHandler {
      Map<String,Object> delegatesByMethod;
      public MixinProxy(TwoTuple<Object,Class<?>>... pairs) {
        delegatesByMethod = new HashMap<String,Object>();
        for(TwoTuple<Object,Class<?>> pair : pairs) {
          for(Method method : pair.second.getMethods()) {
            String methodName = method.getName();
            System.out.println(methodName + "()");
            // The first interface in the map
            // implements the method.
            if (!delegatesByMethod.containsKey(methodName))
              delegatesByMethod.put(methodName, pair.first);// this is the most important, because this inject all functions of pairs
          }
        }
      } 
      public Object invoke(Object proxy, Method method,
        Object[] args) throws Throwable {
        System.out.println("invoke() is invoked"); 
        String methodName = method.getName();
        Object delegate = delegatesByMethod.get(methodName);
        return method.invoke(delegate, args);
      }
      @SuppressWarnings("unchecked")
      public static Object newInstance(TwoTuple... pairs) {
        Class[] interfaces = new Class[pairs.length];
        for(int i = 0; i < pairs.length; i++) {
          interfaces[i] = (Class)pairs[i].second;//second represent XXX.class
        }
        ClassLoader cl =
          pairs[0].first.getClass().getClassLoader();
        return Proxy.newProxyInstance(
          cl, interfaces, new MixinProxy(pairs));
      }
    }   
    
    public class DynamicProxyMixin {
      public static void main(String[] args) {
        Object mixin = MixinProxy.newInstance(
          tuple(new BasicImp(), Basic.class),
          tuple(new TimeStampedImp(), TimeStamped.class),
          tuple(new SerialNumberedImp(),SerialNumbered.class));
        //
        Basic b = (Basic)mixin;
        TimeStamped t = (TimeStamped)mixin;
        SerialNumbered s = (SerialNumbered)mixin;
        b.set("Hello");
        System.out.println(b.get());
        System.out.println(t.getStamp());
        System.out.println(s.getSerialNumber());
      }
    } /* get()
    set()
    getStamp()
    getSerialNumber()
    invoke() is invoked
    invoke() is invoked
    Hello
    invoke() is invoked
    1489219456567
    invoke() is invoked
    1
    *///:~
    
  • 靜態(tài)類型檢查即在程序沒有運(yùn)行時(shí)就能夠通過檢查源代碼確定類型安全蛹疯,與動(dòng)態(tài)類型相對應(yīng)

  • 潛在類型機(jī)制即直接可以用模板T戒财,而不用指定該模板屬于哪個(gè)基類,比如在C++里面就可以直接定義

    template<class T> void perform(T anything) {
      anything.speak();
      anything.sit();
    }
    

    而在java中必須要指明邊界

    class Communicate {
    //must specify the bounds of generic type,but C++ is not necessary
    public static <T extends Performs> void perform(T performer) {
    performer.speak();
    performer.sit();
    }
    }
    
  • java對潛在類型機(jī)制的補(bǔ)償?shù)囊环N方式是反射苍苞,如下

    class CommunicateReflectively {
    //接受一個(gè)Object固翰,然后看是哪個(gè)類
    public static void perform(Object speaker) {
    Class<?> spkr = speaker.getClass();
    try {
    try {
    Method speak = spkr.getMethod("speak");
    speak.invoke(speaker);
    } catch(NoSuchMethodException e) {
    print(speaker + " cannot speak");
    }
    try {
    Method sit = spkr.getMethod("sit");
    sit.invoke(speaker);
    } catch(NoSuchMethodException e) {
    print(speaker + " cannot sit");
    }
    } catch(Exception e) {
    throw new RuntimeException(speaker.toString(), e);
    }
    }
    }
    
  • 15.17中15.17.2與15.17.3,15.17.4沒理解

  • 應(yīng)用于序列的泛型技術(shù)很多都會涉及到Iterable<T>接口

數(shù)組

  • 在java中數(shù)組是一種效率最高的存儲和隨機(jī)訪問對象應(yīng)用序列的方式

  • Comparable接口和Comaprator接口用于排序狼纬,jdk中運(yùn)用策略設(shè)計(jì)模式將“保持不變的事物與會發(fā)生改變的事物相分離”羹呵,代碼如下:

    //Comparable
    class Student implements Comparable<Student>{
        private String name;
        private int age;
        private float score;
        
        public Student(String name, int age, float score) {
            this.name = name;
            this.age = age;
            this.score = score;
        }
        
        public String toString()
        {
            return name+"\t\t"+age+"\t\t"+score;
        }
    
        @Override
        public int compareTo(Student o) {
            // TODO Auto-generated method stub
            if(this.score>o.score)//score是private的,為什么能夠直接調(diào)用,這是因?yàn)樵赟tudent類內(nèi)部
                return -1;//由高到底排序
            else if(this.score<o.score)
                return 1;
            else{
                if(this.age>o.age)
                    return 1;//由底到高排序
                else if(this.age<o.age)
                    return -1;
                else
                    return 0;
            }
        }
    }
    
    public class ComparableDemo01 {
        public static void main(String[] args) {
            // TODO Auto-generated method stub
            Student stu[]={new Student("zhangsan",20,90.0f),
                    new Student("lisi",22,90.0f),
                    new Student("wangwu",20,99.0f),
                    new Student("sunliu",22,100.0f)};
            java.util.Arrays.sort(stu);
            for(Student s:stu)
            {
                System.out.println(s);
            }
        }
    }
    
    //Comparator
    package edu.sjtu.ist.comutil;
    
    import java.util.Comparator;
    
    class Student {
        private String name;
        private int age;
        private float score;
        
        public Student(String name, int age, float score) {
            this.name = name;
            this.age = age;
            this.score = score;
        }
    
        public String getName() {
            return name;
        }
        public void setName(String name) {
            this.name = name;
        }
        public int getAge() {
            return age;
        }
        public void setAge(int age) {
            this.age = age;
        }
        public float getScore() {
            return score;
        }
        public void setScore(float score) {
            this.score = score;
        }
    
        public String toString()
        {
            return name+"\t\t"+age+"\t\t"+score;
        }
    
    }
    
    class StudentComparator implements Comparator<Student>{
    
        @Override
        public int compare(Student o1, Student o2) {
            // TODO Auto-generated method stub
            if(o1.getScore()>o2.getScore())
                return -1;
            else if(o1.getScore()<o2.getScore())
                return 1;
            else{
                if(o1.getAge()>o2.getAge())
                    return 1;
                else if(o1.getAge()<o2.getAge())
                    return -1;
                else 
                    return 0;
            }
        }
        
    }
    public class ComparableDemo02 {
    
        public static void main(String[] args) {
            // TODO Auto-generated method stub
    
            Student stu[]={new Student("zhangsan",20,90.0f),
                    new Student("lisi",22,90.0f),
                    new Student("wangwu",20,99.0f),
                    new Student("sunliu",22,100.0f)};
            java.util.Arrays.sort(stu,new StudentComparator());
            for(Student s:stu)
            {
                System.out.println(s);
            }
        }
    
    }
    
  • 當(dāng)你使用最近的java版本編程時(shí)疗琉,應(yīng)該優(yōu)先選擇容器而不是數(shù)組冈欢,只有在證明性能成為問題時(shí),你才應(yīng)該講程序重構(gòu)為使用數(shù)組

容器源碼解讀

  • 繼承結(jié)構(gòu)代碼如下:
      public interface Iterable<T>{...}
    
    public interface Collection<E> extends Iterable<E>{...}
    public interface Set<E> extends Collection<E>{...}
    public interface SortedSet<E> extends Set<E>{
    Comparator<? super E> comparator();
    
    }
    public interface List<E> extends Collection<E>{...}
    
  • 抽象類實(shí)現(xiàn)接口盈简,可以不用實(shí)現(xiàn)其全部的方法即可以篩選一些方法來實(shí)現(xiàn)凑耻,比如:
interface test{
    void m();
    void f();
  }
  abstract class test2 implements test{
    @Override
    public void m() {
        // TODO Auto-generated method stub
    }
  }
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市柠贤,隨后出現(xiàn)的幾起案子香浩,更是在濱河造成了極大的恐慌,老刑警劉巖臼勉,帶你破解...
    沈念sama閱讀 216,372評論 6 498
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件邻吭,死亡現(xiàn)場離奇詭異,居然都是意外死亡宴霸,警方通過查閱死者的電腦和手機(jī)囱晴,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,368評論 3 392
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來瓢谢,“玉大人畸写,你說我怎么就攤上這事∶タ福” “怎么了枯芬?”我有些...
    開封第一講書人閱讀 162,415評論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經(jīng)常有香客問我千所,道長翅楼,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,157評論 1 292
  • 正文 為了忘掉前任真慢,我火速辦了婚禮毅臊,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘黑界。我一直安慰自己管嬉,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,171評論 6 388
  • 文/花漫 我一把揭開白布朗鸠。 她就那樣靜靜地躺著蚯撩,像睡著了一般。 火紅的嫁衣襯著肌膚如雪烛占。 梳的紋絲不亂的頭發(fā)上胎挎,一...
    開封第一講書人閱讀 51,125評論 1 297
  • 那天,我揣著相機(jī)與錄音忆家,去河邊找鬼犹菇。 笑死,一個(gè)胖子當(dāng)著我的面吹牛芽卿,可吹牛的內(nèi)容都是我干的揭芍。 我是一名探鬼主播,決...
    沈念sama閱讀 40,028評論 3 417
  • 文/蒼蘭香墨 我猛地睜開眼卸例,長吁一口氣:“原來是場噩夢啊……” “哼称杨!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起筷转,我...
    開封第一講書人閱讀 38,887評論 0 274
  • 序言:老撾萬榮一對情侶失蹤姑原,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后呜舒,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體锭汛,經(jīng)...
    沈念sama閱讀 45,310評論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,533評論 2 332
  • 正文 我和宋清朗相戀三年阴绢,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了店乐。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,690評論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡呻袭,死狀恐怖眨八,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情左电,我是刑警寧澤廉侧,帶...
    沈念sama閱讀 35,411評論 5 343
  • 正文 年R本政府宣布页响,位于F島的核電站,受9級特大地震影響段誊,放射性物質(zhì)發(fā)生泄漏闰蚕。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,004評論 3 325
  • 文/蒙蒙 一连舍、第九天 我趴在偏房一處隱蔽的房頂上張望没陡。 院中可真熱鬧,春花似錦索赏、人聲如沸盼玄。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,659評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽埃儿。三九已至,卻和暖如春融涣,著一層夾襖步出監(jiān)牢的瞬間童番,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,812評論 1 268
  • 我被黑心中介騙來泰國打工威鹿, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留剃斧,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 47,693評論 2 368
  • 正文 我出身青樓专普,卻偏偏與公主長得像悯衬,于是被迫代替她去往敵國和親揖庄。 傳聞我的和親對象是個(gè)殘疾皇子筷频,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,577評論 2 353

推薦閱讀更多精彩內(nèi)容

  • mean to add the formatted="false" attribute?.[ 46% 47325/...
    ProZoom閱讀 2,696評論 0 3
  • 50道經(jīng)典Java編程練習(xí)題凝垛,將數(shù)學(xué)思維運(yùn)用到編程中來。抱歉哈找不到文章的原貼了炸渡,有冒犯的麻煩知會聲哈~ 1.指數(shù)...
    OSET我要編程閱讀 6,960評論 0 9
  • Java經(jīng)典問題算法大全 /*【程序1】 題目:古典問題:有一對兔子,從出生后第3個(gè)月起每個(gè)月都生一對兔子丽已,小兔子...
    趙宇_阿特奇閱讀 1,860評論 0 2
  • 小編費(fèi)力收集:給你想要的面試集合 1.C++或Java中的異常處理機(jī)制的簡單原理和應(yīng)用蚌堵。 當(dāng)JAVA程序違反了JA...
    八爺君閱讀 4,587評論 1 114
  • /*【程序21】 * 作者 南楓題目:求1+2!+3!+...+20!的和 1. 程序分析:此程序只是把累加變成了...
    HUC南楓閱讀 434評論 0 0