java基礎總結 -- 泛型 在類、介面、方法、匿名類、元組等使用 堆疊例子 商店模型
阿新 • • 發佈:2018-12-26
為什麼使用泛型:
在面向物件程式語言中,多型算是一種泛化機制。例如,你可以將方法的引數型別設為基類,那麼
該方法就可以接受從這個基類中匯出的任何類作為引數,這樣的方法更通用一些,可應用的地方也多一點。
在類的內部也是如此,凡是能夠使用基類,確實是能夠具備更好的靈活性。
但單繼承會使程式受限。如果方法引數是一個介面而不是一個類,那麼限制就放鬆多了,因為
任何實現了該介面的類都能滿足該方法,這也包含了不存在的類。這就給客戶端程式設計師一種選擇,它可以通過
實現一個介面來滿足類或方法。因此,介面允許我們快速實現類繼承,也可以建立新的型別來實現這點。
可是有的時候,實現介面,對程式的約束也還是太強了。因為一旦指明瞭介面,方法就需要使用特定的介面。
而我們希望達到的目的是編寫更通用的程式碼,要使程式碼能夠應用於“某種不具體的型別”,而不是一個具體的介面或類。
泛型方法
泛型方法使得該方法能夠獨立於類而發生改變。這個方法鎖在的類可以時泛型類,也可以不是泛型類。
是否擁有泛型方法,與其所在的類是否是泛型沒有關係
無論何時,只要你能做到,你就應該儘量使用泛型方法。如果使用泛型方法可以取代將整個型別泛型化,那麼就應該只
使用泛型方法,因為它可以使事情更清楚明白。
對於一個static的方法而言,無法訪問泛型類的型別引數,所以,如果static方法需要使用泛型能力,就必須使其成為泛型
方法。
在面向物件程式語言中,多型算是一種泛化機制。例如,你可以將方法的引數型別設為基類,那麼
該方法就可以接受從這個基類中匯出的任何類作為引數,這樣的方法更通用一些,可應用的地方也多一點。
在類的內部也是如此,凡是能夠使用基類,確實是能夠具備更好的靈活性。
但單繼承會使程式受限。如果方法引數是一個介面而不是一個類,那麼限制就放鬆多了,因為
任何實現了該介面的類都能滿足該方法,這也包含了不存在的類。這就給客戶端程式設計師一種選擇,它可以通過
實現一個介面來滿足類或方法。因此,介面允許我們快速實現類繼承,也可以建立新的型別來實現這點。
可是有的時候,實現介面,對程式的約束也還是太強了。因為一旦指明瞭介面,方法就需要使用特定的介面。
而我們希望達到的目的是編寫更通用的程式碼,要使程式碼能夠應用於“某種不具體的型別”,而不是一個具體的介面或類。
泛型方法
泛型方法使得該方法能夠獨立於類而發生改變。這個方法鎖在的類可以時泛型類,也可以不是泛型類。
是否擁有泛型方法,與其所在的類是否是泛型沒有關係
無論何時,只要你能做到,你就應該儘量使用泛型方法。如果使用泛型方法可以取代將整個型別泛型化,那麼就應該只
使用泛型方法,因為它可以使事情更清楚明白。
對於一個static的方法而言,無法訪問泛型類的型別引數,所以,如果static方法需要使用泛型能力,就必須使其成為泛型
方法。
要定義泛型方法,只需將泛型引數列表置於返回值之前
package com.zghw.base.generic; /** * 泛型的演變 * * @author zghw * */ public class Develop { class Automobile { } // Holder1直接指明瞭持有物件的型別 class Holder1 { private Automobile automobile; public Holder1(Automobile automobile) { this.automobile = automobile; } public void set(Automobile automobile) { this.automobile = automobile; } public Automobile get() { return automobile; } } // Holder2使用Object作為持有物件的型別更加泛化。 class Holder2 { private Object obj; public Holder2(Object obj) { this.obj = obj; } public void set(Object obj) { this.obj = obj; } public Object get() { return obj; } } // 暫時不指定型別,稍後在決定具體使用的型別,需要使用型別引數 class Holder3<T> { private T t; public Holder3(T t) { this.t = t; } public void set(T t) { this.t = t; } public T get() { return t; } } public static void main(String[] args) { Develop de = new Develop(); // 使用Holder2可以設定不同的型別物件, // 通常我們使用容器來儲存一種型別物件 Holder2 h2 = de.new Holder2(de.new Automobile()); h2 = de.new Holder2("1122"); h2.set(123); h2.set(de.new Automobile()); Automobile a = (Automobile) h2.get();// 明確需要型別轉換 // Holder3<Automobile> h3 = de.new Holder3<Automobile>(de.new Automobile()); Automobile aa = h3.get();// 自動地轉換為正確型別 } }
package com.zghw.base.generic; /** * 元組 它是將一組物件直接打包儲存於其中一個單一物件。這個容器物件允許 讀取其中元素,但是不允許向其中存放新的對專案。也可叫做資料傳遞物件或信使 * 主要用於僅一次方法呼叫就能返回多個物件。 元祖可以具有任意長度,同時,元組中地物件可以是任意不同的型別。不過我們希望能夠為 * 每一個物件指明其型別,並且從容器中讀取出來時,能夠得到正確的型別。要處理不同長度的問題, 我們需要建立多個不同的元祖 * * @author zghw * * @param <A> * @param <B> */ public class TwoTuple<A, B> { // 這裡沒有first和second沒有使用private 並且沒有設定set和get方法 // 而是採用了public final ,因為只為了讀取first 和second // 不用於修改,要向修改需要重新構造新物件放入,final保證了不能修改 public final A first; public final B second; public TwoTuple(A first, B second) { this.first = first; this.second = second; } public String toString() { return "first " + " second "; } }
</pre><pre name="code" class="java">package com.zghw.base.generic;
import java.util.Date;
/**
* 僅一次方法呼叫就能返回多個物件,在開發中經常碰到。 可是return語句只允許返回單個物件,因此,解決辦法就是建立一個物件,用它來持有想要返回的多個
* 物件。可以在每次需要的時候,專門建立一個類來完成這樣的工作。
* 使用元組,只需要定一個長度時適合的元組,將其作為方法的返回值,然後在return語句中建立該元組, 並返回即可。
*
* @author zghw
*
*/
public class TestTuple {
static TwoTuple<Integer,String> returnTwoParam(){
return new TwoTuple<Integer,String>(22,"ss");
}
static ThreeTuple<Integer,Develop,Date> returnThreeParam(){
return new ThreeTuple<Integer,Develop,Date>(22,new Develop(),new Date());
}
public static void main(String[] args) {
System.out.println(returnTwoParam());
System.out.println(returnThreeParam());
}
}
package com.zghw.base.generic;
/**
* 如果使用多元組就使用繼承來實現
*
* @author zghw
*
* @param <A>
* @param <B>
* @param <C>
*/
public class ThreeTuple<A, B, C> extends TwoTuple<A, B> {
public final C three;
public ThreeTuple(A first, B second, C three) {
super(first, second);
this.three = three;
}
public String toString() {
return super.toString() + " three ";
}
}
package com.zghw.base.generic;
/**
* 連結串列的棧,實現了先進後出
*
* @author zghw
*
*/
public class LinkStack<T> {
// 最頂層元素
private Node<T> top = new Node<T>();// 初始化為null
// 入棧 :入棧後當前最頂元素變為下一個元素,最新的最頂層元素為新增的新元素,
public void push(T item) {
top = new Node<T>(item, top);
}
// 出棧:最頂層元素出棧,當前最頂元素變為下一個元素,最新的最頂層元素變為下一個元素
public T pop() {
T result = top.item;
if (!top.end()) {
top = top.next;// 下一個當成當前最頂元素
}
return result;
}
class Node<U> {
U item;
Node<U> next;// next 連結串列主要點 當前物件連線下一個當前物件就形成了連結串列
public Node() {
this.item = null;
this.next = null;
}
public Node(U item, Node<U> next) {
this.item = item;
this.next = next;
}
/**
* 是否時最後一個元素
*
* @return
*/
public boolean end() {
return ((top == null) && (next == null));
}
}
public static void main(String[] args) {
LinkStack<String> s = new LinkStack<String>();
s.push("a");
s.push("b");
s.push("c");
s.push("d");
s.push("e");
System.out.println(s.pop());
System.out.println(s.pop());
System.out.println(s.pop());
System.out.println(s.pop());
System.out.println(s.pop());
System.out.println(s.pop());
}
}
package com.zghw.base.generic;
import java.util.ArrayList;
import java.util.Random;
/**
* 隨機選取一個元素
*
* @author zghw
*
* @param <T>
*/
public class RandomList<T> {
private ArrayList<T> stroage = new ArrayList<T>();
private Random random = new Random(47);
/**
* 隨機選取一個型別例項
*/
public T select() {
return stroage.get(random.nextInt(stroage.size()));
}
public void add(T item) {
stroage.add(item);
}
public static void main(String[] args) {
RandomList<String> rl = new RandomList<String>();
for (String s : "// TODO Auto-generated method stub".split(" ")) {
rl.add(s);
}
for (int i = 0; i < 10; i++) {
System.out.println(rl.select());
}
}
}
package com.zghw.base.generic.coffee;
public class Coffee {
//static + final 聯合使用 全域性計數器
private static int counter=0;
private final int id=counter++;
public String toString(){
return getClass().getSimpleName()+" 建立例項數量:"+id;
}
public static void main(String[] args) {
for(int i=0;i<10;i++){
Coffee c =new Coffee();
System.out.println(c);
}
}
}
package com.zghw.base.generic.coffee;
public class Americano extends Coffee {
}
package com.zghw.base.generic.coffee;
public class Breve extends Coffee {
}
package com.zghw.base.generic.coffee;
public class Cappuccino extends Coffee {
}
package com.zghw.base.generic.coffee;
public class Latte extends Coffee {
}
package com.zghw.base.generic.coffee;
public class Mocha extends Coffee {
}
package com.zghw.base.generic;
import java.util.Iterator;
import java.util.Random;
import com.zghw.base.Generator;
import com.zghw.base.generic.coffee.Americano;
import com.zghw.base.generic.coffee.Breve;
import com.zghw.base.generic.coffee.Cappuccino;
import com.zghw.base.generic.coffee.Coffee;
import com.zghw.base.generic.coffee.Latte;
import com.zghw.base.generic.coffee.Mocha;
/**
* 泛型介面的使用 隨機生成不同的子類物件 Iterable迭代器使用
*
* @author zghw
*
*/
public class CoffeeGenerator implements Generator<Coffee>, Iterable<Coffee> {
// 使用型別資訊陣列儲存類資訊
private Class<?>[] types = new Class<?>[] { Breve.class, Americano.class,
Latte.class, Mocha.class, Cappuccino.class };
private Random random = new Random(47);
private int size = 0;
public CoffeeGenerator() {
}
public CoffeeGenerator(int size) {
this.size = size;
}
@Override
public Coffee next() {
try {// 隨機取得Coffee實現類例項物件
return (Coffee) types[random.nextInt(types.length)].newInstance();
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
@Override
public Iterator<Coffee> iterator() {
return new CoffeeIterator();
}
class CoffeeIterator implements Iterator<Coffee> {
int count = size;
@Override
public boolean hasNext() {
return count > 0;
}
@Override
public Coffee next() {
count--;// 內部類呼叫外部類方法
return CoffeeGenerator.this.next();
}
@Override
public void remove() {
}
}
public static void main(String[] args) {
CoffeeGenerator cg = new CoffeeGenerator();
for (int i = 0; i < 5; i++) {
System.out.println(cg.next());
}
for (Coffee c : new CoffeeGenerator(3)) {
System.out.println(c);
}
}
}
package com.zghw.base;
public interface Generator<T> {
public T next();
}
package com.zghw.base.generic;
/**
* 泛型方法
泛型方法使得該方法能夠獨立於類而發生改變。這個方法鎖在的類可以時泛型類,也可以不是泛型類。
是否擁有泛型方法,與其所在的類是否是泛型沒有關係
無論何時,只要你能做到,你就應該儘量使用泛型方法。如果使用泛型方法可以取代將整個型別泛型化,那麼就應該只
使用泛型方法,因為它可以使事情更清楚明白。
對於一個static的方法而言,無法訪問泛型類的型別引數,所以,如果static方法需要使用泛型能力,就必須使其成為泛型
方法。
要定義泛型方法,只需將泛型引數列表置於返回值之前
* @author zghw
*
*/
//GenericMethods並不是引數化的,儘管這個類和其內部方法可以被同時引數化,但是阻止由方法f()擁有型別引數
//這是由該方法的返回型別前面的型別引數列表指明的
public class GenericMethods {
public <T> void f(T t){
System.out.println(t.getClass().getName());
}
public static void main(String[] args) {
//在使用泛型類時,必須在建立物件的時候指定引數型別的值,而使用泛型方法的時候,不必指明引數型別。
//因為編譯器會為我們找出具體的型別。這被成為型別引數推斷
GenericMethods gm =new GenericMethods();
//我們可以像呼叫普通方法一樣呼叫f(),而且好像是f()被無限次地過載過。它甚至可以接受GenericMethods
//作為其型別引數
//如果呼叫f()時傳入地基本型別,自動打包機制就會介入其中,將基本型別的值包裝為對應的物件。
//事實上,泛型方法與自動打包避免了許多以前我們不得不自己編寫出來的程式碼。
gm.f("");
gm.f(1);
gm.f(1.0);
gm.f(1.0F);
gm.f('c');
gm.f(gm);
}
}
package com.zghw.base.generic;
import java.util.ArrayList;
import java.util.List;
/**
* 泛型方法與可變引數使用
* @author zghw
*
*/
public class GenericVarargs {
public static <T> List<T> makeList(T... args ){
List<T> ls = new ArrayList<T>();
for(T t: args){
ls.add(t);
}
return ls;
}
public static void main(String[] args) {
List<String> ls = GenericVarargs.makeList("11","22","33");
System.out.println(ls);
ls=GenericVarargs.makeList("A B C D E F G H I J K L M N O P Q".split(" "));
System.out.println(ls);
}
}
package com.zghw.base.generic;
import java.util.ArrayList;
import java.util.Collection;
import com.zghw.base.Generator;
import com.zghw.base.generic.coffee.Coffee;
/**
* 利用生成器,填充一個Collection,泛化這種操作很有意義
*
* @author zghw
*
*/
public class Generators {
/**
* 向容器中填充物件
*
* @param coll
* 容器
* @param gen
* 物件生成器
* @param size
* 數量
* @return
*/
public static <T> Collection<T> fill(Collection<T> coll, Generator<T> gen,
int size) {
for (int i = 0; i < size; i++) {
coll.add(gen.next());
}
return coll;
}
public static void main(String[] args) {
Collection<Coffee> cc = fill(new ArrayList<Coffee>(),
new CoffeeGenerator(), 5);
for (Coffee c : cc) {
System.out.println(c);
}
}
}
package com.zghw.base;
import com.zghw.base.generic.coffee.Coffee;
/**
* 為任意類構造一個Generator 滿足條件: (1)必須宣告為public (2)具備預設的建構函式
*
* @author zghw
*
* @param <T>
*/
public class BasicGenerator<T> implements Generator<T> {
private Class<T> type;
public BasicGenerator(Class<T> type) {
this.type = type;
}
@Override
public T next() {
try {
return type.newInstance();
} catch (Exception e) {
throw new RuntimeException();
}
}
public static <T> BasicGenerator<T> create(Class<T> type) {
return new BasicGenerator<T>(type);
}
public static void main(String args[]) {
Generator<Coffee> gr = BasicGenerator.create(Coffee.class);
for (int i = 0; i < 5; i++) {
System.out.println(gr.next());
}
}
}
package com.zghw.base.generic;
import java.util.HashSet;
import java.util.Set;
/**
* 數學關係式 交集 並集 合集
*
* @author zghw
*
*/
public class Sets {
/**
* 合集
*/
public static <T> Set<T> union(Set<T> a, Set<T> b) {
Set<T> reslut = new HashSet<T>(a);
reslut.addAll(b);
return reslut;
}
/**
* 交集
*/
public static <T> Set<T> intersection(Set<T> a, Set<T> b) {
Set<T> reslut = new HashSet<T>(a);
reslut.retainAll(b);
return reslut;
}
/**
* 補集
*/
public static <T> Set<T> complement(Set<T> a, Set<T> b) {
return difference(union(a, b), intersection(a, b));
}
/**
* 除了交集
*/
public static <T> Set<T> difference(Set<T> superset, Set<T> subset) {
Set<T> reslut = new HashSet<T>(superset);
reslut.removeAll(subset);
return reslut;
}
}
package com.zghw.base.generic;
import java.lang.reflect.Method;
import java.util.*;
/**
* java.util包中各種Collection類與Map類之間的方法差異
*
* @author zghw
*
*/
public class ContainerMethodDifferences {
private static Set<String> objSet = methods(Object.class);// Object物件的方法集合
/**
* 取得類對應的方法集合
*
* @return
*/
public static Set<String> methods(Class<?> type) {
Set<String> set = new HashSet<String>();
for (Method m : type.getMethods()) {
set.add(m.getName());
}
return set;
}
public static void interfaces(Class<?> type) {
System.out.println("Interfaces in " + type.getSimpleName());
List<String> list = new ArrayList<String>();
for (Class<?> c : type.getInterfaces()) {
list.add(c.getSimpleName());
}
System.out.println(list);
}
public static void different(Class<?> subClass, Class<?> superClass) {
System.out.println(subClass.getSimpleName() + " extends "
+ superClass.getSimpleName() + " adds:");
Set<String> diff = Sets.difference(methods(superClass),
methods(subClass));
diff.removeAll(objSet);// 去掉Object的方法
System.out.println("= " + diff + "=");
interfaces(superClass);
}
public static void main(String args[]) {
System.out.println("Collection: " + methods(Collection.class));
interfaces(Collection.class);
different(Set.class, Collection.class);
different(HashSet.class, Set.class);
different(LinkedHashSet.class, HashSet.class);
different(TreeSet.class, Set.class);
different(List.class, Collection.class);
different(ArrayList.class, List.class);
different(LinkedList.class, List.class);
different(Queue.class, Collection.class);
different(PriorityQueue.class, Queue.class);
System.out.println("Map: " + methods(Map.class));
different(HashMap.class, Map.class);
different(LinkedHashMap.class, HashMap.class);
different(SortedMap.class, Map.class);
different(TreeMap.class, Map.class);
}
}
package com.zghw.base.generic;
import java.util.ArrayList;
import java.util.Random;
import com.zghw.base.Generator;
/**
* 使用泛型構建商店模型
*
* @author zghw
*
*/
// 商品
class Product {
private int id;
private String desc;
private double price;
public Product(int id, String desc, double price) {
this.id = id;
this.desc = desc;
this.price = price;
System.out.println(this);
}
public String toString() {
return id + " : " + desc + " " + price;
}
public static Generator<Product> gen = new Generator<Product>() {
Random random = new Random(47);
@Override
public Product next() {
return new Product(random.nextInt(1000), "test", Math.round(random
.nextDouble() * 1000.0) + 0.99);
}
};
}
// 貨架
class Self extends ArrayList<Product> {
public Self(int nproduct) {
Generators.fill(this, Product.gen, nproduct);
}
}
// 走廊
class Ailse extends ArrayList<Self> {
public Ailse(int nself, int nproduct) {
for (int i = 0; i < nself; i++) {
add(new Self(nproduct));
}
}
}
public class Store extends ArrayList<Ailse> {
public Store(int nailse, int nself, int nproduct) {
for (int i = 0; i < nailse; i++) {
add(new Ailse(nself, nproduct));
}
}
public String toString() {
StringBuilder result = new StringBuilder();
for (Ailse a : this) {
for (Self s : a) {
for (Product p : s) {
result.append(p);
result.append("\n");
}
}
}
return result.toString();
}
public static void main(String[] args) {
Store store = new Store(1, 2, 2);
System.out.println(store);
}
}