资料整理:
夯实JAVA基本之二 —— 反射(1):基本类周边信息获取_启舰的博客-CSDN博客
使用整理:
泛型:
泛型是约束类型,分“显示”泛型和“隐示”泛型
显示泛型:
内部定义指定类型,外部调用只能传入指定类型,否则报错
如:
List<String> 只能添加String类数据
隐示泛型:
隐示泛型就是不明确表示类型,而用字母T代表
它跟接口有点类似,实现方不用太担心这个类是由谁来调用,只要在有需要的地方编写功能即可,T的具体类型由调用者来决定
(这里的T可以是任意字母,只代表了Type的缩写,是规范,例如Key,Value的缩写是K,V)
隐士泛型类定义:
class Point<T>
调用:
Point<类型> p = new Point<类型>() ;
隐士多泛型定义:
class MorePoint<T,U>
调用:
MorePoint<类型,类型> p = new MorePoint<类型,类型>() ;
声明时每个之间用逗号隔开,调用时按顺序每个之间用逗号隔开,无最大限度,如果在实例化时想给自定义类型赋值,构造方法里可执行
泛型接口定义:
interface Info<T>
非泛型类直接调用:
class InfoImpl implements Info<String>
泛型类"可"间接调用:
class InfoImpl<T> implements Info<T>
这里把类的T类型直接赋值给接口的T,也就导致最外部调用传的是什么类型,接口也将是什么类型
泛型函数定义:
返回值前定义<T>
public class StaticFans {
//静态函数
public static <T> void StaticMethod(T a){
Log.d("harvic","StaticMethod: "+a.toString());
}
//普通函数
public <T> void OtherMethod(T a){
Log.d("harvic","OtherMethod: "+a.toString());
}
}
调用:
//静态方法
StaticFans.StaticMethod("adfdsa");//使用方法一,根据传入的值来确定泛型的类型
StaticFans.<String>StaticMethod("adfdsa");//使用方法二
//普通函数
除了需要实例化,与上面一样
方法一: 直接传值,任何值都可以(但必须是派生自Object类型,比如String,Integer等),不要用这种隐式传递方式,代码不利于维护。从外观看不出调用的是泛型函数。
方法二:在调用前加了一个<String>来指定<T>的值,这是我们建议的方式。
返回值中存在泛型\Class类泛型:
public static <T> List<T> parseArray(String response,Class<T> object){
List<T> modelList = JSON.parseArray(response, object);
return modelList;
}
Class<T>类传递:
Class<T>传值:
XXXX类.class
定义泛型数组:
定义:
public static <T> T[] fun1(T...arg){ // 接收可变参数
return arg ; // 返回泛型数组
}
使用:
public static void main(String args[]){
Integer i[] = fun1(1,2,3,4,5,6) ;
Integer[] result = fun1(i) ;
}
该示例利用到可变长参数,这里不讲解,不懂可去学
类型绑定:
在运行时,编译器不知道方法内部的T代表什么类型,只有调用者给出类型,它才知道是什么类型
所以在编写时的T默认只能调用Object方法,T肯定是Object的子类
如果我们在编写时,需要泛型类是某一部分类型,这样我们在编写时,可以调用其方法,就可以用到类型绑定
定义:
<T extends BoundingType>
此时的T表示是自定义类的子类型,传入的T可以是类,也可以是接口,BoundingType一样
这时的T就是在父类基础上创建的,拥有父类的所有功能,所以在编写时,就可以调用父类的函数,该继承和正常的extends开销更小,生命周期更短,称之为绑定,脱离了这个范围,它们的继承关系就没了
调用:
参考之前的调用,不同位置会有不同的调用方式
绑定多个类型:
同时绑定多个类型,用&连接
<T extends Fruit&Serializable>
如果是多个泛型,且每个泛型都带绑定,那应该是这个样子
public static <T extends Comparable & Serializable, U extends Runnable> T foo(T a, U b)
调用:
参考之前的调用,不同位置会有不同的调用方式
泛型定义字母规范:
在定义泛型时,用于指定泛型的变量是一个大写字母,为了提高可读性,用有意义的字母比较好,在不同的情境下使用的字母意义如下:
- E — Element,常用在java Collection里,如:List<E>,Iterator<E>,Set<E>
- K,V — Key,Value,代表Map的键值对
- N — Number,数字
- T — Type,类型,如String,Integer等等
无边界通配符:
?就是无边界通配符
?与T的区别:
T只能在类,接口,函数中声明时使用
无边界通配符在定义变量时只是用于填充泛型T,在实例化时才给实际值,实例化给的是什么类型,?就是什么类型
例如:
Point<?> point=new Point<Integer>(3,3);
Point<?> point=Point<Float>(4.3f,4.3f);
构造泛型实例时,如果省略了填充类型,则默认为无边界通配符
Point point=Point<Float>(4.3f,4.3f);
通配符?的extends:
代表该类型实例化时必须直接或间接继承了XX类型,外部只能传入类型不能实例化,T所在类实例化,外部调用继承方法
该继承和正常的extends相比开销更小,生命周期更短,称之为类型绑定,脱离了这个范围,它们的继承关系就没了
声明:
Point<? extends Number> point
示例:
public class myTestClassP extends CommonTools {
}
public class myTestClass<T> {
T testT;
void initT() {
//实例化
testT = (T) new myTestClassP();
}
}
使用:
myTestClass<? extends CommonTools> point = new myTestClass<>();
if (point.testT == null) {
point.initT();
}
//调用继承方法
point.testT.annalLog("1111", false);
通配符?的super绑定:
代表该类型实例化时必须直接或间接继承了XX类型,外部和T所在类都能实例化,外部调用继承方法
(判断是否为继承是包含边界的,也就是XXX类本身)
声明:
<? super XXX> 表示填充为任意XXX类的子类
示例:
public class myTestClass<T> {
T testT;
}
使用:
myTestClass<? super CommonTools> point = new myTestClass<>();
if (point.testT == null) {
//实例化
point.testT = new SellFragmentDom();
}
//调用父类方法
((SellFragmentDom) point.testT).annalLog("super 2222", false);
、