JAVA中的泛型
泛型是一种数据类型参数化以最大限度的进行代码重用的技术。
泛型类的定义:
在类声明的同时通过<>声明泛型参数
<>中声明的类型参数可以用于定义类属性和类方法
Class Lsit<T>{
Void add(T item){
….
}
T get(int i){
T ret = null;
……
Return ret;
}
}
泛型类的使用:
包含泛型声明的类类型可以再定义引用创建对象时候传入类型参数;
传入类型实参后创建的对象是一个在逻辑上处理特定类型的“专用”对象。
Public class test{
Public static void main(String [] args){
List<string> list1 = new List<string>(); //传入类型参数string
List<teacher> list1 = new List<steacher>(); //传入类型参数teacher
深入泛型:
泛型是一种模板
通过泛型可以创建任意个处理特殊类型的类
理论上可以吧任何一个类都定义成泛型类。
实际开发中把容器类型的类定义成泛型类:
链表
栈
队列
可以在定义泛型时候指定任意个的类型参数。
声明引用和创建对象时必须指定所有的类型参数
定义泛型类的构造方法时不需要增加泛型声明。
从泛型类派生子类
泛型类可以传入实际类型参数创建一个实现类,而且可以从泛型类派生子类;
当泛型类作为父类使用时不能再包含类型参数
使用泛型类是如果不指定类型实参,则类型实参默认为object
当泛型类作为父类使用时必须传入实际类型,否则所有类型参数被当做object类处理。
范例:
package org.lxh.demo;
import java.util.*;
class store<T>{
protected Vector<T> items = new Vector<T>();//为vector传入实际类型
void add(T item){
items.add(item);
}
T get(int index){
T ret = null;
try{
ret=items.get(index);
}catch(Exception e){
ret = null;
}
return ret;
}
}
class stringstore extends store<String>{
int size(){
return items.size();
}
String remove (int size){
String ret = null;
ret = get(size);
if(ret != null){
items.remove(size);
}
return ret;
}
}
public class Math{
public static void main(String[] args){
stringstore s =new stringstore();
s.add("java");
s.add("linux");
s.add("android");
while(s.size()>0){
System.out.println(s.remove(0));
}
}
}
运行结果:
java
linux
android
结论:
1、 当定义类和接口时候才可以使用类型参数
2、 当使用类和接口时候必须为类型参数传入实际的类型。
Vector是JAVA系统提供的一个表示一维向量的泛型类。
构造方法摘要 | |||
Vector() |
| ||
|
| ||
方法摘要 | |||
boolean | |||
void | |||
boolean | addAll(Collection<? extends E> c) | ||
boolean | addAll(int index, Collection<? extends E> c) | ||
void | addElement(E obj) | ||
int | capacity() | ||
void | clear() | ||
clone() | |||
boolean | |||
boolean | containsAll(Collection<?> c) | ||
void | |||
elementAt(int index) | |||
elements() | |||
void | ensureCapacity(int minCapacity) | ||
boolean | |||
firstElement() | |||
get(int index) | |||
int | hashCode() | ||
int | |||
int | indexOf(Object o, int index) | ||
void | insertElementAt(E obj, int index) | ||
boolean | isEmpty() | ||
lastElement() | |||
int | lastIndexOf(Object o) | ||
int | lastIndexOf(Object o, int index) | ||
remove(int index) | |||
boolean | |||
boolean | removeAll(Collection<?> c) | ||
void | removeAllElements() | ||
boolean | removeElement(Object obj) | ||
void | removeElementAt(int index) | ||
protected void | removeRange(int fromIndex, int toIndex) | ||
boolean | retainAll(Collection<?> c) | ||
void | setElementAt(E obj, int index) | ||
void | setSize(int newSize) | ||
int | size() | ||
subList(int fromIndex, int toIndex) | |||
Object[] | toArray() | ||
| toArray(T[] a) | ||
toString() | |||
void | trimToSize() | ||
Store类是一个泛型类T为类型参数
Store类中用参数T创建了vector的实现类。
泛型类的本质
JAVA编译器不允许同一个泛型类的不同实现类的引用间赋值;
同一个泛型类的不同实现类的类型是相同的
所有泛型类的实现类对象共享静态属性和方法
静态方法和静态属性不允许使用类型参数。
JAVA中泛型准则:
只要编译时系统没有产生“未经检查的转换”警告,则程序运行时候不会产生ClasscastExecption异常。
泛型类本质
范例:
package org.lxh.demo;
import java.util.*;
class Store<T>{
protected Vector<T> items = new Vector<T>();
void add(T item){
items.add(item);
}
T get(int index){
T ret = null;
try{
ret=items.get(index);
}catch(Exception e){
ret = null;
}
return ret;
}
}
class StringStore extends Store<String>{
int size(){
return items.size();
}
String remove (int size){
String ret = null;
ret = get(size);
if(ret != null){
items.remove(size);
}
return ret;
}
}
public class Math{
public static void main(String[] args){
Store<String> sStore = new Store<String>();
Store<Integer> dStore = new Store<Integer>();
Store s = sStore;
Integer num =1;
dStore.add(num);
s.add(dStore.get(0));
System.out.println(dStore.get(0));
System.out.println(sStore.get(0));
}
}
结果:
1
Exception in thread "main" java.lang.ClassCastException: java.lang.Integer cannot be cast to java.lang.String
at org.lxh.demo.Math.main(Math.java:45)
类型通配符
1、在JAVA中可以定义指向“所有泛型”的泛型类引用
2、在声明泛型类引用时把?当做具体类型传入
注意点:
声明为通用类型的引用不能执行add方法。
因为Add方法无法确认add中T的具体类型。
Get方法可以返回元素的值,虽然不知道T的具体类型,但是总似乎可以确定T就是一个object的对象。
可理解为通配类型的引用的方法只有返回值的类型T被替换为object。
范例:
package org.lxh.demo;
import java.util.*;
class Store<T>{
protected Vector<T> items = new Vector<T>();
void add(T item){
items.add(item);
}
T get(int index){
T ret = null;
try{
ret=items.get(index);
}catch(Exception e){
ret = null;
}
return ret;
}
}
class StringStore extends Store<String>{
int size(){
return items.size();
}
String remove (int size){
String ret = null;
ret = get(size);
if(ret != null){
items.remove(size);
}
return ret;
}
}
public class Math{
public static void print(Store<?> s){
for(int i=0;s.get(i)!=null;i++){
System.out.println(s.get(i));
}
}
public static void main(String[] args){
Store<String> sStore = new Store<String>();
Store<Integer> dStore = new Store<Integer>();
Store<?> oStore = sStore;
sStore.add("java");
sStore.add("linux");
sStore.add("android");
//oStore.add(new Integer(1)); //声明为通用类型的引用不能执行add方法。
dStore.add(1);
dStore.add(2);
dStore.add(3);
print(sStore);
print(dStore);
}
}
结果:
java
linux
android
1
2
3
泛型方法:
可以单独为方法声明类型参数,而不需要将整个类定义为泛型类
定义了类型参数的方法叫做泛型方法
范例:
package org.lxh.demo;
import java.util.*;
class Store<T>{
protected Vector<T> items = new Vector<T>();
void add(T item){
items.add(item);
}
T get(int index){
T ret = null;
try{
ret=items.get(index);
}catch(Exception e){
ret = null;
}
return ret;
}
}
class StringStore extends Store<String>{
int size(){
return items.size();
}
String remove (int size){
String ret = null;
ret = get(size);
if(ret != null){
items.remove(size);
}
return ret;
}
}
public class Math{
public static <T> void copy(T[] array,Store<T> store){
for(int i=0;i<array.length;i++){
store.add(array[i]);
}
}
public static <T> void print(Store<T> store){
for(int i=0;store.get(i)!=null;i++){
System.out.println(store.get(i));
}
}
public static void main(String[] args){
Store<String> sStore = new Store<String>();
Store<Integer> dStore = new Store<Integer>();
Integer[] num = {1,2,3,4,5};
String[] str = {"java","linux","android"};
copy(num,dStore);
copy(str,sStore);
print(dStore);
print(sStore);
}
}
结果:
1
2
3
4
5
java
linux
android
泛型的限制
泛型不支持泛型数组的创建,但是支持泛型数组的引用声明
避免在泛型中创建泛型数组,将数组作为方法参数传入v。