您的位置:首页 > 编程语言 > Java开发

java泛型的使用

2014-03-30 02:37 399 查看

一、概述

1、概念:泛型就是参数化的类型,使用广泛的类型。

2、作用:

*安全:指定容器要持有什么类型的对象,而且由编译器来保证类型的正确性。

*省心:所有的类型转换都是自动的和隐式的,提高代码的重用率

二、泛型类

1、格式:< 字母列表>

class类名 <字母列表>{

修饰符 字母 属性;

修饰符 构造器 (字母){

}

修饰符 返回类型 方法名(字母){

}

字母列表中的每个字母都代表一种还未确定的引用类型(泛型是在使用时确定具体类型),可以使用任何字母表示,但为了规范使用,一般使用以下常见字母

T 表示Type即类型;

K 和V
分别表示键值中的key和Value

E 表示Element

? 表示不确定的类型(通配符)

2、泛型类在声明时使用泛型,不能将泛型字母使用在静态方法和静态属性上,因为泛型是在使用时确定具体类型,而static是在编译时确定。

3、泛型不能使用基本数据类型,必须使用引用类型,否则编译出错。

下面举一个泛型类的例子说明

public class Student<T1,T2> {
private T1 javaScore;
private T2 oracleScore;

//泛型声明时不能使用 静态属性|静态方法上
//private static T1 test;

public T1 getJavaScore() {
return javaScore;
}

public void setJavaScore(T1 javaScore) {
this.javaScore = javaScore;
}

public T2 getOracleScore() {
return oracleScore;
}

public void setOracleScore(T2 oracleScore) {
this.oracleScore = oracleScore;
}

public static void main(String[] args) {
//使用时指定类型(引用类型)
Student<String,Integer> stu = new Student<String,Integer> ();
//1、安全:类型检查
stu.setJavaScore("优秀");
//2、省心:类型转换
int it =stu.getOracleScore(); //自动拆箱
}

}

三、泛型接口

泛型在接口中的使用与泛型类基本一致,需要注意的是在接口中泛型字母只能使用在方法中,不能使用在全局常量中(接口中的成员变量均为全局常量)。

四、泛型方法

泛型方法就是为方法的返回类型签名,< >位于返回类型前面,泛型方法因为类型还未确定,所以只能访问对象信息,不能修改信息。

五、泛型的擦除

1.擦除:

*在使用时没有指定具体类型

*子类继承|实现时没有指定具体类型

2.后果:

*擦除后不类型检查

*擦除后按Object接收,以Object对待

*存在编译警告,加上Object可以去除,但显得有些画蛇添足

/**
* 父类为泛型类
* 1、属性
* 2、方法
*
* 要么同时擦除,要么子类大于等于父类的类型,
* 不能子类擦除,父类泛型
* 1、属性类型
*  父类中,随父类而定
*  子类中,随子类而定
* 2、方法重写:
*  随父类而定
*/
public abstract class Father<T,T1> {
T name;
public abstract void test(T t);

}
/**
* 子类声明时指定具体类型
* 属性类型为具体类型
* 方法同理
*/
class Child1 extends Father<String,Integer>{
String t2;
@Override
public void test(String t) {
}
}
/**
* 子类为泛型类 ,类型在使用时确定,大于等于父类的类型
* @author Administrator
*
*/
class Child2<T1,T,T3> extends Father<T,T1>{
T1 t2;

@Override
public void test(T t) {

}
}
/**
* 子类为泛型类,父类不指定类型 ,泛型的擦除,使用Object替换
*/
class Child3<T1,T2> extends Father{
T1 name2;
@Override
public void test(Object t) {
// TODO Auto-generated method stub

}
}
/**
* 子类与父类同时擦除
*/
class Child4 extends Father{
String name;
@Override
public void test(Object t) {

}
}
/**
*错误:子类擦除,父类使用泛型
class Child5 extends Father<T,T1>{
String name;
@Override
public void test(T t) {

}
*/


/**
*泛型的擦除
*1、继承|实现声明 不指定类型
*2、使用时 不指定类型
*统一Object 对待
*1、编译器警告 消除使用Object
*2、不完全等同于Object ,编译不会类型检查
*/
public class Student<T> {
private T javaScore;
private T oracleScore;

//泛型声明时不能使用 静态属性|静态方法上
//private static T1 test;

public T getJavaScore() {
return javaScore;
}
public void setJavaScore(T javaScore) {
this.javaScore = javaScore;
}

public T getOracleScore() {
return oracleScore;
}
public void setOracleScore(T oracleScore) {
this.oracleScore = oracleScore;
}

public static void main(String[] args) {
Student stu1 = new Student();
//消除警告 使用 Object
Student<Object> stu = new Student<Object>();
//stu.setJavaScore("af"); //以Object对待

test(stu1); //stu1 相当于Object 但是不完全等同Object
//擦除,不会类型检查
//test(stu);
test1(stu1);
test1(stu);
}

public static  void test(Student<Integer> a){

}
public static  void test1(Student<?> a){

}
}


六、泛型没有多态

public class Fruit {

}
class Apple extends Fruit{

}
public class App {
public static void main(String[] args) {
//A<Fruit> f = new A<Apple>();错误,泛型没有多态
A<Fruit> f =new A<Fruit>();
//test(new A<Apple>());错误
}
//形参使用多态
public static void test(A<Fruit> f){

}
//返回类型使用多态
public static A<Fruit>  test2(){
//return (A<Fruit>)(new A<Apple>());错误
return null;
}
}

七、通配符?、extends和super在泛型中的使用

1.通配符的作用:虽然泛型没有多态,但通过通配符的使用,我们可以实现类似多态的功能。

2.通配符的使用:通配符使用在声明类型|方法上,不能用在声明类或使用时(使用时必须确定类型)。
3.? :表示类型不定,使用时确定类型。
4.? extends classA :表示小于等于,也称作上限,即该类型只能是classA的子类或自身。
5.? super classA :表示大于等于,也称作下限,即该类型只能是classA的父类或自身。
public class Student<T> {
T score;

public static void main(String[] args) {
Student<?> stu = new Student<String>();
test(new Student<Integer>());

test2(new Student<Apple>());
//test3(new Student<Apple>()); //泛型没有多态

//test4(new Student<Apple>()); //<
stu  = new Student<Fruit>();
//test4(stu); //使用时确定类型
test4(new Student<Object>());
test4(new Student<Fruit>());
}

public static void test(Student<?> stu){

}
public static void test3(Student<Fruit> stu){

}
//extends <=
public static void test2(Student<? extends Fruit> stu){

}
//super >=
public static void test4(Student<? super Fruit> stu){

}

}

八、泛型的嵌套

1.声明:嵌套使用泛型
A<B<C>> = new A<B<C>>();
2.使用:从外到内,层层拆分

public class Bjsxt <T>{
T stu ;

public static void main(String[] args) {
//泛型的嵌套
Bjsxt<Student<String>> room =new  Bjsxt<Student<String>>();
//从外到内拆分
room.stu = new Student<String>();
Student<String> stu = room.stu;
String score =stu.score;
System.out.println(score);
}
}

九、没有泛型数组

可以声明泛型数组,但是不能创建泛型数组。虽然如此,但是我们可以通过使用Object接收,再将其强制转换为泛型数组。

public static void main(String[] args) {
Integer[]  arr = new Integer[4];
//Student<String>[] arr2 = new Student<String>[10];
Student<?>[] arr2 = new Student[10];

MyArrayList<String> strList =new MyArrayList<String>();
strList.add(0, "a");
String elem =strList.getElem(0);
System.out.println(elem);}
class MyArrayList<E>{
//E[] cap =new E[10]; 没有泛型数组
Object[] cap = new Object[10];

public void add(int idx,E e){
cap[idx] =e;
}

@SuppressWarnings("unchecked")
public E[] getAll(){
return (E[]) cap;
}
@SuppressWarnings("unchecked")
public E getElem(int idx){
return (E) cap[idx];
}
}


十、JDK7泛型使用的新特性

JDK1.7中使用泛型,声明一次类型即可,在使用|创建时不用指定类型。

 例如List<String>  arrList2= new ArrayList<>();

终于写完了

第一次写博客,有写的不好的地方还望指教。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  java 泛型