泛型
来源:互联网 发布:知乎ipad客户端 编辑:程序博客网 时间:2024/06/06 05:33
一: 一个元组类库
1. 什么是元组
- 元组能做什么
调用一次方法能够返回多个对象 - 元组特性:
元组可以是任意长度,元组中的长度可以是任意类型 - 实现元组
定义泛型类,通过继承机制实现长度更长的元组
类的属性定义为final是出于安全考虑,外部类不能随意修改 - 实例
package com; class Automobile{}; class cx<A,B>{ public final A a; public final B b; protected cx(A a,B b) { this.a=a; this.b=b; } public A getA() { return a; } public B getB() { return b; } public String toString() { return "("+a+","+b+")"; } } class cx_a<A,B,C> extends cx<A,B> { public final C c; public C getC() { return c; } public cx_a(A a, B b,C c) { super(a, b); this.c=c; // TODO Auto-generated constructor stub } public String toString() { return "("+a+","+b+","+c+")"; } } class cx_b<A,B,C,D> extends cx_a<A,B,C> { public final D d; public cx_b(A a,B b,C c,D d) { super(a,b,c); this.d=d; } public D getD() { return d; } public String toString() { return "("+a+","+b+","+c+","+d+")"; } } public class test<A,B,C,D,E> extends cx_b<A,B,C,D> { private final E e; public test(A a,B b,C c,D d,E e) { super(a,b,c,d); this.e=e; } public E getE() { return e; } public String toString() { return "("+a+","+b+","+c+","+d+","+e+")"; } public static void main(String[] args) { test<String,Integer,String,String,Long> temp=new test<String,Integer,String,String,Long>("a",3,"b","c",(long) 345); System.out.println(temp.toString()); } }
二:一个堆栈类
用LinkedList可以实现栈,这里我们不用LinkedList,采用内部链式存储机制来实现、
Node(3,top)其中的top是Node(2,top)
Node(2,top)其中的top是Node(1,top)
public class LinkedStack<T> { private static class Node<U> { U item; Node<U> next; Node() { item = null; next = null; } Node(U item, Node<U> next) { this.item = item; this.next = next; } boolean end() { return item == null && next == null; } } private Node<T> top = new Node<T>(); // End sentinel 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; } public static void main(String[] args) {// LinkedStack<String> lss = new LinkedStack<String>();// for(String s : "Phasers on stun!".split(" "))// lss.push(s);// String ss;// while((ss = lss.pop()) != null)// System.out.println(ss); //----- if put integer into the LinkedList LinkedStack<Integer> lii = new LinkedStack<Integer>(); for(Integer i = 0; i < 10; i++){ lii.push(i); } Integer end; while((end = lii.pop()) != null) System.out.println(end); //----- integer test end! } }
三:RandomList
class RandomList<T> { private ArrayList<T> storage = new ArrayList<T>(); private Random rand = new Random(47); public void add(T item) { storage.add(item); } public T select() { return storage.get(rand.nextInt(storage.size())); } public static void main(String[] args) { RandomList<String> rs = new RandomList<String>(); for(String s: ("The quick brown fox jumped over " + "the lazy brown dog").split(" ")) rs.add(s); for(int i = 0; i < 11; i++) System.out.print(rs.select() + " "); } }
四:泛型接口
package generics;import java.util.Iterator;import java.util.Random;interface Generator<T> { T next();}// 方法next()的返回类型是参数化的T。正如你所见到的,接口使用泛型与类使用泛型没什么区别。// 为了演示如何实现Generator接口,我们还需要一些别的类。例如,Coffee类层次结构如下:// Java代码 收藏代码class Coffee { private static long counter;// 编号,初始值为0 private final long id = counter++; public String toString() { return getClass().getSimpleName() + " " + id; }}class Mocha extends Coffee {}class Latte extends Coffee {}class Breve extends Coffee {}// 现在,我们可以编写一个类,实现Generator<Coffee>接口,它能够随机生成不同类型的Coffee对象:// Java代码 收藏代码public class CoffeeGenerator implements Generator<Coffee>, Iterable<Coffee> { private Class[] types = { Latte.class, Mocha.class, Breve.class, }; private static Random rand = new Random(47); public CoffeeGenerator() { } // 为了使用For循环对该类实例进行迭代时次数控制: private int size = 0; public CoffeeGenerator(int sz) { size = sz; } public Coffee next() { try { // 随机返回一个Coffee实例 return (Coffee) types[rand.nextInt(types.length)].newInstance(); } catch (Exception e) { throw new RuntimeException(e); } } // 实现Iterator接口,这里属于黑箱迭代子模式 private class CoffeeIterator implements Iterator<Coffee> { int count = size; public boolean hasNext() { return count > 0; } public Coffee next() { count--; // 调用外部类的next方法,所以前面要明确指定外部类类型, // 不然的话就是调用内部类自身的方法了 return CoffeeGenerator.this.next(); } public void remove() { // Not implemented throw new UnsupportedOperationException(); } }; // 向外界提供迭代器的实现,这样可以用在foreach循环语句中 public Iterator<Coffee> iterator() { return new CoffeeIterator(); } public static void main(String[] args) { CoffeeGenerator gen = new CoffeeGenerator();// 不使用迭代接口Iterator进行迭代时,由程序外部自己控制迭代过程 for (int i = 0; i < 5; i++) { /* * 某次输出: Breve 0 Breve 1 Mocha 2 Breve 3 Mocha 4 */ System.out.println(gen.next()); } /* * 使用增加for循环,CoffeeGenerator实现了Iterable接口,所以它可以在 * 循环语句中使用。使用迭代子模式时迭代过程由迭代器来控制 */ for (Coffee c : new CoffeeGenerator(5)) { /* * 某次输出: Breve 5 Mocha 6 Breve 7 Latte 8 Mocha 9 */ System.out.println(c); } }}
使用Generator<T>
接口生成斐波那契数列
public class Fibonacci implements Generator<Integer> { protected 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(); //输出0-9的斐波拉契 for (int i = 0; i < 10; i++) { /* * Output: 1(0) 1(1) 2(2) 3(3) 5(4) 8(5) 13(6) 21(7) 34(8) 55(9) */ System.out.print(gen.next()); } } public int getIndex() { return count - 1; } }
五:泛型方法
1.泛型方法比泛型类的优势之处:
(1)泛型方法使得方法能够独立于类而产生变化
(2)调用方法时调用static方法更方便,但是static方法无法访问泛型类的类型参数,所以如果static方法需要使用泛型能力,就必须成为泛型方法。
(3)使用泛型方法时通常不用指明参数类型(因为编译器会为我们找出具体的类型,这称为类型参数判断),而使用泛型类时必须在创建对象时指定类型参数的值
例:
//泛型方法public class GenericMethods { public <T> void f(T x){ System.out.println(x.getClass().getName()); } public static void main(String[] args) { GenericMethods gm = new GenericMethods(); gm.f(""); gm.f(1); gm.f(1.0); gm.f(1.0f); gm.f(1.0f); gm.f('c'); gm.f(gm); }}
2.杠杆利用类型参数推断
首先是一个静态方法:
class New1 { public static <K, V> Map<K, V> map(){ return new HashMap<K, V>(); } // 然后可以这样创建一个Map: public static void test(String[] args){ Map<String, List<Cat>> catMap = New.map(); }}
可以发现,右边的不用再按照以前的这种写法了:
Map<String, List> catMap = new HashMap<String, List>();
左边声明部分的类型为右边提供了一种推断,使得编译器可以直接创造出来具体的类了。不过,这种场景没有声明,直接使用New.map()是编译不通过的,因为没有像这里左边的可以推断的依据了, 如下面的,加入f()是一个方法,需要传入一个Map,如下的写法是编译不通过的:
f(New.map());
如果确实还是想按照上面那样使用,则可以考虑使用显示类型说明了,在操作符与方法名直接插入尖括号显示的指明类型,代码如下:
F(New.<Person, List>map());
不过这种方式很少使用。也就是说,在编写非赋值语句时,才要这样的说明,而使用不了杠杆利用类型推断。
我们为了方便,可以使用同样的方式创建其他的容器了,可惜JDK本身没有提供这样的类:
class New { public static <K,V> Map<K,V> map() { return new HashMap<K,V>(); } public static <T> List<T> list() { return new ArrayList<T>(); } public static <T> LinkedList<T> lList() { return new LinkedList<T>(); } public static <T> Set<T> set() { return new HashSet<T>(); } public static <T> Queue<T> queue() { return new LinkedList<T>(); } // Examples: public static void test(String[] args) { Map<String, List<String>> sls = New.map(); List<String> ls = New.list(); LinkedList<String> lls = New.lList(); Set<String> ss = New.set(); Queue<String> qs = New.queue(); }}
3.可变参数也是可以使用泛型声明类型的:
public class GenericVarargs { 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("A","B","C","D","E"); System.out.println(ls); }}
- 泛型
- 泛型
- 泛型
- 泛型
- 泛型
- 泛型
- 泛型
- 泛型
- 泛型
- 泛型
- 泛型
- 泛型
- 泛型
- 泛型
- 泛型
- 泛型
- 泛型
- 泛型
- 决策树
- 关于服务器的运行寿命 你应该知道这些
- angular.js:14199 Error: [$rootScope:inprog]的成因及解决办法
- C语言中的位操作符的应用
- 将源代码一步打包成deb包的脚本
- 泛型
- 复制数组改良
- 20171027Link
- 欢迎使用CSDN-markdown编辑器
- PL/SQL
- Codeforces 711C 树DP 解题报告
- c的多种用法
- instcat.sql sqlserver数据链路 sqlserver2008连接2000报错
- 08打开r40m平台Android6.0下的TF卡(分色排版)