2024年java泛型使用基础

java泛型使用基础1 为什么需要泛型 2 泛型类型 2 1 泛型类 2 2 泛型接口 3 泛型方法 4 类型擦除 5 泛型和继承 6 类型边界 7 类型通配符 7 1 上界通配符 7 2 下界通配符 7 3 无界通配符 7 4 通配符和向上转型 8 泛型的约束 9 泛型**实践 9 1 泛型命名 9 2 使用泛型的建议 10 小结 11 参考资料 1 为什么需要泛型

大家好,我是讯享网,很高兴认识大家。



1. 为什么需要泛型

2. 泛型类型

2.1. 泛型类

2.2. 泛型接口

3. 泛型方法

4. 类型擦除

5. 泛型和继承

6. 类型边界

7. 类型通配符

7.1. 上界通配符

7.2. 下界通配符

7.3. 无界通配符

7.4. 通配符和向上转型

8. 泛型的约束

9. 泛型**实践

9.1. 泛型命名

9.2. 使用泛型的建议

10. 小结

11. 参考资料

#1. 为什么需要泛型

public class NoGenericsDemo {

    public static void main(String[] args) {

        List list = new ArrayList<>();

        list.add("abc");

        list.add(18);

        list.add(new double[] {1.0, 2.0});

        Object obj1 = list.get(0);

        Object obj2 = list.get(1);

        Object obj3 = list.get(2);

        System.out.println("obj1 = [" + obj1 + "]");

        System.out.println("obj2 = [" + obj2 + "]");

        int num1 = (int)list.get(0);

        int num2 = (int)list.get(1);

        int num3 = (int)list.get(2);

        System.out.println("num1 = [" + num1 + "]");

        System.out.println("num2 = [" + num2 + "]");

        System.out.println("num3 = [" + num3 + "]");

    }

}

// Output:

// obj1 = [abc]

// obj2 = [18]

// obj3 = [[D@47089e5f]

// Exception in thread "main" java.lang.ClassCastException: java.lang.String cannot be cast to java.lang.Integer

// at io.github.dunwu.javacore.generics.NoGenericsDemo.main(NoGenericsDemo.java:23)

编译时的强类型检查

避免了类型转换

List list = new ArrayList();

list.add("hello");

String s = (String) list.get(0);

List<String> list = new ArrayList<String>();

list.add("hello");

String s = list.get(0);  // no cast

泛型编程可以实现通用算法

#2. 泛型类型

#2.1. 泛型类

class name<T1, T2, ..., Tn> { /* ... */ }

未应用泛型的类

public class Info {

public Object getValue() {

return value;

public void setValue(Object value) {

this.value = value;

}

}

单类型参数的泛型类

public class Info<T> {

    public Info(T value) {

        this.value = value;

    public T getValue() {

        return value;

    public void setValue(T value) {

        this.value = value;

    @Override

    public String toString() {

        return "Info{" + "value=" + value + '}';

    }

public class GenericsClassDemo01 {

    public static void main(String[] args) {

        Info<Integer> info = new Info<>();

        info.setValue(10);

        Info<String> info2 = new Info<>();

        info2.setValue("xyz");

        System.out.println(info2.getValue());

    }

}

// Output:

// 10

// xyz

public static void main(String[] args) {

    Info info = new Info();

    info.setValue(10);

    System.out.println(info.getValue());

    info.setValue("abc");

    System.out.println(info.getValue());

}

多个类型参数的泛型类

public class MyMap<K,V> {

    private K key;

    public MyMap(K key, V value) {

        this.key = key;

        this.value = value;

    @Override

    public String toString() {

        return "MyMap{" + "key=" + key + ", value=" + value + '}';

    }

public class GenericsClassDemo02 {

    public static void main(String[] args) {

        MyMap<Integer, String> map = new MyMap<>(1, "one");

        System.out.println(map);

    }

}

// Output:

// MyMap{key=1, value=one}

泛型类的类型嵌套

public class GenericsClassDemo03 {

    public static void main(String[] args) {

        Info<String> info = new Info("Hello");

        MyMap<Integer, Info<String>> map = new MyMap<>(1, info);

        System.out.println(map);

    }

}

// Output:

// MyMap{key=1, value=Info{value=Hello}}

#2.2. 泛型接口

public interface Content<T> {

    T text();

}

public class GenericsInterfaceDemo01 implements Content<Integer> {

    public GenericsInterfaceDemo01(int text) {

        this.text = text;

    @Override

    public static void main(String[] args) {

        GenericsInterfaceDemo01 demo = new GenericsInterfaceDemo01(10);

        System.out.print(demo.text());

    }

}

// Output:

// 10

实现接口的子类不明确声明泛型类型

public class GenericsInterfaceDemo02<T> implements Content<T> {

    public GenericsInterfaceDemo02(T text) {

        this.text = text;

    @Override

    public static void main(String[] args) {

        GenericsInterfaceDemo02<String> gen = new GenericsInterfaceDemo02<>("ABC");

        System.out.print(gen.text());

    }

}

// Output:

// ABC

#3. 泛型方法

public <T> T func(T obj) {}

public class GenericsMethodDemo01 {

    public static <T> void printClass(T obj) {

        System.out.println(obj.getClass().toString());

    public static void main(String[] args) {

        printClass("abc");

        printClass(10);

    }

}

// Output:

// class java.lang.String

// class java.lang.Integer

public class GenericVarargsMethodDemo {

    public static <T> List<T> makeList(T... args) {

        List<T> result = new ArrayList<T>();

        Collections.addAll(result, args);

        return result;

    public static void main(String[] args) {

        List<String> ls = makeList("A");

        System.out.println(ls);

        ls = makeList("A", "B", "C");

        System.out.println(ls);

    }

}

// Output:

// [A]

// [A, B, C]

#4. 类型擦除

把泛型中的所有类型参数替换为 Object,如果指定类型边界,则使用类型边界来替换。因此,生成的字节码仅包含普通的类,接口和方法。

擦除出现的类型声明,即去掉 <> 的内容。比如 T get() 方法声明就变成了 Object get() ;List<String> 就变成了 List。如有必要,插入类型转换以保持类型安全。

生成桥接方法以保留扩展泛型类型中的多态性。类型擦除确保不为参数化类型创建新类;因此,泛型不会产生运行时开销。

public class GenericsErasureTypeDemo {

    public static void main(String[] args) {

        List<Object> list1 = new ArrayList<Object>();

        List<String> list2 = new ArrayList<String>();

        System.out.println(list1.getClass());

        System.out.println(list2.getClass());

    }

}

// Output:

// class java.util.ArrayList

// class java.util.ArrayList

#5. 泛型和继承

List<Integer> list = new ArrayList<>();

List<Object> list2 = list; // Erorr

#6. 类型边界

<T extends XXX>

public class GenericsExtendsDemo01 {

    static <T extends Comparable<T>> T max(T x, T y, T z) {

        T max = x; // 假设x是初始最大值

        if (y.compareTo(max) > 0) {

            max = y; //y 更大

        }

        if (z.compareTo(max) > 0) {

            max = z; // 现在 z 更大

        }

        return max; // 返回最大对象

    public static void main(String[] args) {

        System.out.println(max(3, 4, 5));

        System.out.println(max(6.6, 8.8, 7.7));

        System.out.println(max("pear", "apple", "orange"));

    }

}

// Output:

// 5

// 8.8

// pear

<T extends B1 & B2 & B3>

public class GenericsExtendsDemo02 {

    static class A { /* ... */ }

    interface B { /* ... */ }

    interface C { /* ... java泛型使用基础*/ }

    static class D1 <T extends A & B & C> { /* ... */ }

    static class D2 <T extends B & A & C> { /* ... */ } // 编译报错

    public static void main(String[] args) {

        D1<E> demo1 = new D1<>();

        System.out.println(demo1.getClass().toString());

        D1<String> demo2 = new D1<>(); // 编译报错

    }

}

#7. 类型通配符

#7.1. 上界通配符

public class GenericsUpperBoundedWildcardDemo {

    public static double sumOfList(List<? extends Number> list) {

        double s = 0.0;

        for (Number n : list) {

            s += n.doubleValue();

        }

        return s;

    public static void main(String[] args) {

        List<Integer> li = Arrays.asList(1, 2, 3);

        System.out.println("sum = " + sumOfList(li));

    }

}

// Output:

// sum = 6.0

#7.2. 下界通配符

public class GenericsLowerBoundedWildcardDemo {

    public static void addNumbers(List<? super Integer> list) {

        for (int i = 1; i <= 5; i++) {

            list.add(i);

        }

    public static void main(String[] args) {

        List<Integer> list = new ArrayList<>();

        addNumbers(list);

        System.out.println(Arrays.deepToString(list.toArray()));

    }

}

// Output:

// [1, 2, 3, 4, 5]

#7.3. 无界通配符

可以使用 Object 类中提供的功能来实现的方法。

使用不依赖于类型参数的泛型类中的方法。

public class GenericsUnboundedWildcardDemo {

    public static void printList(List<?> list) {

        for (Object elem : list) {

            System.out.print(elem + " ");

        }

        System.out.println();

    public static void main(String[] args) {

        List<Integer> li = Arrays.asList(1, 2, 3);

        List<String> ls = Arrays.asList("one", "two", "three");

        printList(li);

        printList(ls);

    }

}

// Output:

// 1 2 3

// one two three

#7.4. 通配符和向上转型

public class GenericsWildcardDemo {

    public static void main(String[] args) {

        List<Integer> intList = new ArrayList<>();

        List<? extends Integer> intList2 = new ArrayList<>();

        List<? extends Number> numList2 = intList2;  // OK

    }

}

#8. 泛型的约束

泛型类型的类型参数不能是值类型(opens new window)

Pair<int, char> p = new Pair<>(8, 'a');  // 编译错误

不能创建类型参数的实例(opens new window)

public static <E> void append(List<E> list) {

    E elem = new E();  // 编译错误

    list.add(elem);

}

不能声明类型为类型参数的静态成员(opens new window)

public class MobileDevice<T> {

    // ...

}

类型参数不能使用类型转换或 instanceof(opens new window)

public static <E> void rtti(List<E> list) {

    if (list instanceof ArrayList<Integer>) {  // 编译错误

        // ...

    }

}

List<Integer> li = new ArrayList<>();

List<Number>  ln = (List<Number>) li;  // 编译错误

不能创建类型参数的数组(opens new window)

List<Integer>[] arrayOfLists = new List<Integer>[2];  // 编译错误

不能创建、catch 或 throw 参数化类型对象(opens new window)

// Extends Throwable indirectly

// Extends Throwable directly

class QueueFullException<T> extends Throwable { /* ... */ // 编译错误

public static <T extends Exception, J> void execute(List<J> jobs) {

    try {

        for (J job : jobs)

            // ...

    } catch (T e) {  // compile-time error

        // ...

    }

}

仅仅是泛型类相同,而类型参数不同的方法不能重载(opens new window)

public class Example {

    public void print(Set<String> strSet) { }

    public void print(Set<Integer> intSet) { } // 编译错误

}

#9. 泛型**实践

#9.1. 泛型命名

E - Element

K - Key

N - Number

T - Type

V - Value

S,U,V etc. - 2nd, 3rd, 4th types

#9.2. 使用泛型的建议

消除类型检查告警

List 优先于数组

优先考虑使用泛型来提高代码通用性

优先考虑泛型方法来限定泛型的范围

利用有限制通配符来提升 API 的灵活性

优先考虑类型安全的异构容器

#10. 小结

#11. 参考资料

Java 编程思想(opens new window)

Java 核心技术(卷 1)(opens new window)

Effective java(opens new window)

Oracle 泛型文档(opens new window)

Java 泛型详解(opens new window)

帮助我们改善此页面! (opens new window)

小讯
上一篇 2024-12-26 14:11
下一篇 2024-12-31 20:47

相关推荐

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容,请联系我们,一经查实,本站将立刻删除。
如需转载请保留出处:https://51itzy.com/kjqy/4905.html