泛型:
定义泛型的类 :在类名后面加一个尖括号,括号里是一个大写字母,大写字母可以是任何大写字母,意义相同。大写字母表示派生自Object类的任何类
类中泛型的使用:T派生自Object类的任何类,可以把T当成String,Integer,Double等使用
class Point<T>{ //此处可以随便写标识符号
定义变量
private Object x;
private T y;
public Object getX() {
return x;
}
public void setX(Object x) {
this.x = x;
}
public T getY() {//作为返回值
return y;
}
public void setY(T y) {//作为参数
this.y = y;
}
}
泛型类的使用:构造泛型类要在类名后面添加上<>,中间写上要传入的类型,尖括号中传入什么类型,T就代表什么类型
Point<String> p = new Point<String>();
p.setX("sdf");
p.getX();
泛型类实现的优势:
1、使用Object作为返回值,要强制转换成指定类型,使用泛型时,不用强制转换
Point<String> floatPoint = new Point<String>();
floatPoint.setX(10.2f);
floatPoint.setY(10.3f);
Float floatX = (Float)floatPoint.getX();
Float floatY = floatPoint.getY();
2、多泛型变量定义:可以定义多个泛型,用逗号隔开,使用的时候和单个用法一样
定义:
class MorePoint<T,U,K>{
}
使用:MorePoint<String,Integer,Double> morePoint = new MorePoint<String,Integer,Double>();
3、字母规范;任意大写字母都行,为了提高可读性,会使用一些有意义的字母
E——Element,常在java Collection里,如;List<E>,Iterator<E>,Set<E>
K,V——Key,Value, 代表Map的键值对
N——Number,数字
T——Type,类型,如String,Integer等
泛型接口定义及使用:
1、使用方法一:非泛型类继承泛型类和实现泛型接口时,泛型类/泛型接口要填充泛型类型
class InfoImpl implements Info<String>{
......
}
2、使用方法二:泛型类继承泛型类和实现泛型接口时,父泛型类/泛型接口可以不用指定类型,直接用泛型变量就可以
class InfoImpl<T> implements Info<T>{
.........
}
构造多个泛型变量的类
class InfoImpl<T,K,U> implements Info<U>{
.........
}
泛型函数定义及使用
class StaticFans{
静态函数
public static <T> void StaticMethod(T a){
}
普通函数
public <T> void OtherMethod(T a){
}
}
使用静态方法
StaticFans.StaticMethod("adadsda");//使用方法一 不建议用 不利于代码阅读和维护,从外观无法看出调用的是泛型函数
StaticFans.<String>StaticMethod("adadsda");//使用方法二
常规方法使用
StaticFans staticFans = new StaticFans();
staticFans.OtherMethod(new Integer(123));//使用方法一 不建议用 不利于代码阅读和维护,从外观无法看出调用的是泛型函数
staticFans.<Integer>OtherMethod(new Integer(123));//使用方法二
使用Class<T>传递泛型类Class对象:Class<T>也是一泛型,用来装载类的class对象的
定义:
public static <T> List<T> parseArray(String response,Class<T> object){
List<T> modelList = JSON.parseArray(response,object);
return modelList;
}
调用:
Apple.<Integer>parseArray("sdsd",Integer.class);
类型绑定:
定义形式:<T extends BoundingType> T是BoundingType的子类型 T和BoundingType可以是类,也可以是接口,此处的extends表示的子类型,不等同于继承,意思是说T是在BoundingType基础上创建的,具有BoundingType的功能。
定义泛型接口:
public interface Comparable<T> {
public boolean compareTo(T i);
}
实现泛型接口:
public class StringCompare implements Comparable<StringCompare> {
public String mStr;
public StringCompare(String mStr) {
this.mStr = mStr;
}
@Override
public boolean compareTo(StringCompare i) {
if(mStr.length()>i.mStr.length()){
return true;
}
return false;
}
}
绑定接口;
public class Test {
public static <T extends Comparable> T min(T ...a){
T smallest = a[0];
for(T item:a){
if(smallest.compareTo(item)){
smallest=item;
}
}
return smallest;
}
public static void main(String[] args) {
StringCompare min = min(new StringCompare("123"), new StringCompare("456"));
System.out.println(min.mStr);
}
}
绑定类:
父类;
public class Fruit {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
字类:
public class Apple extends Fruit implements Serializable {
public Apple(){
setName("apple");
}
}
绑定类:
public static <T extends Fruit> String getFruitName(T a){
return a.getName();
}
绑定多个限定:
public static <T extends Fruit&Serializable> String getFruitName(T a){
return a.getName();
}
public static <T extends Comparable&Serializable,U extends Runnable> T getFruitName(T a,U u){
....
}
无边界通配符:?
泛型变量T不能直接在代码中使用,只能在类 接口 函数中声明以后才能使用
public class Box<T>{
public T get(){
}
}
?只能用于填充泛型变量T,表示通配任何类型,只是填充方式的一种 例如:Box<?> box=new Box<String>(); 定义变量时填充 不能出现在后面String的位置
通配符?的extends绑定
通配符加限定:<? extends Number>
Point<? extends Number> point;
point = new Point<Number>();//成功赋值 说明extends包括边界
point = new Point<Float>();
point = new Point<Double>();
利用<? extends Number>定义的变量,只可取其中的值,不可修改,因为变量的类型始终是<? extends Number>,是未知类型,无法被设置值
Point<? extends Number> point;
point = new Point<Integer>(3,33);
Number integer_1 = point.getX();
point.setX(new Integer(222));//编译报错
通配符?的super绑定
格式;<? super XXX>
//Employee,Manager,CEO分别代表工人,管理者,CEO Manager派生于Employee,CEO派生于Manager
List<? super Manager> list;
list = new ArrayList<Employee>();
list = new ArrayList<Manager>();//Manager成功赋值说明 super关键字包括边界
list = new ArrayList<CEO>();//报错 CEO是Manager的子类 不是父类
super通配符实例内容:能存不能取,
List<? super Manager> list;
list = new ArrayList<Employee>();
list.add(new Employee());//编译错误 list中item的类型是 <? super Manager> 即Manager的任意父类,编译器无法确定<? super Manager>的具体类型,所以只能存入Manager和它的子类,Employee不一定是<? super Manager>的子类,无法存入
list.add(new Manager());
list.add(new CEO());
Object object = list.get(0);//因为list.get(0)肯定是Object的子类;
Employee employee = list.get(0);//编译错误 list中item的类型是<? super Manager>,编译器能肯定是Manager的父类,不能确定是不是Employee类型,所以报错
构造泛型实例时,如果省略了填充类型,则默认填充为无边界通配符