------- android培训、java培训、期待与您交流! ----------
泛型的概述:
泛型是一种特殊的类型,它把指定类型的工作推迟到客户端代码声明并实例化类或方法的使用进行。也被称为参数化类型,可以把类型当做参数一样传递过来,在传递过来之前我不明确,但是在使用的时候就就明确了。
泛型出现的原因:
早期的Object类型可以接收任意的对象类型,但是在实际的使用中,会有类型转换的 问题。也就存在这隐患,所以Java提供了泛型来解决这个安全问题。是jdk1.5的新特性。
泛型的好处:
1.提高了程序的安全性
2.将运行期遇到的问题转移到了编译期
3.省去了类型强转的麻烦
泛型的常见应用:
1.泛型类
2.泛型方法
3.泛型接口
Java泛型的工作原理以及类型擦除概述:
Java的泛型是伪泛型。在编译期间,所有的泛型信息都会被擦除掉。正确理解泛型概念的首要前提是理解类型擦除。
Java中的泛型基本上都是在编译器这个层次来实现的。在生产的Java字节码中是不包含泛型中的类型信息的。使用泛型的时候加上的类型参数,会在编译器在编译的时候去掉。这个过程就称为类型擦除。
如在代码中定义的List<Object>和List<String>类型,在编译后都会变成List。JVM看到的只是List,而由泛型附加的类型信息对JVM来说是不可见的。Java编译器会在编译时尽可能的发现可能出错的地方,但是仍然无法避免在运行时刻出现类型转换异常的情况。
类型擦除后保留的原始类型
原始类型就是擦除去了泛型信息,最后在字节码中的类型变量的真正类型。无论何时定义一个泛型类型,相应的原始类型都会被自动地提供。类型变量被擦除,并使用其限定类型(无限定的变量用Object)替代。
泛型的格式:
< 泛型类型 >
注意: 这里的泛型类型可以任意的内容,基本的数据类型,比如 String Person QQ、T、E、K
泛型案例:
public class GenericDemo {
public static void main(String[] args) {
ArrayList<String> list2 = new ArrayList<String>();
list2.add("A1");
list2.add("B1");
list2.add("C1");
// list2.add(123);
for (int i = 0; i < list2.size(); i++) {
String s = list2.get(i);
System.out.println(s);
}
}
}
自定义泛型案例:
案例:使用ArrayList集合,存储自定义对象,并遍历 (泛型版本);
public class GenericDemo {
public static void main(String[] args) {
//创建集合对象 加泛型
ArrayList<Person> list = new ArrayList<Person>();
//创建元素对象
Person p1 = new Person("张三");
Person p2 = new Person("李四");
Person p3 = new Person("王五");
//添加元素到集合
list.add(p1);
list.add(p2);
list.add(p3);
//遍历
Iterator<Person> it = list.iterator();
while (it.hasNext()) {
Person p = it.next();
System.out.println(p.getName());
}
}
}
//自定义类 作为泛型使用
public class Person {
private String name;
public Person() {
super();
}
public Person(String name) {
super();
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
泛型类:
把泛型定义在类上。
格式:public class 类名<泛型类型1,…>
注意:泛型类型必须是引用类型
<QQ> 定义一个泛型
QQ 使用当前这个泛型,这个QQ在程序运行的时候,会对应着一个具体的数据类型
public class Test<QQ> {
private QQ name;
public void setName(QQ name){
this.name = name;
}
public QQ getName(){
return name;
}
}
package cn.itcast_08_Generic_Class;
泛型类测试:
public class QQTest {
public static void main(String[] args) {
//Test t = new Test();
Test<String> t = new Test<String>();
t.setName("呵呵");
System.out.println( t.getName() );
Test<Integer> t2 = new Test<Integer>();
t2.setName(123);
System.out.println( t2.getName() );
}
}
package cn.itcast_09_Generic_Method;
泛型方法:
把泛型定义在方法上
格式:public <泛型类型> 返回类型 方法名(泛型类型 .)
K 的类型是在创建对象的时候 确定的
TT 类型是在调用方法的时候 确定的
这里的K,TT 理解为 是一种数据类型的变量名
注意:创建多个泛型类对象的时候,可以赋值不同的泛型类型,不会产生冲突
public class GenericMethod<K> {
//普通方法
public String method(String str){
return str + "哈哈";
}
//泛型方法
public K function(K str){
return str;
}
//泛型方法
public <TT> TT show(TT str) {
return str;
}
}
package cn.itcast_09_Generic_Method;
泛型方法的测试类:
public class GenericMethodTest {
public static void main(String[] args) {
GenericMethod<String> gm = new GenericMethod<String>();
System.out.println(gm.method("haha"));
String str = gm.function("呵呵");
System.out.println(str);
Integer in = gm.show(123);
System.out.println(in);
}
}
package cn.itcast_10_Generic_Interface;
泛型接口
把泛型定义在接口上
格式:public interface 接口名<泛型类型1…>
public interface Inter<TT> {
public abstract TT show(TT str);
}
package cn.itcast_10_Generic_Interface;
实现泛型接口的类
方式1 : 在编写类的时候实现泛型接口
定义类的时候就确定了泛型的数据类型
public class InterImpl implements Inter<String> {
@Override
public String show(String str) {
return str;
}
}
方式2 :
创建对象的时候,确定泛型的数据类型
InterImpl<QQ> 声明泛型QQ
implements Inter<QQ> 使用QQ 所代表的数据类型
public class InterImpl<QQ> implements Inter<QQ>{
@Override
public QQ show(QQ str) {
return str;
}
}
泛型接口测试类
public class Test {
public static void main(String[] args) {
//方式2
InterImpl<String> impl = new InterImpl<String>();
String str = impl.show("hehe");
System.out.println(str);
//方式1
InterImpl impl = new InterImpl();
String str = impl.show("haha");
System.out.println(str);
}
}
package cn.itcast_11_Generic;
import java.util.ArrayList;
import java.util.Collection;
泛型通配符<?>
任意类型,如果没有明确,那么就是Object以及任意的Java类了
? extends E
向上限定,E及其子类
?代表了 可以是E所对应的数据类型,或者是E的子类类型
例如:
? extends Animal
? 代表了 Animal类型,或者Animal子类类型
? super E
向下限定,E及其父类
?代表了 可以使 E所对应的数据类型,或者是E的父类类型
例如:
? super Dog
? 代表的是 Dog类型,或者是Dog的父类类型
class Animal {
}
class Dog extends Animal {
}
class Cat extends Animal {
}
public class CollectionDemo {
public static void main(String[] args) {
//泛型的数据类型 要求左右一致
//Collection<Object> coll = new ArrayList<Animal>();
//Collection<Animal> coll = new ArrayList<Dog>();
Collection<?> c1 = new ArrayList<Animal>();
Collection<?> c2 = new ArrayList<Dog>();
Collection<?> c3 = new ArrayList<Cat>();
Collection<?> c4 = new ArrayList<Object>();
Collection<?> c10 = new ArrayList<String>();
Collection<?> c11 = new ArrayList<Integer>();
Collection<? extends Animal> c5 = new ArrayList<Animal>();
Collection<? extends Animal> c6 = new ArrayList<Dog>();
Collection<? extends Animal> c7 = new ArrayList<Cat>();
// Collection<? extends Animal> c8 = new ArrayList<Object>(); 因为 Object类型,不是Animal类型或Animal的子类型
Collection<? super Animal> c9 = new ArrayList<Animal>();
// Collection<? super Animal> c10 = new ArrayList<Dog>();// 因为Dog 不是 Animal类型 或者 Animal的父类型
// Collection<? super Animal> c11 = new ArrayList<Cat>();// 因为Cat 不是 Animal类型 或者 Animal的父类型
Collection<? super Animal> c12 = new ArrayList<Object>();
}
}