what
方法在实现的时候,不指定入参/返回值的具体类型,等调用的时候再确定。
类定义,部分成员/方法也可以,等实例化的时候再确定。
核心概念:参数化类型,把类型当作是参数传递。
why
不用指定类型,更通用,不用强制类型转换。
where
使用场景:集合类,不定类型,通用性方法。
how
1.泛型方法
```
public class GenericMethod {
public static void main(String[] args) {
}
// private List convert2Father() {
// List list = new ArrayList<>();
// list.add(1);
// list.add(2);
// // extends 不set
// return list;
// }
// private List convert2Son() {
private Listconvert2Son() {
List list =new ArrayList<>();
list.add(1);
list.add(2);
// super 可set
return list;
}
}
```
```
import java.util.ArrayList;
import java.util.List;
public class GenericRetuenTest {
public static void main(String[] args) {
List superList =getList(Super.class);
System.out.println("superList.size():" + superList.size());
for (Super element : superList) {
System.out.println(element);
}
System.out.println("!!!!!!");
List subAList =getList(SubA.class);
System.out.println("subAList.size():" + subAList.size());
for (SubA element : subAList) {
System.out.println(element);
}
System.out.println("!!!!!!");
List subBList =getList(SubB.class);
System.out.println("subBList.size():" + subBList.size());
for (SubB element : subBList) {
System.out.println(element);
}
System.out.println("!!!!!!");
List stringList =getList(String.class);
System.out.println("stringList.size():" + stringList.size());
for (String element : stringList) {
System.out.println(element);
}
}
private static ListgetList(Class clazz) {
List result =new ArrayList();
Super[] array = {new Super(), new SubA(), new SubB()};
for (Super element : array) {
if (clazz.isAssignableFrom(element.getClass())) {
result.add(clazz.cast(element));
}
}
return result;
}
private static class Super {
@Override
public StringtoString() {
return "Super";
}
}
private static class SubAextends Super {
@Override
public StringtoString() {
return "SubA";
}
}
private static class SubBextends Super {
@Override
public StringtoString() {
return "SubB";
}
}
}
```
2.泛型类
```
public class GenericClassFather {
private T t;
// public static T t;//静态成员,不可泛型
public void setObj(T t) {
this.t = t;
}
public T getObj() {
return this.t;
}
public void show(T t) {
System.out.println(t.toString());
}
}
```
```
public class GenericClassSonStringextends GenericClassFather {
@Override
public void show(T t) {
System.out.println("ObjectToolString:"+t.toString());
}
}
public class GenericClassSonTextends GenericClassFather {
@Override
public void show(T1 t1) {
System.out.println("T:"+t1.toString());
}
}
```
```
import java.util.Date;
public class GenericClassTest {
public static void main(String[] args) {
GenericClassFather tool=new GenericClassFather<>();
tool.setObj("generic");
System.out.println(tool.getObj());
tool.show("qq");
GenericClassFather toolDate=new GenericClassFather<>();
toolDate.setObj(new Date());
System.out.println(toolDate.getObj());
GenericClassSonString genericSonClassString =new GenericClassSonString();
genericSonClassString.show("123");
GenericClassSonT genericClassSonT =new GenericClassSonT();
genericClassSonT.show("345");
}
}
```
**类上声明的泛形只对非静态成员有效**
继承(子类指定类型or不指定)
3.通配符
泛型中的<Object>并不是像以前那样有继承关系的,也就是说List<Object>和List<String>是毫无关系的!!!
不能依靠object类来实现继承,如,List<Object>
3.1 ?号通配符表示可以匹配任意类型,不能set/add,不知道盘子的兜底
3.2List<? extends Number>上界通配符,不能set(子类盖父类内存,盖不住)
3.3<? super >下界通配符,可以set
```
package Generics;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.List;
public class SuperExtends {
public static void main(String[] args) {
List superList =getList(Super.class);
System.out.println("superList.size():" + superList.size());
for (Super element : superList) {
System.out.println(element);
}
System.out.println("*****************************************");
List subAList =getList(SubA.class);
System.out.println("subAList.size():" + subAList.size());
for (SubA element : subAList) {
System.out.println(element);
}
System.out.println("*****************************************");
List subBList =getList(SubB.class);
System.out.println("subBList.size():" + subBList.size());
for (SubB element : subBList) {
System.out.println(element);
}
System.out.println("*****************************************");
List stringList =getList(String.class);
System.out.println("stringList.size():" + stringList.size());
for (String element : stringList) {
System.out.println(element);
}
}
// private static void GenericTest2() {
// //https://blog.csdn.net/w372426096/article/details/78081552
//如果List<S>复合类型是协变的,那么如果S是T的子类,则List<S>也是List<T>的子类。如果List<S>是逆变的,结果颠倒,List<T>会变成List<S>的子类。
//Java中数组是协变的
//Java中泛型是不变的
//<? extends>实现了泛型的协变:List list = new ArrayList();
//<? super>实现了泛型的逆变 :List list = new ArrayList();
//传参要求是协变,返回值要求是逆变的
//
// //直接赋值,泛型不协变
// //父类集合添加子类集合是可以的
// ArrayList arrayList1 = new ArrayList();
// arrayList1.add("123");
// ArrayList<Object> arrayList2 = arrayList1;//直接赋值,泛型不协变
// arrayList1 = new ArrayList<Object>();// 直接赋值,泛型不协变
// ArrayList arrayList2 = new ArrayList<>();
// arrayList2.add(arrayList2.get(0));
// arrayList2.addAll(arrayList1);//父类集合添加子类集合是可以的
//
// //父类=list.get():拿出来往上塞,相当于放到左值(get出来放到父类里,super的话只能放到object里),向上类型转换Object obj = fathers1.get(0);
// //list.set(子类)=list.get(i)=子类:往下放进去,相当于塞右值进去(set进去的只能是子类,extends的话编译器能确定的子类只能是null),向下类型转换 fathers1.add( Son1 ) =》father = son
// //extends 做左值字面意思可协变
// //get:extends的类的左值/向上类型转换:父类
// //set:extends的类的右值/向下类型转换:null
// List fathers1 = new ArrayList<>();
// List son1s = new ArrayList<>();
// List grandpas1 = new ArrayList<>();
//
// fathers1 = son1s; //extends的协变,左右值关系不满足,但是是定义 todo
// grandpas1 = fathers1;//不满足extends的定义 Required type: List<Grandpa> Provided:List<capture of ? extends Father> todo
// fathers1.addAll(son1s);//找右值,null
//
// fathers1.add(new Son1()); //找右值,null
// fathers1.add(new Father());//找右值,null
// fathers1.add(null);//找右值,null
//
// Object obj = fathers1.get(0);//找左值,父类
// Grandpa grandpa = fathers1.get(0);//找左值,父类
// Father father = fathers1.get(0);//找左值,父类
// Son1 son1 = fathers1.get(0);//子类左值父类,不可行赋值逻辑关系
//
// //super 逆变
// //get:super的左值/向上类型转换:object
// //set:super的右值/向下类型转换:子类
// List fathers2 = new ArrayList<>();
// List grandpas2 = new ArrayList<>();
// List son2s = new ArrayList<>();
//
// fathers2 = grandpas2; //super的逆变,左右值关系满足
// grandpas2 = fathers2;//左右值关系不满足
// fathers2.addAll(son2s);
//
// fathers2.add(new Son1());//找右值,子类
// fathers2.add(new Father());//找右值,子类
// fathers2.add(new Grandpa());//错误,找右值,子类 Father =Grandpa 不可行的赋值关系
// fathers2.add(null);//找右值,子类
//
// Object object = fathers2.get(0);//找左值,Object
// Grandpa grandpaa = fathers2.get(0);//找左值 object 如果是父亲(Grandpa)=父亲的父亲(? super Father),就是错误的赋值逻辑
// }
private static void GenericTest() {
//泛型只在编译期间有效,运行时会擦除
ArrayList a =new ArrayList();
ArrayList b =new ArrayList();
ArrayList c =new ArrayList();
List aList =new ArrayList<>();
List aLinkedList =new LinkedList<>();
List asList = Arrays.asList();
System.out.println(a.getClass());
System.out.println(b.getClass());
System.out.println(c.getClass());
System.out.println(aList.getClass());
System.out.println(aLinkedList.getClass());
System.out.println(asList.getClass());
a.add("hello");
Class aClass = a.getClass();
try {
Method aAdd = aClass.getMethod("add", Object.class);
aAdd.invoke(a, 100);
System.out.println(a);
}catch (NoSuchMethodException e) {
e.printStackTrace();
}catch (IllegalAccessException e) {
e.printStackTrace();
}catch (InvocationTargetException e) {
e.printStackTrace();
}
}
// private static List getSubList(List data) {
// List result=new ArrayList<>();
// for (Son1 datum : data) {
// result.add(datum);
// }
// }
private static ListgetList(Class clazz) {
List result =new ArrayList();
Super[] array = {new Super(), new SubA(), new SubB()};
for (Super element : array) {
if (clazz.isAssignableFrom(element.getClass())) {
result.add(clazz.cast(element));
}
}
return result;
}
private static class Super {
@Override
public StringtoString() {
return "Super";
}
}
private static class SubAextends Super {
@Override
public StringtoString() {
return "SubA";
}
}
private static class SubBextends Super {
@Override
public StringtoString() {
return "SubB";
}
}
}
class Grandpa {
static {
System.out.println("爷爷在静态代码块");
}
}
class Fatherextends Grandpa {
static {
System.out.println("爸爸在静态代码块");
}
public static int factor =25;
public Father() {
System.out.println("我是爸爸~");
}
}
class Son1extends Father {
static {
System.out.println("儿子在静态代码块");
}
public Son1() {
System.out.println("我是儿子~");
}
}
```
3.4 通配符和泛型方法
大多时候,我们都可以使用泛型方法来代替通配符的…..
如果参数之间的类型有依赖关系,或者返回值是与参数之间有依赖关系的。那么就使用泛型方法
如果没有依赖关系的,就使用通配符,通配符会灵活一些.
#
泛型:
void onResponse(int err_code, T objData);数据T转为需要的类型,例如List?
泛型参考:SharedPreferencesJsonDAO,注意提前声明类型<T>,记得通配符super和extends,
分类别处理逻辑时,instanceof分支(UserInfoDao)
<? extends T > 所有的泛型类必须<=类T,父类上限是T,?是T的子类。 不能往里存(子类的内容/粒度大于父类,不知道存哪里啊),只能往外取
<? super T> 所有的泛型类必须>=类T,子类的下限是T,?是T的父类。 存正常(基类的粒度/内容都小于T,都可以存下),取必须赋给OBject(不知道父类super向上究竟的界在哪里,只能取最大父类Object)
PECS:producer extends consumer super:频繁存/set要有最大粒度的底盘兜住,所以用super;频繁取/get,用extends,可以取出来放到指定盘子里。
类型转换原则:(内容少的->内容多的,粒度小的->粒度大的,内存小空间->大空间),少的部分赋默认值/方法。
int->double,可以,知识其他的内存填默认值0;
double->int,不可以,内容/精度丢失。
基类=子类(基类指向子类,基类小内容内存覆盖子类多内容,缺失的部分赋默认值,调用子类的默认构造函数);
子类=父类(子类大内存扣在父类小内存上,丢失)。
https://blog.csdn.net/sjm19901003/article/details/44743801
### 动态比类型
- 因为在泛型代码内部,无法获取任何有关泛型参数类型的任何信息!,Java的泛型就是使用擦除来实现的
那如何获取参数类型?——**类型标签Class< T>**
```
class A{}
class Bextends A{}
public class TestInstance {
private Classt;
public TestInstance(Class t){
this.t = t;
}
public boolean compare(Object obj){
return t.isInstance(obj);
// 相当于obj instanceof t
}
public static void main(String[] args) {
TestInstance ti =new TestInstance(A.class);
System.out.println(ti.compare(new A()));
System.out.println(ti.compare(new B()));
}
}
```
网友评论