
- 泛型和通配符的使用
- 一、泛型的概念
- 1.泛型是什么?
- 2.为什么要有泛型(集合举例)
- 2.1.没有泛型的不足
- 2.2.泛型完善的地方
- 二、自定义泛型
- 1.自定义泛型结构
- 2.泛型类
- 2.1.注意事项
- 3.泛型方法
- 4.泛型继承上面的使用
- 三、通配符及使用
- 1.通配符一般情况使用
- 2.通配符有限制条件的使用
一、泛型的概念 1.泛型是什么?
泛型就是允许在定义类、接口时通过一个标识表示类中某个属性的类型或者是某个方法的返回值及参数类型。这个类型(必须是类,基础类型不可以)参数将在使用时(例如,继承或实现这个接口,用这个类型声明变量、创建对象时)确定(即传入实际的类型参数,也称为类型实参)。
2.为什么要有泛型(集合举例) 2.1.没有泛型的不足/**
* 集合里面如果没有使用泛型的弊端
* 1.没有限制存放的类型,类型不安全
*/
public static void genericInCollection()
{
ArrayList objects = new ArrayList();
objects.add(1);
objects.add(2);
objects.add(3);
objects.add("你好");
for (Object object : objects) {
Integer i = (Integer) object;
//向下转型时候容易引起异常 ClassCastException
System.out.println("i = " + i);
}
}
2.2.泛型完善的地方
/**
* 集合里面使用泛型,创建集合的时候就可以确定类型,类型安全
*/
public static void genericInCollection2()
{
ArrayList<Integer> objects = new ArrayList<>();
objects.add(1);
objects.add(2);
objects.add(3);
// 类型不符合的,编译无法通过
// objects.add("D");
for (Integer object : objects)
{
int i = object;
System.out.println("i = " + i);
}
}
二、自定义泛型
1.自定义泛型结构
/*
* 1.一个类或者接口上面可以有多个的泛型,通常用大写字母表示
* 2.类继承时候的泛型不一定要写,接口实现的时候的泛型一定要写
* 3.实例化的时候需要声明对应的类型,该对象对应的泛型也确定下来
*/
public class GenericClass<X, Y, Z>
{
X x;
Y y;
Z z;
public static void main(String[] args)
{
GenericClass<Integer, String, Double> aClass = new GenericClass<>();
GenericClass<Integer, Double, String> bClass = new GenericClass<>();
}
}
class GenericClass1 extends GenericClass
{
}
interface GenericInter<T>
{
T getCode(T t);
}
class GenericInterClass implements GenericInter<Integer>
{
@Override
public Integer getCode(Integer integer)
{
return integer;
}
}
2.泛型类
public class GenericClass<X>
{
//泛型类型
X x;
//泛型方法
public X getX()
{
return x;
}
//泛型构造器
public GenericClass(X x) {
this.x = x;
}
//泛型构造器
public GenericClass() {
}
public void setX(X x)
{
this.x = x;
}
@Override
public String toString()
{
return "GenericClass{" + "x=" + x + '}';
}
public static void main(String[] args)
{
//实例化的时候没有指明泛型类型,默认为object类型
GenericClass genericClass = new GenericClass();
genericClass.setX(12);
GenericClass1 genericClass1 = new GenericClass1();
genericClass1.setX("123");
}
}
//继承泛型类的子类,可以声明父类的泛型类型,
class GenericClass1 extends GenericClass<String>
{
}
//继承泛型类的子类,也可以全部保留泛型,也可以部分保留泛型
//子类仍是泛型类子类实例化的时候在进行确定
//子类也可以自己新增泛型
class GenericClass2<X> extends GenericClass<X>
{
}
2.1.注意事项
- 异常类不能是泛型
- 静态方法里面不能使用类的泛型(静态方法在类实例化之前,而类的泛型是在类的实例化确定)
//泛型类,如果对应的泛型不相同,不能进行赋值
ArrayList<String> strings = new ArrayList<>();
ArrayList<Integer> integers = new ArrayList<>();
strings = integers;
3.泛型方法
/*
* 泛型方法与其类是否为泛型类无关。
* 在泛型方法中可以定义泛型参数,参数的类型为调用时传入数据的类型。
* 具体格式为:[访问权限] (static) <泛型> 返回类型 方法名([泛型标识 参数名称]) 抛出的异常
*/
public static <T> Boolean genericMethod1(String s,T t)
{
if (t==null) {
return true;
}
return t.toString().length() > s.length();
}
public static void main(String[] args) {
System.out.println("genericMethod1(\"123\",000) = " + genericMethod1("123", 000));
}
4.泛型继承上面的使用
// 如果B是A的一个子类型(子类或者子接口),而G是具有泛型声明的类或接口,
// G并不是G的子类型,无法由父类引用
Object o = new Object();
String s = new String();
o = s;
ArrayList<Object> objects = new ArrayList<>();
ArrayList<String> strings = new ArrayList<>();
// 无法进行赋值
// objects = strings;
// 如果B是A的一个子类型(子类或者子接口),而T是某一个类型
// 则 B是 A的子类型 (参考list和arraylist)
List<String> list = new ArrayList<>();
ArrayList<String> arrayList = new ArrayList<>();
list = arrayList;
三、通配符及使用
1.通配符一般情况使用
public class WildCard1
{
public static void main(String[] args)
{
List<Object> objects = new ArrayList<>();
objects.add(123);
objects.add("a");
objects.add(new Animal<String>("狗"));
List<String> strings = new ArrayList<>();
strings.add("你好");
strings.add("hello world");
// 在泛型的继承上面,G并不是G的子类型,无法由父类引用
// objects = strings;
// 但是 通配符?可以看作是所有泛型的父类
// 也即 G> 是 G和G的父类
List<?> list = objects;
//想要添加数据,由于无法确定类型及其子类,则无法添加
//**null是所有的类型都有的
list.add(null);
list = strings;
print1(objects);
print1(strings);
print2(objects);
print2(strings);
}
// 通配符的方法可以接收所有的泛型,省去各种重载
//读取的类型object,因为object是所有类型的父类,都可以引用
public static void print1(List<?> list)
{
for (Object o : list)
{
System.out.println("print1---o = " + o);
}
}
public static void print2(List list)
{
for (Object o : list)
{
System.out.println("print2---o = " + o);
}
}
}
2.通配符有限制条件的使用
public class WildCard2
{
public static void main(String[] args)
{
// 可以赋值泛型为 Fruit 或者 Fruit子类 实例
List<? extends Fruit> extendList = new ArrayList<>();
// 可以赋值泛型为 Fruit 或者 Fruit父类 实例
List<? super Fruit> superList = new ArrayList<>();
List<Fruit> fruits = new ArrayList<>();
List<apple> apples = new ArrayList<>();
List<Object> objects = new ArrayList<>();
extendList = fruits;
extendList = apples;
extendList = objects;
// 遍历其类型 由最上级的父类 fruit接收
for (Fruit fruit : extendList)
{
}
superList = fruits;
superList = apples;
superList = objects;
// 遍历其类型 由最上级的父类 object 接收
for (Object o : superList)
{
}
}
}
class Fruit
{
}
class apple extends Fruit
{
}
欢迎分享,转载请注明来源:内存溢出
微信扫一扫
支付宝扫一扫
评论列表(0条)