JDK1.5新特性
泛型(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(); } } |