再来看泛型与lambda表达式从Arrays.asList说起~
当时学习泛型和lambda表达式的时候就是一带而过,没有深究,基础不扎实导致不明白问题
今天看了看视频,把泛型和lambda整理了一下。
带着问题来学习,先来看看Arrays源码(注释很重要)
//这是asList方法,它返回的不是util下的ArrayList,而是自己的一个内部类,如下
public static <T> List<T> asList(T... a) {
return new ArrayList<>(a);
}
//这个内部类重写了几乎所有util下的ArrayList的方法,但是没有重写remove和add方法
private static class ArrayList<E> extends AbstractList<E>
implements RandomAccess, java.io.Serializable
{@override}
这个ArrayList会导致很多人产生误会,其实它不是java.util.ArrayList,而是自己的一个内部类
回到正题,来说泛型。
泛型定义在方法上是泛型方法,前边是声明,后边是使用,先声明再使用。举个例子:
public static <T> List<T> asList(T... a) { return new ArrayList<>(a);}
第一个<T>是泛型的声明,第二个<T>是泛型的使用,这个方法的返回值类型是List<T>,<T>在调用这个方法时确定。
再来说一下泛型的类型,泛型分为声明阶段和使用阶段
- 声明阶段:不明确具体类型
- 使用阶段:明确具体类型
注:泛型的默认类型是Object类型
泛型实际上是一种语法糖,我们来谈谈它的优点:
- 代码更加简洁(不用强制转换)
- 程序更加强壮(只要编译不报错,运行就不报错)
- 可读性和稳定性(在编译时就确定了具体类型)
泛型类:泛型定义在类名后,用户使用该类的时候,才把类型明确下来
/*
1:把泛型定义在类上
2:类型变量定义在类上,方法中也可以使用
*/
public class ObjectTool<T> {
private T obj;
public T getObj() {
return obj;
}
public void setObj(T obj) {
this.obj = obj;
}
}
泛型接口:泛型定义在接口名后
/*
把泛型定义在接口上
*/
public interface Inter<T> {
public abstract void show(T t);
}
类型通配符
?通配符表示可以匹配任意类型,任意的java类都可以匹配
注:使用?通配符的时候只能调对象与类型无关的方法,不能调用对象与类型有关的方法
泛型中的<Object>并不是像之前那样有继承关系的了,也就是说List<Object>和List<String>是毫无关系的!!!
下面聊一下Lambda表达式
Lambda表达式是匿名内部类的简写,它实质上是个类,也是一种语法糖
来吧,还是带着例子看问题
// 匿名内部类 创建接口的实现类对象
I1 a1=new I1() {
@Override
public void test(A a) {
a.method();
}
};
// lambda表达式
I1 a2=(A a)->a.method();
// 方法引用
I1 a3=A::method;
感受到Lambda表达式的魅力了嘛(无处安放的魅力啊~~~)
同样的一件事,好几行的代码用Lambda表达式一行就完事了(这就是所谓的语法糖)
Lambda表达式的出现是由于java想拥有函数式编程的思想
函数式接口:接口中只有一个抽象方法
Lambda表达式格式:(参数表)->{方法实现}
注:当参数表中只有一个参数时,()可以不写;当方法实现中只有一行代码且为return时,{}可以不写
java中常用的函数式接口:
- Predicate<T>: T -> boolean test()方法
- Consumer<T>: T->void accept()方法
- Function<T,R>:T->R apply()方法
- Supplier<T>:()-T get()方法
能力有限啊~今天就先聊到这吧。