泛型
泛型的概念
编译时检查非法的类型数据结构,本质就是参数化类型,也就是所操作的数据类型被指定为类型数据结构.
泛型类
定义语法
class 类名称<泛型标识,泛型标识,...>{
private 泛型标识 变量名;
......
}
常用泛型标识:T E K V
泛型类注意事项
泛型类,如果没有指定具体的数据类型,此时,操作类型是Ob;ject
泛型的类型参数只能是类类型,不能是基本数据类型
泛型类型在逻辑上可以看成是多个不同的类型,但实际上都是相同类型
eg1
public class Generic<T> {
private T key;
public Generic(T key) {
this.key = key;
}
public T getKey() {
return key;
}
public void setKey(T key) {
this.key = key;
}
@Override
public String toString() {
return "Generic{" +
"key=" + key +
'}';
}
}
public class MainClass {
public static void main(String[] args) {
Generic<String> strGeneric=new Generic<>("a");
String key1 = strGeneric.getKey();
System.out.println(key1);
Generic<Integer> integerGeneric=new Generic<>(123);
Integer key2 = integerGeneric.getKey();
System.out.println(key2);
//不指定泛型,默认为Object类型,int 不是继承自Object所以不能作为限定类型
Generic generic=new Generic("ABC");
Object key3 = generic.getKey();
System.out.println(key3);
//泛型不支持基本数据类型
//Generic<int> generic1=new Generic<int>(100);
//同一泛型类,根据不同的数据类型创建的对象,本质上是同一类型
System.out.println(strGeneric.getClass());
System.out.println(integerGeneric.getClass());
System.out.println(strGeneric.getClass()==integerGeneric.getClass());
}
}
eg2:模拟抽奖器
public class ProductGetter
Random random=new Random();
//奖品
private T product;
//奖品池
ArrayList<T> list=new ArrayList<>();
//添加奖品
public void addProduct(T t){
list.add(t);
}
//抽奖
public T getProduct(){
product=list.get(random.nextInt(list.size()));
return product;
}
}
public static void main(String[] args) {
//创建抽奖器对象,指定数据类型
ProductGetter<String> stringProductGetter=new ProductGetter<>();
String[] strProduct={"苹果手机","华为手机","扫他机器人","咖啡机"};
//给抽奖器中填充奖品
for (int i=0;i<strProduct.length;i++){
stringProductGetter.addProduct(strProduct[i]);
}
String product = stringProductGetter.getProduct();
System.out.println("恭喜您抽中了:"+product);
}
}
泛型类派生子类
子类也是泛型类,子类和父类的泛型类型要一致
class ChildGeneric
子类不是泛型类,父类要明确泛型的数据类型
class ChildGeneric extends Generic
eg:
public class Parent<E> {
private E value;
public E getValue() {
return value;
}
public void setValue(E value) {
this.value = value;
}
}
public class ChildFirst<T,E,K> extends Parent<T>{
@Override
public T getValue() {
return super.getValue();
}
}
public class ChildSecond extends Parent<Integer>{
@Override
public Integer getValue() {
return super.getValue();
}
@Override
public void setValue(Integer value) {
super.setValue(value);
}
}
public class MainClass {
public static void main(String[] args) {
ChildFirst<String> childFirst=new ChildFirst<>();
childFirst.setValue("abc");
String value = childFirst.getValue();
System.out.println(value);
ChildSecond childSecond=new ChildSecond();
childSecond.setValue(100);
Integer value1 = childSecond.getValue();
System.out.println(value);
}
}
泛型接口
定义
interface 接口名称<泛型标识,泛型标识,...>{
泛型标识 方法名();
......
}
泛型接口的使用
实现类不是泛型类,接口要明确实现接口的数据类型
实现类也是泛型类,实现类要包含泛型接口的泛型标识,可以扩展
public interface Generator<T> {
T getKey();
}
//对应a
public class Apple implements Generator<String>{
@Override
public String getKey() {
return "hello generic";
}
}
//对应b
public class Pair<T,E> implements Generator<T>{
private T key;
private E value;
public Pair(T key, E value) {
this.key = key;
this.value = value;
}
@Override
public T getKey() {
return key;
}
public E getValue() {
return value;
}
}
public class Test05 {
public static void main(String[] args) {
Apple apple=new Apple();
String key = apple.getKey();
System.out.println(key);
Pair<String,Integer> pair=new Pair<>("count",100);
String key1 = pair.getKey();
Integer value = pair.getValue();
System.out.println(key1+":"+value);
}
}
泛型方法
泛型类,是在实例化类的时候指明泛型的具体类型
泛型方法,是在调用方法的时候指明泛型的具体类型
语法
修饰符<T,E,..>返回值类型 方法名(形参列表)
方法体...
public与返回值中间
泛型类中的使用了泛型的成员方法并不是泛型方法。
与泛型类的定义一样,此处T可以随便写为任意标识,常见的如T、E、K、V等形式的参数常用于表示泛型。
泛型方法可变参数
public <E> void print(.. e){
for (E el :e){
System.out.println(e);
}
}
/**
* 抽奖器
* @param <T>
*/
public class ProductGetter<T> {
Random random=new Random();
//奖品
private T product;
//奖品池
ArrayList<T> list=new ArrayList<>();
//添加奖品
public void addProduct(T t){
list.add(t);
}
//抽奖
public T getProduct(){
product=list.get(random.nextInt(list.size()));
return product;
}
/**
* 定义泛型方法
* @param list 参数
* @param <E>泛型标识,具体类型,由调用方法的时候指定
* @return
*/
public <E> E getProduct(ArrayList<E> list){
return list.get(random.nextInt(list.size()));
}
/**
* 静态的泛型方法,采用多个泛型类型
* @param t
* @param e
* @param k
* @param <T>
* @param <E>
* @param <K>
*/
public static <T,E,K> void printType(T t, E e, K k){
System.out.println(t + "\t" + t.getClass().getSimpleName());
System.out.println(e +"\t" +e.getClass().getSimpleName());
System.out.println(k + "\t" + k.getClass().getSimpleName ());
}
/**
* 泛型可变参数的定义
* @param e
* @param <E>
*/
public static <E> void print(E... e){
for (int i = 0; i < e.length; i++) {
System.out.println(e[i]);
}
}
}
泛型方法总结
泛型方法能使方法独立于类而产生变化
如果 static 方法要使用泛型能力,就必须使其成为泛型方法
类型通配符
类型通配符一般是使用"?"代替具体的类型实参
所以,类型通配符是类型实参,而不是类型形参
public class Box<E> {
private E first;
public E getFirst() {
return first;
}
public void setFirst(E first) {
this.first = first;
}
}
public class Test07 {
public static void main(String[] args) {
Box<Integer> box1=new Box<>();
box1.setFirst(12);
showBox(box1);
}
public static void showBox(Box<?> box){
Object first = box.getFirst();
System.out.println(first);
}
}
类型通配符上限
语法
类/接口<?extends 实参类型>
要求该泛型的类型,只能是实参类型,或实参类型的子类类型
public class Test08 {
public static void main(String[] args) {
ArrayList<MinCat> minCats=new ArrayList();
ArrayList<Cat> cats=new ArrayList();
ArrayList<Animal> animals=new ArrayList<>();
showAnimal(minCats);
showAnimal(cats);
// showAnimal(animals); 会报错
}
public static void showAnimal(ArrayList<? extends Cat> list){
for (int i = 0; i < list.size(); i++) {
Cat cat = list.get(i);
System.out.println(cat);
}
}
}
类型通配符下限
语法
类/接口<?super 实参类型>
要求该泛型的类型,只能是实参类型,或实参类型的父类类型。
多了一个info方法,擦除类型后
泛型数组
泛型数组的创建
可以声明带泛型的数组引用,但是不能直接创建带泛型的数组对象
//报错的写法
ArrayList
//正确的写法
ArrayList
以下方式是有弊端的
public class Test10 {
public static void main(String[] args) {
ArrayList[] list=new ArrayList[5];
ArrayList<String>[] listArr=list;
ArrayList<Integer> intList=new ArrayList<>();
intList.add(100);
list[0]=intList;
String s = listArr[0].get(0);
System.out.println(s);
}
}
Exception in thread "main" java.lang.ClassCastException: java.lang.Integer cannot be cast to java.lang.String
at com.itheima.demo10.Test10.main(Test10.java:13)
可以通过java.lang.reflect.Array的newInstance(Class<T>,int)创建T[]数组
import java.lang.reflect.Array;
public class Fruit <T>{
private T[] array;
public Fruit(Class<T> clz,int length) {
//通过Array.newInstance创建泛型数组
array = (T[])Array.newInstance(clz, length);
}
public void put(int index,T item){
array[index]=item;
}
public T get(int index){
return array[index];
}
public T[] getArray(){
return array;
}
}
泛型与反射
反射常用的泛型类
Class
Constructor
public class Person {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
public class Test11 {
public static void main(String[] args) throws Exception {
Class<Person> personClass1 = Person.class;
Constructor<Person> constructor1 = personClass1.getConstructor();
Person person1 = constructor1.newInstance();
System.out.println(person1);
Class personClass2 = Person.class;
Constructor constructor2 = personClass2.getConstructor();
Object o = constructor2.newInstance();
System.out.println(o);
}
}
标签:void,class,println,ArrayList,泛型,public
From: https://www.cnblogs.com/pp531/p/17536602.html