文章目录
前言
如果您觉得有用的话,记得给博主点个赞,评论,收藏一键三连啊,写作不易啊^ _ ^。
而且听说点赞的人每天的运气都不会太差,实在白嫖的话,那欢迎常来啊!!!
泛型的小千世界(java)
1、泛型
1.1 概述
本质上就是类型参数化。
1.2 好处
1)、对于开发的功能,代码更加灵活
2)、使代码更加简洁
3)、避免强制转换,造成的程序异常
1.3 泛型的特点
【类型擦除】
代码在进入jvm后,泛型会被擦除掉,这时如果该泛型设置了类型上限,那么转换成该类型上限,否则转换成object类型
代码如下(示例)
//未指定上限
public class Test1<T> {
T t;
public T getValue() {
return t;
}
public void setVale(T t) {
this.t = t;
}
}
//指定上限
public class Test2<T extends String> {
T t;
public T getT() {
return t;
}
public void setT(T t) {
this.t = t;
}
}
2、泛型的用法
2.1 泛型接口的列子
利用泛型类声明接口来唱歌
代码如下(示例)
package com.yzy.text;
/*
* 泛型接口
*
* */
interface Computer<E,F>{
//定义两个泛型
void makechorue(E x,F y);
}
class Chorus<E,F>implements Computer <E,F>{
public void makechorue(E x, F y) {
x.toString(); //因为不知道什么类型,所以统一变成字符串
y.toString();
}
}
class Musical{
public String toString(){
System.out.println("| 5 6 3-| 5 17 56|");
return ""; //弹出String型
}
}
class Singer{
public String toString(){
System.out.println("好一朵茉莉花");
return "";
}
}
public class Text57OOP35 {
public static void main(String[] args) {
Chorus<Singer, Musical> model = new Chorus<Singer,Musical>();
Singer singer = new Singer();
Musical musical= new Musical();
model.makechorue(singer, musical);
}
}
效果:
2.2 泛型类例子
利用泛型类来实现求取锥类的体积
代码如下(示例)
/**
* 锥类
* */
class Cone<E>{
double height;
E bottom; //低
public Cone(E bottom) {
this.bottom = bottom;
}
public double computeVolume(){
String s = bottom.toString();
double ss =Double.parseDouble(s);
return 1.0/3.0*ss*height;
}
}
/**
* 圆锥底面积
* */
class CircleA{
double radius, area;
public CircleA(double r) {
radius = r;
}
public String toString(){
area=radius*radius*Math.PI; //Math.PI π的意思
return ""+area; //double型转换成String型
}
}
/**
* 四角锥 底面积
* */
class Rectangle{
double sidA,sidB,area;
public Rectangle(double sidA, double sidB) {
this.sidA = sidA;
this.sidB = sidB;
}
public String toString(){
area =sidA*sidB;
return ""+area;
}
}
public class Text56OOP34 {
public static void main(String[] args) {
CircleA circle = new CircleA(10);
Cone<CircleA> coneone = new Cone<CircleA>(circle);
coneone.height = 30;
System.out.println("圆锥体积:"+coneone.computeVolume());
Rectangle rectangle = new Rectangle(10, 20);
Cone<Rectangle> conetwo = new Cone<Rectangle>(rectangle);
conetwo.height = 40;
System.out.println("四角锥体积:"+conetwo.computeVolume());
}
}
效果:
3.其他
3.1 自定义生成泛型对象
代码如下(示例)
public <E> E objectNewInstance(Class<E> clazz) {
E a = null;
try {
a=clazz.newInstance();
} catch (Exception e1) {
log.error("创建自定义泛型对象错误:{}",e1);
}
return a;
}
使用:
E e = (E) objectNewInstance(DeclaredDlCurveCompanyTimeVo.class);
3.2 泛型对象 转成 class 对象
代码如下(示例)
public void test(List<F> records) {
records.forEach(vo->{
try {
//泛型对象 转成 class 对象
Class<? extends Object> clazz = vo.getClass();
} catch (Exception e) {
log.error("反射错误:{}",vo);
}
});
}
3.3 继承关系的使用
即设置泛型上限,传入的泛型必须是String类型或者是他的子类
代码如下(示例)
public <T extends String> void test(T t) {
}
3.4 依赖关系的使用
F是继承自E。即传入的类型是E类型或者是E类型的子类
代码如下(示例)
public <E, F extends E> void test(E e, F c) {
}
3.5 通配符
注意: 通配符不能用作返回值
如果返回值依赖类型参数,不能使用通配符作为返回值。可以使用类型参数返回:
public <T> T test (T t){
return t;
}
(1) <?> 无限通配符
注意: 无限通配符只能读的能力,没有写的能力。
代码如下(示例)
public void test(List<?> list) {
//只允许读数据
Object o = list.get(0);
//不允许写数据
// list.add("1111");
}
(2) <? extends T> 定义上限 表示参数化类型可能是T 或是 T的派生类(子类);
频繁往外读取内容的,适合用上界Extends。
(3) <? super T> 定义下限 表示参数化类型可能是T 或是 T的基类(父类);
经常往里插入的,适合用下界Super
代码如下(示例)
class A{
}
class B extends A{
}
class C extends B{
}
public class Test {
public static List<B> b = new ArrayList<>();
public static List<C> c = new ArrayList<>();
public static List<A> a = new ArrayList<>();
public static void main(String[] args) {
List<? extends B> listextends = null;
List<? super B> listsuper = null;
//? extends B 表示参数化类型可能是T 或是 T的派生类(子类);
listextends = Test.a; //报错
listextends = Test.b;
listextends = Test.c;
//<? super T> 表示参数化类型可能是T 或是 T的基类(父类);
listsuper = Test.a;
listsuper = Test.b;
listsuper = Test.c; //报错
}
}
效果:
(4) <? super T>和<? extends T> 经典用法
public <T> void copy(List<? super T> dest, List<? extends T> src) {
for (int i = 0; i < src.size(); i++)
dest.set(i, src.get(i));
}
}