Java泛型
来源:互联网 发布:php用户信息管理系统 编辑:程序博客网 时间:2024/06/05 00:33
Why
JDK1.5增加泛型支持在很大程度上是为了让集合能记住其元素的数据类型。在没有泛型前,一旦把一个对象“丢进”java集合中,集合就会忘记对象的类型,把所有对象当成Object类型处理。当程序从集合中取出对象后,就需要进行强制类型转换,这种强制类型转换不仅使代码臃肿,而且容易引起ClassCastException异常。
增加了泛型支持后的集合的优点:
- 可以记住集合中元素的类型,并可以在编译时检查集合中元素的类型,如果试图向集合中添加不满足类型要求的对象,编译器就会提示错误;
- 可以让代码更加简洁,程序更加健壮;
除此之外,Java泛型还增强了枚举类、反射等方面的功能。
总结起来就是在编译时会检查类型安全,并且所有的强制转换都是自动和隐式的,以提高代码重用率。
import java.util.List;import java.util.ArrayList;public class Solution { public static void main(String[] args) { //创建一个只想保存字符串的List集合 List strList = new ArrayList(); strList.add("疯狂java讲义"); strList.add("疯狂Android讲义"); //“不小心”把一个Integer对象“丢进”了集合 strList.add(5); //① strList.forEach(str->System.out.println(((String)str).length())); //② }}
What、When、Where
所谓泛型,就是允许在定义类、接口、方法时使用类型形参,这个类型形参将在声明变量、创建对象、调用方法时动态地指定。
泛型的本质是参数化类型,也就是说所操作的数据类型被指定为一个参数。
这种参数类型可以用在类、接口和方法的创建中,分别称为泛型类、泛型接口、泛型方法。
Java引入泛型的好处是安全简单。
规则限制
- 泛型的类型参数只能是类类型(包括自定义类),不能是简单类型;
- 同一种泛型可以对应多个版本(因为参数类型是不确定的),不同的版本的泛型类实例是不兼容的;
- 泛型的类型参数可以有多个;
- 泛型的参数类型可以使用extends语句,例如< T extends superclass>。习惯上称为“有界类型”;
- 泛型的参数类型还可以是通配符类型。例如Class< ? > classType = Class.forName(“java.lang.String”).
How
1、定义泛型接口、类
public class Apple<T> { private T info; public Apple(){} public Apple(T info) { this.info = info; } public void setInfo(T info) { this.info = info; } public T getInfo() { return this.info; } public static void main(String[] args) { Apple<String> a1 = new Apple<>("苹果"); System.out.println(a1.getInfo()); Apple<Double> a2 = new Apple<>(5.67); System.out.println(a2.getInfo()); }}
注意:当创建泛型类声明自定义类,为该类定义构造函数时,构造函数名还是原来的类名,不要增加泛型声明。例如,为Apple< T>类定义构造函数,其构造函数名依然是Apple,而不是Apple< T>!调用该构造函数时却可以使用Apple< T>的形式,当然应该为T形参传入实际的类型参数。Java7提供了菱形语法,允许省略< >中的类型参数。
事实上,并不存在泛型类,例如,
import java.util.List;import java.util.ArrayList;public class Test { public static void main(String[] args) { List<String> l1 = new ArrayList<>(); List<Integer> l2 = new ArrayList<>(); System.out.println(l1.getClass()==l2.getClass()); }}
结果为true,因为不管泛型的实际类型参数是什么,他们在运行时总有同样的类(class)处理,在内存中也只占用一块内存空间,因此在静态方法、静态初始化块或者静态变量声明和初始化中不允许使用类型形参。比如下面代码:
public class R<T> { //下面代码错误,不能在静态变量声明中使用类型参数 static T info; T age; public void foo(T msg){} //下面代码错误,不能在静态方法声明中使用类型参数 public static void bar(T msg){}}
由于系统并不会真正生成泛型类,所以intanceof运算符后不能使用泛型类。例如,下面代码是错误的:
java.util.Collection<String> cs = new java.util.ArrayList<>();//下面代码编译时引起错误if(cs intanceof java.util.ArrayList<String>(){}
2、设定类型通配符的上限
//定义一个抽象类Shapepublic abstract class Shape { public abstract void draw(Canvas c);}//定义一个Shape的子类Circlepublic class Circle extends Shape { public void draw(Canvas c) { System.out.println("在画布"+c+"上画一个圆"); }}//定义一个Shape的子类Rectanglepublic class Rectangle extends Shape { public void draw(Canvas c) { System.out.println("在画布"+c+"上画一个矩形"); }}public class Canvas { public void drawAll(List<? extends Shape> shapes) { for(Shape s : shapes) { s.draw(this); } }}
List< ? extends Shape > 是受限制通配符的例子,此处的问号(?)代表一个未知的类型,但是此处的这个未知类型一定是Shape的子类型,因此可以把Shape称为这个通配符的上限。
3、定义泛型方法
泛型方法的语法格式如下:
修饰符 <T,S> 返回值类型 方法名(形参列表){ //方法体}
- 【java 2】java泛型
- Java 泛型 Java generic
- Java Tutorials_Generics(java泛型)
- Java基础 Java 泛型
- java 泛型
- java泛型
- Java泛型
- Java泛型
- java泛型
- java泛型
- java泛型
- Java 泛型
- Java泛型
- Java 泛型
- JAVA 泛型
- java 泛型
- java泛型
- Java泛型
- ubuntu配置tomcat
- [django]django后台css样式丢失
- 第十一周项目2.2 将继承方式protect改为private 改法一
- 常见的与内部类相关的笔试面试题
- Google机器学习教程心得(一)
- Java泛型
- 第十一周项目2.2 将继承方式protect改为private 改法二
- GCJ Round 1B 2016
- pat L2-1. 紧急救援——dijkstra
- Java 高效并发
- linux下使用aria2c + chrome插件取代迅雷
- JAVA流程控制
- jQuery实现点击全选和取消全选
- POJ3278Catch That Cow(BFS)