Java泛型最全知识总结

Java泛型最全知识总结

什么是Java泛型?

Java泛型是JDK 5之后引入的新特性,它可以让我们编写更加安全和简洁的程序。它通过参数化类型的概念来实现,可以让我们在编译期检查类型安全,避免了很多传统上容易出现的运行期异常。

泛型的基本语法

泛型语法可以分为四种:泛型类、泛型方法、泛型接口、泛型通配符。

泛型类

泛型类使用<T>或其他类型参数来表示泛型类型,例如:

public class MyGenericClass<T> {
    private T value;

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

    public T getValue() {
        return value;
    }
}

这个示例中,MyGenericClass是一个泛型类,类型参数为Tvalue的类型就是T

泛型方法

泛型方法使用<T>或其他类型参数来表示泛型类型,例如:

public class GenericMethods {
    public static <T> void printArray(T[] array) {
        for (T elem : array) {
            System.out.print(elem + " ");
        }
        System.out.println();
    }
}

这个示例中,printArray是一个泛型方法,类型参数为T,可以接受任何类型的数组。

泛型接口

泛型接口使用<T>或其他类型参数来表示泛型类型,例如:

public interface MyGenericInterface<T> {
    T getValue();

    void setValue(T value);
}

这个示例中,MyGenericInterface是一个泛型接口,类型参数为TgetValuesetValue方法都是使用T作为返回值或参数类型。

泛型通配符

泛型通配符用于限制泛型类型的范围,例如:

public class GenericStack<T> {
    private List<T> stackList = new ArrayList<>();

    public void push(T element) {
        stackList.add(element);
    }

    public T pop() {
        return stackList.remove(stackList.size() - 1);
    }

    //泛型通配符 ? 表示任意类型
    public void pushAll(Collection<?> collection) {
        for (Object obj : collection) {
            stackList.add((T) obj);
        }
    }

    //泛型通配符 ? extends 表示任意类型的子类
    public void pushAllExtends(Collection<? extends T> collection) {
        for (T obj : collection) {
            stackList.add(obj);
        }
    }

    //泛型通配符 ? super 表示任意类型的超类
    public void pushAllSuper(Collection<? super T> collection) {
        for (Object obj : collection) {
            stackList.add((T) obj);
        }
    }
}

这个示例中,pushAll方法使用?作为泛型通配符,表示可以接收任意类型的集合。pushAllExtends方法使用? extends T作为泛型通配符,表示可以接受任意类型的子类集合。pushAllSuper方法使用? super T作为泛型通配符,表示可以接受任意类型的超类集合。

泛型的继承和通配符

泛型的继承

泛型类型允许泛型上下界的限制,例如:

public class Animal {}
public class Dog extends Animal {}
public class Cat extends Animal {}

public class Box<T extends Animal> {
    private T animal;

    public void setAnimal(T animal) {
        this.animal = animal;
    }

    public T getAnimal() {
        return animal;
    }
}

public static void main(String[] args) {
    Box<Animal> box1 = new Box<>();
    Box<Dog> box2 = new Box<>();
    Box<Cat> box3 = new Box<>();
}

这个示例中,Box使用T extends Animal来限制了T的范围,只能是Animal类或其子类。

泛型通配符

泛型通配符可以让我们接受任意类型的泛型参数,例如:

public static void printList(List<?> list) {
    for (Object obj : list) {
        System.out.print(obj + " ");
    }
    System.out.println();
}

public static void main(String[] args) {
    List<String> list1 = Arrays.asList("I", "love", "Java");
    List<Integer> list2 = Arrays.asList(1, 2, 3, 4, 5);
    printList(list1);
    printList(list2);
}

这个示例中,printList方法使用List<?>来表示接受任意类型的泛型参数。

泛型的类型推断

在JDK7之后,Java提供了类型推断的功能,让我们可以在很多场合下省略泛型类型参数,例如:

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

这个示例中,我们使用List<String>来声明了一个空的ArrayList对象,在JDK7之前,我们需要写成这样:

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

泛型的重要知识点和注意事项

  • Java泛型只在编译时期有效,在运行时期被擦除;
  • 泛型类型参数不能是基本数据类型,可以使用包装类型代替;
  • 不可以在泛型类型的静态方法和静态初始化块中使用泛型类型参数;
  • 泛型类的类型参数可以有多个,例如MyClass<T, K>
  • 当使用泛型时,我们应该遵循PECS原则(Producer Extends Consumer Super),即使用extends限定生产者类型,使用super限定消费者类型。

示例1:泛型通配符的含义及使用方法

public static void process(List<?> list) {
    for (Object obj : list) {
        if (obj instanceof Integer) {
            System.out.println(obj + " is an integer.");
        } else {
            System.out.println(obj + " is a string.");
        }
    }
}

public static void main(String[] args) {
    List<Object> list1 = new ArrayList<>();
    list1.add(1);
    list1.add("hello");
    process(list1);

    List<Integer> list2 = Arrays.asList(1, 2, 3, 4, 5);
    process(list2);
}

这个示例中,process方法使用了泛型通配符<?>,表示接受任意类型的List对象。在方法内部,我们使用instanceof关键字来判断元素的类型,从而进行相应的处理。

示例2:泛型的继承

public interface Comparable<T> {
    int compareTo(T o);
}

public class Student implements Comparable<Student> {
    private String name;
    private int age;
    private double score;

    public Student(String name, int age, double score) {
        this.name = name;
        this.age = age;
        this.score = score;
    }

    @Override
    public int compareTo(Student o) {
        return Double.compare(this.score, o.score);
    }
}

public static void main(String[] args) {
    List<Student> list = Arrays.asList(
        new Student("Tom", 20, 89),
        new Student("Jerry", 22, 78),
        new Student("Mary", 19, 95)
    );
    Collections.sort(list);
    for (Student student : list) {
        System.out.println(student.getName() + " " + student.getAge() + " " + student.getScore());
    }
}

这个示例中,Student类实现了Comparable接口,并重写了compareTo方法,用于按照成绩大小排序。在main方法中,我们使用Collections.sort方法对学生列表进行了排序,由于该列表元素都是Student类型,所以可以按照compareTo方法排序。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:Java泛型最全知识总结 - Python技术站

(0)
上一篇 2023年5月26日
下一篇 2023年5月26日

相关文章

  • springboot-mybatis/JPA流式查询的多种实现方式

    针对这个问题,我准备分为以下几个部分进行讲解。 1. 概述 在实际的开发过程中,通常需要处理大量的数据,如果使用传统的查询方式一次性将数据全部查出,可能会导致内存溢出等问题,而流式查询则可以一边查询,一边处理数据,从而避免这些问题。而在 Spring Boot 中,我们常用的流式查询方式有两种:MyBatis 和 JPA。 2. MyBatis 实现流式查询…

    Java 2023年5月20日
    00
  • springboot 整合 clickhouse的实现示例

    SpringBoot整合ClickHouse的实现示例 ClickHouse是一个高性能的列式数据库,可以用于处理大量数据。本文将详细讲解SpringBoot整合ClickHouse的实现示例的完整攻略,并提供两个示例。 1. 添加ClickHouse依赖 在SpringBoot项目中,我们可以使用ClickHouse JDBC驱动来连接ClickHouse…

    Java 2023年5月15日
    00
  • java 线程中start方法与run方法的区别详细介绍

    什么是线程 在 Java 中,我们可以通过 java.lang.Thread 类创建线程。线程是一个可以独立运行的子任务。与程序中的其他子任务不同,线程在操作系统层面上是一种独立的执行单元。在单个应用程序内,多个线程可以同时执行,每个线程都有自己的栈和局部变量,线程之间可以共享堆上的变量。由于线程在同时执行,因此在多线程编程中需要引入线程同步、锁和互斥等概念…

    Java 2023年5月26日
    00
  • 教你怎么在IDEA中创建java多模块项目

    下面是在IDEA中创建Java多模块项目的完整攻略: 1. 创建项目 首先,我们要打开IDEA,选择 “Create New Project”。然后,我们会看到一个对话框。 在对话框中,我们需要选择一个Maven项目类型,并确保我们勾选上了 “Create from archetype” 选项。然后点击 “Add archetype” 按钮,在弹出的对话框中…

    Java 2023年5月26日
    00
  • Java采用setAsciiStream方法检索数据库指定内容实例解析

    让我来详细讲解一下“Java采用setAsciiStream方法检索数据库指定内容实例解析”这个主题。 什么是setAsciiStream方法 在Java JDBC编程中,我们可以使用setAsciiStream方法设置指定内容,该方法是在PreparedStatement接口内定义的方法。setAsciiStream方法的作用是将给定的ASCII输入流转换…

    Java 2023年5月19日
    00
  • Java+Spring+MySql环境中安装和配置MyBatis的教程

    下面是关于“Java+Spring+MySql环境中安装和配置MyBatis的教程”的完整攻略,包含两个示例说明。 Java+Spring+MySql环境中安装和配置MyBatis的教程 MyBatis是一个开源的Java持久化框架,它可以帮助我们轻松地将Java对象映射到关系型数据库中。本文将详细介绍如何在Java+Spring+MySql环境中安装和配置…

    Java 2023年5月17日
    00
  • 如何写好一个Spring组件的实现步骤

    下面我将为您详细讲解如何写好一个Spring组件的实现步骤。 1. 设计接口 首先,我们需要设计组件的接口。组件的接口应该清晰明了,符合单一职责原则,以及接口隔离原则。在设计接口时,可以参考现有的类库或其他组件的设计。 例如,我们想要编写一个邮件发送组件,我们可以先设计下面的接口: public interface MailSender { void sen…

    Java 2023年5月19日
    00
  • 使用Spring处理x-www-form-urlencoded方式

    要使用Spring处理x-www-form-urlencoded方式,需要进行以下步骤: 配置Spring MVC 在web.xml中配置DispatcherServlet。在DispatcherServlet的xml配置文件中,添加,启用Spring MVC注解驱动。这样Spring MVC就可以自动处理表单提交请求。 编写Controller Sprin…

    Java 2023年5月20日
    00
合作推广
合作推广
分享本页
返回顶部