泛型

一、泛型是什么

  泛型本质是指类型参数化。意思是允许在定义类、接口、方法的时候使用类型形参,在真正使用时指定具体类型,所有使用该泛型参数的地方都被统一化,保证类型一致。如果未指定具体类型,默认是Object类型。集合体系中的所有类都增加了泛型,泛型也主要用在集合。

二、为什么需要泛型

  在没有泛型之前(JDK1.5之前),许多错误只能在运行才可以发现,通过引入泛型,可以使其部分错误在编译期就报错,大大提高了代码的健壮性。

   具体好处为:

  • 编译时确定类型,保证类型安全,避免类型转换异常。
  • 免除强制类型转换。
  • 使代码可重用性更高,增加通用性。

三、使用

一般泛型使用的3种方式

// 1、泛型类:T表示任意类型
public class Demo<T> {
	//...
} 

// 2、泛型接口: 和定义类一样(接口就是一个特殊类)
public interface ImplDemo<T,V>{
	// ...
}

// 3、泛型方法:无返回类型
public <T> void demo1(T name){
	System.out.println(name);
}

// 泛型方法:返回泛型类型值
public <T> T demo2(T t){
	return t;
}

四、泛型擦除

public static void main(String[] args) {
    List<String> a = new ArrayList<>();
    List<Integer> b = new ArrayList<>();
    System.out.println(a.getClass());    // class java.util.ArrayList
    System.out.println(b.getClass());    // class java.util.ArrayList
    System.out.println(a.getClass() == b.getClass());    // true
}
// 如上述代码所示,最终系统返回结果是true,说明List<Integer> 和List<String>只是在编译期间有效果,当代码在实际运行时,会自动转化成class java.util.ArrayList

五、什么是通配符

除了用 <T> 表示泛型外,还有 <?> 这种形式。"?"被称为通配符。

六、通配符上、下限

  在JDK集合框架中大量的使用了通配符,可以去参考

<?>				// 无限定通配符
<? extends T>	// 有上限通配符
<? super T> 	// 有下限通配符

七、举例

1、普通泛型

  • 例一:一个泛型类型
// 此处可以随便写标识符号,T是type的简称
class Point<T> {
    // var的类型由T指定,即:在真正使用时由外部指定
    private T value;

    // 返回值的类型由外部决定
    public T getValue() {
        return value;
    }

    // 设置的类型也由外部决定
    public void setValue(T value) {
        this.value = value;
    }
}

public class Test {
    // 测试
    public static void main(String[] args) {
        // 里面的var类型为String类型
        Point<String> a = new Point<>();
        // 设置字符串
        a.setValue("it");
        // 取得字符串的长度
        System.out.println(a.getValue().length());
    }
}
  • 例二:两个泛型类型
class Notepad<K, V> {

    private K key;

    private V value;

    public K getKey() {
        return this.key;
    }

    public V getValue() {
        return this.value;
    }

    public void setKey(K key) {
        this.key = key;
    }

    public void setValue(V value) {
        this.value = value;
    }
}

public class Test {
    //  测试
    public static void main(String[] args) {
        Notepad<String, Integer> t = new Notepad<>();
        t.setKey("汤姆");
        t.setValue(20);
        System.out.print("姓名;" + t.getKey());
        System.out.print(",年龄;" + t.getValue());
    }
}

2、无限定通配符

class Info<T> {
    private T value;

    public T getValue() {
        return value;
    }

    public void setValue(T value) {
        this.value = value;
    }
}

//  测试
public class Test {
    public static void main(String[] args) {
        Info<String> i = new Info<>();
        i.setValue("it");
        fun(i);
    }

    // 可以接收任意的泛型对象
    public static void fun(Info<?> temp) {
        System.out.println("内容:" + temp.getValue());
    }
}

3、有限定通配符

3.1、上限通配符(extends)

class Info<T> {
    private T value;

    public T getValue() {
        return value;
    }

    public void setValue(T value) {
        this.value = value;
    }
}

//  测试
public class Test {
    public static void main(String[] args) {
        Info<Integer> a = new Info<>();
        Info<Float> b = new Info<>();

        a.setValue(30);
        b.setValue(30.1F);

        fun(a);
        fun(b);
    }

    // 只能接收Number子类继承链上的类型
    public static void fun(Info<? extends Number> temp) {
        System.out.print(temp.getValue());
    }
}

3.2、下限通配符(super)

class Info<T> {
    private T value;

    public T getValue() {
        return value;
    }

    public void setValue(T value) {
        this.value = value;
    }
}

// 测试
public class Test {
    public static void main(String args[]) {
        Info<String> a = new Info<String>();
        Info<Object> b = new Info<Object>();
        a.setValue("hello");
        b.setValue(new Object());
        fun(a);
        fun(b);
    }

    // 只能接收 String 父类继承链上的类型
    public static void fun(Info<? super String> temp) {
        System.out.print(temp.getValue());
    }
}

4、泛型类型转换

泛型类型向上、向下均无法转换

class Info<T>{

    private T value;

    public T getValue() {
        return value;
    }

    public void setValue(T value) {
        this.value = value;
    }
}

//  测试
public class Test{
    public static void main(String[] args) {
        Info<String> a = new Info<>();
        Info<Object> b = null;
        // java: 不兼容的类型: T.Info<java.lang.String>无法转换为T.Info<java.lang.Object>
        // b = a;
        // java: 不兼容的类型: T.Info<java.lang.Object>无法转换为T.Info<java.lang.String>
        // a = b;
    }
}

5、泛型接口

  • 子类实现未确定泛型类型的接口,子类也需要将接口的泛型类型一同继承
interface Info<T> {
    T getValue();
}

class InfoImpl<T> implements Info<T> {

    private T value;

    public InfoImpl(T value) {
        this.value = value;
    }

    @Override
    public T getValue() {
        return value;
    }

    public void setValue(T value) {
        this.value = value;
    }
}

public class Test {
    public static void main(String[] args) {
        Info<String> a = new InfoImpl<>("汤姆");
        System.out.println("内容:" + a.getValue());
    }
}
  • 子类实现已确定泛型类型的接口,子类可不指定泛型类型
interface Info<T> {
    T getValue();
}

class InfoImpl implements Info<String> {

    private String value;

    public InfoImpl(String value) {
        this.value = value;
    }

    @Override
    public String getValue() {
        return value;
    }

    public void setValue(String value) {
        this.value = value;
    }
}

public class Test {
    public static void main(String[] args) {
        Info<String> a = new InfoImpl("汤姆");
        System.out.println("内容:" + a.getValue());
    }
}

6、泛型方法

class Demo {
    public <T> T fun(T value) {
        return value;
    }
}

public class Test {
    public static void main(String[] args) {
        Demo a = new Demo();
        
        String b = a.fun("汤姆");
        System.out.println(b);
        
        int c = a.fun(30);
        System.out.println(c);
    }
}

7、泛型参数 + 返回泛型+ 上限通配符

class Info<T extends Number> {
    private T value;

    public T getValue() {
        return value;
    }

    public void setValue(T value) {
        this.value = value;
    }
}

public class Test {
    public static void main(String[] args) {
        Info<Integer> a = fun(30);
        System.out.println(a.getValue());
    }

    public static <T extends Number> Info<T> fun(T param) {
        Info<T> temp = new Info<T>();
        temp.setValue(param);
        return temp;
    }
}

8、泛型参数+返回泛型类型+无限通配符

class Info<T> {
    private T value;

    public T getValue() {
        return value;
    }

    public void setValue(T value) {
        this.value = value;
    }
}

public class Test {
    public static void main(String[] args) {
        Info<String> a = new Info<>();
        Info<Integer> b = new Info<>();
        Info<String> c = new Info<>();

        a.setValue("HELLO");
        b.setValue(123);
        c.setValue("汤姆");

        add(a, b);
        add2(a, b);
        add3(a, b);
        add4(a, c);
    }

    // 穷举
    public static void add(Info<?> a, Info<?> b) {
        System.out.println(a.getValue() + " " + b.getValue());
    }

    public static <ADBCDEF> void add2(Info<?> a, Info<?> b) {
        System.out.println(a.getValue() + " " + b.getValue());
    }

    public static void add3(Info a, Info b) {
        System.out.println(a.getValue() + " " + b.getValue());
    }

    public static <T> void add4(Info<T> a, Info<T> b) {
        System.out.println(a.getValue() + " " + b.getValue());
    }

}

9、泛型数组

public class Test {
    public static void main(String[] args) {
        Integer[] a = fun(1, 2, 3, 4, 5, 6);
        fun2(a);
        String[] b = fun("a", "b", "c");
        fun2(b);
    }

    public static <T> T[] fun(T... arg) {
        return arg;
    }

    public static <T> void fun2(T[] param) {
        System.out.print("接收泛型数组:");
        for (T t : param) {
            System.out.print(t + "\t");
        }
        System.out.println();
    }
}

10、泛型类型复杂嵌套

class Info<K, V> {
    private K key;
    private V value;

    public Info(K key, V value) {
        this.key = key;
        this.value = value;
    }

    public K getKey() {
        return key;
    }

    public void setKey(K key) {
        this.key = key;
    }

    public V getValue() {
        return value;
    }

    public void setValue(V value) {
        this.value = value;
    }
}

class Demo<S> {
    private S info;

    public Demo(S info) {
        this.setInfo(info);
    }

    public void setInfo(S info) {
        this.info = info;
    }

    public S getInfo() {
        return this.info;
    }
}

public class Test {
    public static void main(String[] args) {
        Info<String, Integer> b = new Info<String, Integer>("汤姆", 30);
        Demo<Info<String, Integer>> a = new Demo<Info<String, Integer>>(b);

        System.out.println("内容一:" + a.getInfo().getValue());
        System.out.println("内容二:" + a.getInfo().getValue());
    }
}

11、根据类对象返回泛型值

public class Test {
    public static void main(String[] args) {
        ArrayList<String> a = newArrayList(String.class);
        ArrayList<Integer> b = newArrayList(Integer.class);
        ArrayList<Class> c = newArrayList(Class.class);
    }

    public static <E> ArrayList<E> newArrayList(Class<E> clazz) {
        return new ArrayList<>();
    }
}

八、其它

https://www.jianshu.com/p/0384b0e3641b

https://www.cnblogs.com/sunwei2012/archive/2010/10/08/1845938.html

posted @     阅读(136)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
点击右上角即可分享
微信分享提示