泛型(Genrics)
所谓泛型就是变量类型的参数化
泛型是JDK1.5中一个最重要的特征。通过引入泛型,我们将获得编译时类型的安全和运行时更小地抛出ClassCastExceptons的可能。
在jdk1.5中,你可以声明一个集合将接收/返回的对象的类型。
泛型的ArrayList
|
public class GenericTest1 { public static void main(String[] args) { List<String> list = new ArrayList<String>(); list.add("aaa"); list.add("bbb"); list.add("ccc"); list.add("ddd");
for(Iterator<String> iter = list.iterator(); iter.hasNext();) { String val = iter.next(); System.out.println(val); } } } |
泛型的LinkedList
|
public class GenericTest2 { public static void main(String[] args) { List<String> list = new LinkedList<String>();
list.add("aaa"); list.add("bbb"); list.add("ccc"); list.add("ddd");
for(Iterator<String> iter = list.iterator(); iter.hasNext();) { String val = iter.next(); System.out.println(val); } } } |
泛型的HashSet
|
public class GenericTest3 { public static void main(String[] args) { Set<String> set = new HashSet<String>();
set.add("aaa"); set.add("bbb"); set.add("ccc"); set.add("ddd");
for(Iterator<String> iter = set.iterator(); iter.hasNext();) { String val = iter.next(); System.out.println(val); } } } |
泛型的HashMap
|
public class GenericTest4 { public static void main(String[] args) { Map<String,String> map = new HashMap<String,String>();
map.put("a","aaa"); map.put("b","bbb"); map.put("c","ccc"); map.put("d","ddd");
Set<String> set = map.keySet();
for(Iterator<String> iter = set.iterator(); iter.hasNext();) { String key = iter.next(); String val = map.get(key); System.out.println(key + ":" + val); }
System.out.println("-----------------------");
Set<Map.Entry<String,String>> set2 = map.entrySet();
for(Iterator<Map.Entry<String,String>> iter = set2.iterator(); iter.hasNext();) { Map.Entry<String,String> entry = iter.next(); String key = entry.getKey(); String val = entry.getValue(); System.out.println(key + ":" + val); }
} } |
如果使用泛型,只要代码在编译时没有出现警告,就不会遇到ClassCastException
自定义一个简单的泛型类
|
public class GenericTest { public static void main(String[] args) { Foo<Integer> f1 = new Foo<Integer>(); Foo<Boolean> f2 = new Foo<Boolean>();
f1.setFoo(new Integer(3)); f2.setFoo(new Boolean(true));
System.out.println(f1.getFoo()); System.out.println(f2.getFoo()); } } class Foo<T> { private T foo; public T getFoo() { return foo; } public void setFoo(T foo) { this.foo = foo; } } |
两个泛型参数的使用和一个参数的使用类似。
|
public class GenericTest2 { public static void main(String[] args) { FooTest<Integer,Boolean> foo = new FooTest<Integer, Boolean>();
foo.setFoo1(new Integer(3)); foo.setFoo2(new Boolean(false));
System.out.println(foo.getFoo1()); System.out.println(foo.getFoo2()); } } class FooTest<T,K> { private T foo1; private K foo2; public T getFoo1() { return foo1; } public void setFoo1(T foo1) { this.foo1 = foo1; } public K getFoo2() { return foo2; } public void setFoo2(K foo2) { this.foo2 = foo2; } } |
泛型数组
|
public class Generic3<T> { private T[] foo; public T[] getFoo() { return foo; } public void setFoo(T[] foo) { this.foo = foo; }
public static void main(String[] args) { Generic3<String> arr = new Generic3<String>();
String[] str1 = {"hello","world","welcome"}; String[] str2 = null;
arr.setFoo(str1); str2 = arr.getFoo();
for(String s : str2) { System.out.println(s); } } } |
用泛型定义一个简单的集合
|
@SuppressWarnings("unchecked") public class SimpleCollection<T> { private T[] arr; private int index = 0; public SimpleCollection() { arr = (T[]) new Object[10]; } public SimpleCollection(int capacity) { arr = (T[]) new Object[capacity]; } public void add(T t) { arr[index++] = t; } public int getLength() { return this.index; } public T get(int i) { return arr[i]; } public static void main(String[] args) { SimpleCollection<Integer> col = new SimpleCollection<Integer>(); for (int i = 0; i < 10; i++) { col.add(new Integer(i)); } for (int i = 0; i < col.getLength(); i++) { System.out.println(col.get(i)); } } } |
将一个泛型对象组合到另一个类中
|
public class GenericFoo<T> { private Generic<T> warpper; public Generic<T> getWarpper() { return warpper; } public void setWarpper(Generic<T> warpper) { this.warpper = warpper; }
public static void main(String[] args) { Generic<Integer> g1 = new Generic<Integer>(); g1.setFoo(new Integer(20));
GenericFoo<Integer> gf = new GenericFoo<Integer>(); gf.setWarpper(g1);
Generic<Integer> g2 = gf.getWarpper(); System.out.println(g2.getFoo()); } } class Generic<T> { private T foo; public T getFoo() { return foo; } public void setFoo(T foo) { this.foo = foo; } } |
在泛型集合中使用自定义类
|
public class Generic2 { public static void main(String[] args) { List<Person> list = new ArrayList<Person>();
list.add(new Person("bob",20,"us")); list.add(new Person("jack",23," list.add(new Person("Mike",25,"cn"));
for(Iterator<Person> iter = list.iterator(); iter.hasNext();) { Person p = iter.next(); System.out.println(p); } } } class Person { private String name; private int age; private String address; public Person(String name, int age, String address) { super(); this.name = name; this.age = age; this.address = address; } 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 String getAddress() { return address; } public void setAddress(String address) { this.address = address; } @Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + ((address == null) ? 0 : address.hashCode()); result = prime * result + age; result = prime * result + ((name == null) ? 0 : name.hashCode()); return result; } @Override public boolean equals(Object obj) { if (this == obj) return true; if (obj == null) return false; if (getClass() != obj.getClass()) return false; Person other = (Person) obj; if (address == null) { if (other.address != null) return false; } else if (!address.equals(other.address)) return false; if (age != other.age) return false; if (name == null) { if (other.name != null) return false; } else if (!name.equals(other.name)) return false; return true; } @Override public String toString() { return name + ", " + age + ", " + address; } } |
限制泛型的可用类型
在定义泛型类别时,预设可以使用任何的类型来实例泛型类型中的类型。
但是如果想要限制使用泛型类别时,只能用某个特定类型或者是其子类型才能实例化该类型时,可以在定义类型时,使用extends关键字指定这个类型必须是继承某个类,或者实现某个接口。
|
public class ListGeneric<T extends List> { private T[] objArr;
public T[] getObjArr() { return objArr; } public void setObjArr(T[] objArr) { this.objArr = objArr; } public static void main(String[] args) { ListGeneric<ArrayList> listGeneric1 = new ListGeneric<ArrayList>(); ListGeneric<LinkedList> listGeneric2 = new ListGeneric<LinkedList>();
ArrayList[] arrList = new ArrayList[3]; listGeneric1.setObjArr(arrList);
LinkedList[] linkList = new LinkedList[3]; listGeneric2.setObjArr(linkList); } } |
当没有指定泛型继承的类型或接口时,默认使用T extends Object ,所在默认情况下任何类型都可以作为参数传入。
如果想要在使用时对泛型类型进行约束,可以使用通配说明<? extends List>
|
public class GenericTest7s { public static void main(String[] args) { //把GenericTest的泛型参数类型限定为指定的类 或接口 GenericTest<? extends List> list = null;
list = new GenericTest<ArrayList>();
list = new GenericTest<LinkedList>();
//把GenericTest的泛型参数类型限定为List的基类。 GenericTest<? super List> list2= null; list2 = new GenericTest<Object>();
GenericTest<String> list3 = new GenericTest<String>();
list3.setList("Hello");
//GenericTest<?>相当于GenericTest<? extends Object> GenericTest<?> list4 = list3;
System.out.println(list4.getList());
//这行会报错,因为list4的参数类型是Object类型的,用其他类型时要强制类型转换。 //违背了使用泛型的初衷。 //list4.setList("World"); } } class GenericTest<T> { private T list; public T getList() { return list; } public void setList(T list) { this.list = list; } } |
使用<?>或是<? extends SomeClass>的声明方式,意味着你只能通过该名称来取得所参考实例的信息,或者是移除某些信息,但不能增加它的信息,因为只知道当中放置的是SomeClass的子类,但不能确定是什么类型的实例,编译器不让你加入信息,理由是,如果可以加入信息的话,那么你就得记得取回的实例是什么类型的,然后再去转换为原来的类型方可进行操作,这样就失去了泛型的意义 。
|
public class GenericTest { public static void main(String[] args) { Foo<? extends Object> f3 = new Foo<String>(); f3.setFoo(null); //编译器会报错,因为你可以插入成功的话,那么取出来时就要进行强制类型转换,这样做就失去了泛型的意义。 f3.setFoo("hello"); } } class Foo<T> { private T foo; public T getFoo() { return foo; } public void setFoo(T foo) { this.foo = foo; } } |
<? super List> 表示泛型类型是List的基类,一般很少用。
List<? extends Object > 通常简写为List<?>
泛型的继承
|
class Parent<T, K> { private T foo1; private K foo2; public T getFoo1() { return foo1; } public void setFoo1(T foo1) { this.foo1 = foo1; } public K getFoo2() { return foo2; } public void setFoo2(K foo2) { this.foo2 = foo2; } } class Child<T, K, V> extends Parent<T, K> { private V foo3; public V getFoo3() { return foo3; } public void setFoo3(V foo3) { this.foo3 = foo3; } } |
实现泛型的接口
|
interface Father<K,V> { public void setKey(K key); public void setValue(V value); } class SubClass<K,V> implements Father<K,V> { private K key; private V value;
@Override public void setKey(K key) { this.key = key; } @Override public void setValue(V value) { this.value = value; } } |
增强for循环
|
public class ForTest { public static void main(String[] args) { int[] arr = {1,2,3,4,5,6}; for(int i : arr) { System.out.println(i); }
System.out.println("----------------------");
ArrayList<String> list = new ArrayList<String>();
list.add("aaa"); list.add("bbb"); list.add("ccc");
for(String str : list) { System.out.println(str); }
System.out.println("----------------------");
int[][] arr2 = {{1,2,3},{4,5,6},{7,8,9}};
for(int[] a : arr2) { for(int i : a) { System.out.println(i); } } } } |
统计命令行中单词出现的次数
|
public class Frequency { public static void main(String[] args) { Map<String,Integer> map = new HashMap<String,Integer>();
for(String word : args) { Integer times = map.get(word); map.put( word, (null == times) ? 1 : (times + 1)); }
System.out.println(map); } } |
自动装箱和拆箱
自动装箱:基本类型自动转为包装类:int --> Integer
自动拆箱:包装类自动转为基本类型:Integer --> int
|
public class AutoBoxingAndUnboxing { public static void main(String[] args) { int i = 3; ArrayList<Integer> list = new ArrayList<Integer>();
list.add(i); list.add(i+3);
for(int ele : list) { System.out.println(ele); } } } |
|
public class AutoBoxingTest { public static void main(String[] args) { Map<String,Integer> map = new HashMap<String,Integer>();
for(String str : args) { if(map.containsKey(str)) { int val = map.get(str); map.put(str,(val+1)); } else { map.put(str,1); } }
Set<Map.Entry<String,Integer>> set = map.entrySet(); for(Map.Entry<String,Integer> entry : set) { String key = entry.getKey(); int val = entry.getValue();
System.out.println(key + ":" + val); } } } |
Integer类有一个缓存,它会缓存介于-128到127之间的整数
|
public class IntCache { public static void main(String[] args) { Integer a = 100; Integer b = 100;
System.out.println(a == b);//true
a = 200; b = 200;
System.out.println(a == b);//false } } |
可变参数
可变参数使程序员可以声明一个接受可变数目参数的方法。
注意:可变参数必须是方法声明中的最后一个参数。
|
public class TestVarArgs { //当有多个参数时, int... args必须是参数表中的最后一个 static void sum(int... args) { int sum = 0; for(int i : args) { sum += i; }
System.out.println(sum); }
public static void main(String[] args) { //相当于C#中的params int[]. sum(1,2); sum(1,2,3,4,5); sum(new int[]{1,2,3}); } } |
枚举
枚举在某种层次上相当于类,和类或接口处于同一级别之上,通常只是用枚举来定义一些常量。
|
public enum Color { Red, Blue, Green } public class ColorTest { public static void main(String[] args) { Color color = Color.Red;
System.out.println(color);
System.out.println();
for(Color col : Color.values()) { System.out.println(col); } } } |
|
public class EnumTest { public static void doOperator(OpConst opConst) { switch(opConst) { case TURN_LEFT: System.out.println("向左转"); break; case TURN_RIGHT: System.out.println("向右转"); break; case SHOOT: System.out.println("射击"); break; } }
public static void main(String[] args) { doOperator(OpConst.TURN_LEFT); doOperator(OpConst.TURN_RIGHT); doOperator(OpConst.SHOOT); } } enum OpConst { TURN_LEFT, TURN_RIGHT, SHOOT } |
定义枚举类型时,本质上就是在定义一个类别,只不过很多细节由编译器帮你完成了,所以某种程序上,enum关键字的作用就是class或interface.
|
public enum Coin { //枚举的实例,默认都是public static final的 Penny("Hello"),Dime("World"),Chome("welcome");
//枚举的属性 private String value;
//枚举的方法,可以被每个实例成员调用 public String getValue() { return this.value; }
//枚举的构造函数 private Coin(String value) { this.value = value; }
public static void main(String[] args) { Coin coin = Coin.Chome; System.out.println(coin.getValue()); } } |
|
|
我们所定义的每个枚举类型都继承自java.lang.Enum类,枚举中的每个成员默认都是public static final的。
每个枚举的成员其实就是你定义的枚举类型的实例。
EnumSet集合的使用
|
public class EnumTest4 { public static void main(String[] args) { //把指定的枚举实例添加到集合中 EnumSet<FontConst> enumSet = EnumSet.of(FontConst.Normal, FontConst.Bold); showEnumTest(enumSet); System.out.println("-----------------");
// complementOf方法,用于获得指定集合中不包含的成员 showEnumTest(EnumSet.complementOf(enumSet)); System.out.println("-----------------");
// noneOf表示用FontConst类型创建一个空的集合 enumSet = EnumSet.noneOf(FontConst.class); enumSet.add(FontConst.Normal); enumSet.add(FontConst.Bold);
showEnumTest(enumSet); }
public static void showEnumTest(EnumSet<FontConst> enumSet) { for(Iterator<FontConst> iter = enumSet.iterator(); iter.hasNext();) { System.out.println(iter.next()); } } } enum FontConst { } |
|
|
枚举集合的拷贝
|
public class EnumSetTest { public static void main(String[] args) { ArrayList<FontConst> list = new ArrayList<FontConst>();
list.add(FontConst.Normal); list.add(FontConst.Bold); list.add(FontConst.Italilc);
//把指定的列表集合拷贝到枚举集合中去 showEnumTest(EnumSet.copyOf(list)); }
public static void showEnumTest(EnumSet<FontConst> enumSet) { for(Iterator<FontConst> iter = enumSet.iterator(); iter.hasNext();) { System.out.println(iter.next()); } } } |
EnumMap的使用
|
public class EnumMapTest { public static void main(String[] args) { Map<Action,String> map = new EnumMap<Action,String>(Action.class);
map.put(Action.TURN_RIGHT,"向右转"); map.put(Action.SHOOT,"射击"); map.put(Action.TURN_LEFT,"向左转");
Set<Action> set = map.keySet(); for(Action key : set) { System.out.println(map.get(key)); } } } enum Action { TURN_LEFT,TURN_RIGHT,SHOOT; } |
一个使用枚举较为合适的场景
|
public class AccessControl { public static void main(String[] args) { AccessRight right = AccessRight.valueOf("MANAGE");
System.out.println(checkRight(right)); }
public static Boolean checkRight(AccessRight right) { if(right == AccessRight.MANAGE) { return true; } return false; } } enum AccessRight { MANAGE,DEPARTMENT,EMPLOYEE; } |
静态导入
在另一个包中如下这个类
|
package com.anllin.common; public class Common { public static final int AGE = 10;
public static void output() { System.out.println(AGE); } } |
在当前包中,静态导入后可以象使用内部类成员一样访问common类的AGE常量。
虽然在一定程度上带来了便利,但会降低程序的可读性。
|
package com.anllin.jdk5; import static com.anllin.common.Common.AGE; import static com.anllin.common.Common.output; public class StaticImportTest { public static void main(String[] args) { int age = AGE; output(); } } |