Изучение дженериков Java

Java задняя часть

«Эта статья участвовала в мероприятии Haowen Convocation Order, щелкните, чтобы просмотреть:Двойные заявки на внутреннюю и внешнюю стороны, призовой фонд в 20 000 юаней ждет вас, чтобы бросить вызов!"

Хотя я некоторое время писал код на Java, пока я вижу дженерики, я все равно предпочитаю сдаться. Но сегодня я просматривал код начальника компании и обнаружил, что дженерики используются во многих местах, поэтому сегодня я разберусь с дженериками, в которых разбираюсь.

что такое дженерики

Общее программирование — это стиль или парадигма языков программирования. Обобщения позволяют программистам, пишущим код на строго типизированных языках программирования, использовать типы, указанные позже, указывая эти типы в качестве параметров во время создания экземпляра. Существует два основных типа определений: 1⃣️ Некоторые типы, которые содержат параметры типа в программном кодировании, то есть общие параметры могут представлять только классы, а не отдельные объекты. 2⃣️ Некоторые классы, содержащие параметры в кодировке программы. Его параметры могут представлять классы или объекты и т. д.

👆Объяснение выше взято из энциклопедии Baidu.Проще говоря, дженерики — это парадигма кода.

Дженерики Java

Параметры дженериков Java могут представлять только классы, а не отдельные объекты. Поскольку фактический тип параметра типа универсального типа Java исключается во время компиляции, тип его параметра типа не может быть известен во время выполнения, и невозможно напрямую использовать тип примитивного значения в качестве параметра универсального типа.

Принципы проектирования дженериков Java:

Отложите специфичность типа до создания объекта или вызова метода для определенного типа. Пока нет предупреждений во время компиляции, то нет и во время выполненияClassCastExceptionаномальный.

Вот пример простых дженериков:

public class Generic {

    public static void main(String[] args) {
        // C 可以接受 String
        C<String> stringC = new C<>("Hello world");
        System.out.println(stringC);
        
        // C 可以接受 Integer
        C<Integer> integerC = new C<>(100);
        System.out.println(integerC);

    }
}

// C 可以接受任意类型数据的初始化
class C<T> {
    private T item;

    public C(T t){
        item = t;
    }

    @Override
    public String toString() {
        return  item + "";
    }
}

Т, Е, К, В

T, E, K, V по сути являются подстановочными знаками. Кодирование иногда связано с соглашением. Например, мы можем использовать любую букву между A-Z для обозначения подстановочных знаков, и это не повлияет на нормальную работу программы. Обычно T, E, K, V согласовываются следующим образом:

  • Представляет неопределенный тип Java
  • T ( type )Представляет конкретный тип Java
  • K V ( key value )Представляет значение ключа в значении ключа Java.
  • E ( element )означает Элемент

подстановочный знак

  • подстановочный знак верхней границы? extends T

    НапримерList< ? extends Number>Цель состоит в том, чтобы принятьList<Integer> or List<Long>тип данных.

  • Подстановочный знак Нижнего мира? super T

    НапримерList<? super Number>Цель состоит в том, чтобы восполнить недостаток, заключающийся в том, что может храниться только один конкретный тип данных.

public class Generic {

    public static void main(String[] args) {
        // 可以
        List<? super Number> list = new ArrayList<>();
        list.add(10);
        list.add(20L);
        list.add(20.2);

        System.out.println(list);

        List<Integer> list1 = new ArrayList<>();
        List<Long> list2 = new ArrayList<>();

        list1.add(10);
        list1.add(20);

        list2.add(10L);
        list2.add(20L);

        read(list1);
        read(list2);
    }

    private static void read(List< ? extends Number> list) {
        Number first = list.get(0);
        Number last = list.get(list.size() - 1);
        System.out.println("first = " + first.toString() + " last = " + last.toString());
    }
    
}

Наконец, взгляните на принцип PECS (Producer Extends Consumer Super):

  • Если вы часто читаете контент, целесообразно использовать расширение верхней границы.
  • Часто вставляется в него, подходит для использования Nether Super

Общий случай

// 多参数泛型 
class Person<N, A, S> {

    private N name;
    private A age;
    private S sex;

    Person(N name, A age, S sex) {
        this.name = name;
        this.age = age;
        this.sex = sex;
    }

    public N getName() {
        return name;
    }
    public void setName(N name) {
        this.name = name;
    }
    public A getAge() {
        return age;
    }
    public void setAge(A age) {
        this.age = age;
    }
    public S getSex() {
        return sex;
    }
    public void setSex(S sex) {
        this.sex = sex;
    }

    @Override
    public String toString() {
        return "姓名:" + name + ",年龄:" + age + ",性别:" + sex;
    }
}

// 使用
public class Generic {

    public static void main(String[] args) {

        Person<String, Integer, Character> person = new Person<String, Integer, Character>("蛋炒饭", 28, '男');
        printPerson(person);
        // 姓名:蛋炒饭,年龄:28,性别:男
    }
    
    // 泛型方法
    private static <T> void printPerson(T person){
        if ( person != null) {
            System.out.println(person);
        }
    }
}