泛型: 就是一种把指定数据类型的工作推迟到创建对象或者调用方法的时候的特殊的类型 , 是一种参数化类型
* 格式:
* <数据类型>
* 数据类型: 必须是引用数据类型
*
* 泛型的好处:
* a: 把运行期的错误提前到了编译期
* b: 省去了向下转型
* c: 去掉了黄色警告线
*/
泛型有三种使用方式,分别为:泛型类、泛型接口、泛型方法
/**
* 自定义泛型类: 就是把泛型定义在类上
* 格式: class 类名<泛型1 , 泛型2 ,....> 泛型标识:可以随便写任意标识号,
标识指定的泛型的类型 常见的如T、E、K、V等形式的参数常用于表示泛型
*/
public class ObjectTools<T> { //定义成员变量的类型
private T t ;
public T getT() {
return t;
}
public void setT(T t) {
this.t = t;
}
public static void main(String[] args) {
ObjectTools<String> objTool1 = new ObjectTools<String>();
objTool1.setT("张三") ;
String t = objTool1.getT() ;
System.out.println(t);
System.out.println("---------------------------------");
ObjectTools<Integer> objTool2 = new ObjectTools<Integer>();
objTool2.setT(20);
Integer t2 = objTool2.getT() ;
System.out.println(t2);
}
}
/**
* 泛型方法: 就是把泛型定义在方法上
* 格式:public <泛型类型> 返回类型 方法名(泛型类型 .)
*/
public class Phone {
public <T> void show(T t) {
// 方法使用的参数不一定要和类上的泛型一致.那么怎么办呢? 把泛型定义在方法上
//<T>这个T是个修饰符的功能,表示是个泛型方法,就像有static修饰的方法是个静态方法一样。
//<T> 不是返回值,表示传入参数有泛型 参数类型是T,T你不知道什么,所以在前面加上一个<T>
System.out.println( t );
}
public static void main(String[] args) {
Phone p = new Phone();
p.show("张三");
p.show(20);
p.show(true);
}
}
同时定义泛型类和泛型方法
class Demo<T> {
public void show(T t) {
System.out.println( "show: " + t );
}
public <Q> void print(Q q) {
System.out.println( "print:" + q );
}
public static void main(String[] args) {
Demo<String> d = new Demo<String>();
d.show( "hello word!" );
d.print( "Cameron Diaz i love you !" );
}
}
/**
* 泛型接口: 就是把泛型定义在接口上
* 格式: public interface 接口名<数据类型> {}
*/
public interface Inter<T> {
public abstract void show(T t) ;
}
/**
* 实现类 在创建子类的时候还不知道是什么类型,这个时候就需要将子类也声明成泛型类
*/
public class InterImpl<T> implements Inter<T> {
@Override
public void show(T t) {
System.out.println(t);
}
}
//实现类在实现接口的时候
//另一种情况:已经知道该是什么类型的了
//public class InterImpl implements Inter<String> {
// @Override
// public void show(String t) {
// System.out.println(t);
// }
//}
泛型方法与可变参数
再看一个泛型方法和可变参数的例子:
修饰符 返回值类型 方法名(数据类型... 变量名) 可变参数的本质上是一个数组
public <T> void printMsg( T... args){
for(T t : args){
Log.d("泛型测试","t is " + t);
}
}
printMsg("111",222,"333","444");
// 如果泛型明确了以后,左右两边必须一致
Collection<Object> col1 = new ArrayList<Object>();
//Collection<Object> col2 = new ArrayList<Animal>();错误的
// ? 表示的任意的意思
Collection<?> col5 = new ArrayList<Object>();
Collection<?> col6 = new ArrayList<Animal>();
Collection<?> col7 = new ArrayList<Dog>();
Collection<?> col8 = new ArrayList<Cat>();
// ? extends E : 向下限定,表示的是E或者E的子类
Collection<? extends Animal> col10 = new ArrayList<Animal>();
Collection<? extends Animal> col11 = new ArrayList<Dog>();
Collection<? extends Animal > col12 = new ArrayList<Cat>();
// ? super E : 向上限定 , 表示的是E或者E的父类
Collection<? super Animal> col13 = new ArrayList<Object>();
Collection<? super Animal> col14 = new ArrayList<Animal>();
class Animal {}
class Dog extends Animal {}
class Cat extends Animal {}
/**
需要引入的jar
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.8.7</version>
</dependency>
定义转换string的泛型方法
*/
public static <T> List<T> readJsonList(String jsondata, Class<T> collectionClass) {
try {
ObjectMapper mapper = new ObjectMapper();
JavaType javaType = mapper.getTypeFactory().constructParametricType(ArrayList.class, collectionClass);
return mapper.readValue(jsondata, javaType);
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
使用:
List<Dog> dogs = JsonUtils.readJsonList1(jsonString, Dog.class);
===============================================================================
//泛型方法反射创建对象
public static <T> T createInstance(Class<T> clazz) throws IllegalAccessException, InstantiationException {
return clazz.newInstance();
}
使用:
Dog dog = createInstance(Dog.class);
Cat cat = createInstance(Cat.class);