Java泛型:概述、自定义泛型类、方法、接口、泛型通配符上下限

本文详细介绍了Java中的泛型,包括泛型的基本概念、泛型类、泛型方法和泛型接口的定义与使用。通过代码示例展示了泛型在集合操作、自定义类和方法以及接口规范中的应用,强调了泛型在提高代码安全性和灵活性方面的重要性。此外,还提及了泛型通配符和上下限的概念,帮助理解如何在不同场景下更灵活地使用泛型。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Java多态详解
Java内部类详解

1.概述

泛型概述
1.泛型:是JDK5中引入的特性,可以在编译阶段约束操作的数据类型,并进行检查;
2.泛型的格式:<数据类型>; 注意:泛型只能支持引用数据类型;
3.集合体系的全部接口和实现类都是支持泛型的使用的;

泛型的好处
1.统一数据类型;
2.把运行时期的问题提前到了编译期间,避免了强制类型转换可能出现的异常,因为编译阶段类型就能确定下来;

在这里插入图片描述

代码示例

import java.util.ArrayList;
import java.util.List;

public class Fan {
    public static void main(String[] args) {
        List list=new ArrayList();

        list.add("Java");
        list.add("HTML");
        list.add(11);
        list.add(22);

        //定义时没有指定类型,就要使用Object来承接 因此可以直接定义为 List<Object> list2 = new ArrayList<>();
        for(Object i:list){
            System.out.println(i);
        }

//        而泛型的存在就是要求指定数据类型,避免引发其它异常问题。
//        泛型就是一个标签:<数据类型> 
//        泛型可以在编译阶段约束只能操作某种数据类型。
    }
}

2.自定义泛型类

泛型类介绍

1.定义类时同时定义了泛型的类就是泛型类;

泛型类的格式

修饰符 class 类名<泛型变量>{
}

范例:
public class MyArrayList<T> {
}

1.此处泛型变量T可以随便写为任意标识,常见的如E、T、K、V等;
2.作用:编译阶段约束操作的数据类型,类似于集合的作用;

对泛型类的理解
把出现泛型变量的地方全部替换成传输的真实数据类型。

代码示例

要求
模拟ArrayList集合自定义一个集合MyArrayList集合,完成添加和删除功能的泛型设计即可。

Test.java

public class Test {
    public static void main(String[] args) {
        // 需求:模拟ArrayList定义一个MyArrayList ,关注泛型设计
        MyArrayList<String> list = new MyArrayList<>();
        list.add("Java");
        list.add("Java");
        list.add("MySQL");
        list.remove("MySQL");
        System.out.println(list);

        MyArrayList<Integer> list2 = new MyArrayList<>();
        list2.add(23);
        list2.add(24);
        list2.add(25);
        list2.remove(25);
        System.out.println(list2);
    }
}

MyArrayList.java

import java.util.ArrayList;

public class MyArrayList<E> {
	//本例主要是为了理解泛型类的定义,因此不关注具体实现,而是借用ArrayList
    private ArrayList lists = new ArrayList();

    public void add(E e){
        lists.add(e);
    }

    public void remove(E e){
        lists.remove(e);
    }

    @Override
    public String toString() {
        return lists.toString();
    }
}

3.自定义泛型方法

泛型方法介绍

泛型方法的概述
1.定义方法时同时定义了泛型的方法就是泛型方法;

泛型方法的格式

修饰符 <泛型变量> 方法返回值 方法名称(形参列表){
}

范例: 
public <T> void show(T t) {
}

作用: 方法中可以使用泛型接收一切实际类型的参数,方法更具备通用性

对泛型方法的理解
把出现泛型变量的地方全部替换成传输的真实数据类型。

代码示例

要求
给你任何一个类型的数组,都能返回它的内容。也就是实现Arrays.toString(数组)的功能。

/**
    目标:自定义泛型方法。

    什么是泛型方法?
        定义了泛型的方法就是泛型方法。

    泛型方法的定义格式:
        修饰符 <泛型变量> 返回值类型 方法名称(形参列表){

        }
        注意:方法定义了是什么泛型变量,后面就只能用什么泛型变量。
        泛型类的核心思想:是把出现泛型变量的地方全部替换成传输的真实数据类型。

    需求:给你任何一个类型的数组,都能返回它的内容。Arrays.toString(数组)的功能!

    小结:
        泛型方法可以让方法更灵活的接收数据,可以做通用技术!
 */
public class GenericDemo {
    public static void main(String[] args) {
        String[] names = {"小璐", "蓉容", "小何"};
        printArray(names);

        Integer[] ages = {10, 20, 30};
        printArray(ages);

        Integer[] ages2 = getArr(ages);
        String[]  names2 = getArr(names);
    }

    public static <T> T[] getArr(T[] arr){
        return arr;
    }

    public static <T> void printArray(T[] arr){
        if(arr != null){
            StringBuilder sb = new StringBuilder("[");
            for (int i = 0; i < arr.length; i++) {
                sb.append(arr[i]).append(i == arr.length - 1 ? "" : ", ");
            }
            sb.append("]");
            System.out.println(sb);
        }else {
            System.out.println(arr);
        }
    }
}

3.自定义泛型接口

泛型接口介绍

泛型接口的概述

  1. 使用了泛型定义的接口就是泛型接口;

泛型接口的格式

修饰符 interface 接口名称<泛型变量>{
}

范例: 
public interface Data<E>{
}

作用: 泛型接口可以让实现类选择当前功能需要操作的数据类型

对泛型接口的理解
泛型接口可以约束实现类,实现类可以在实现接口的时候传入自己操作的数据类型这样重写的方法都将是针对于该类型的操作

代码示例

要求
教务系统,提供一个接口可约束一定要完成数据(学生,老师)的增删改查操作。

GenericDemo.java

public class GenericDemo {
    public static void main(String[] args) {
		//在该类中调用数据的各种方法:增删改查
    }
}

Student.java

public class Student {
	//该类中定义学生对象的各项信息,如姓名。学号、成绩
}

StudentData.java

public class StudentData implements Data<Student>{
	//该类是数据接口Data的实现类,在定义的同时声明了只传入Student类型
    @Override
    public void add(Student student) {

    }

    @Override
    public void delete(int id) {

    }

    @Override
    public void update(Student student) {

    }

    @Override
    public Student queryById(int id) {
        return null;
    }
}

Teacher.java

public class Teacher {
	//同Student类
}

TeacherData.java

public class TeacherData implements Data<Teacher>{
	//同StudentData类
    @Override
    public void add(Teacher teacher) {

    }

    @Override
    public void delete(int id) {

    }

    @Override
    public void update(Teacher teacher) {

    }

    @Override
    public Teacher queryById(int id) {
        return null;
    }
}

Data.java

public interface Data<E> {
	//接口定义类,规范对学生、教师的操作方法
    void add(E e);
    void delete(int id);
    void update(E e);
    E queryById(int id);
}

5.泛型通配符、上下限

泛型通配符、上下限

通配符:?
1.? 可以在“使用泛型”的时候代表一切类型;
2. E T K V 是在定义泛型的时候使用的;

泛型的上下限
1.? extends Car: ?必须是Car或者其子类 泛型上限;
2.? super Car : ?必须是Car或者其父类 泛型下限;

代码示例
开发一个极品飞车的游戏,所有的汽车都能一起参与比赛。

GenericDemo.java

public class GenericDemo {
    public static void main(String[] args) {
        ArrayList<BMW> bmws = new ArrayList<>();
        bmws.add(new BMW());
        bmws.add(new BMW());
        bmws.add(new BMW());
        go(bmws);

        ArrayList<BENZ> benzs = new ArrayList<>();
        benzs.add(new BENZ());
        benzs.add(new BENZ());
        benzs.add(new BENZ());
        go(benzs);

        ArrayList<Dog> dogs = new ArrayList<>();
        dogs.add(new Dog());
        dogs.add(new Dog());
        dogs.add(new Dog());
        // go(dogs);
    }

    /**
       所有车比赛
	   有了上下限,可以避免乱传参,万一把Dog传过来怎么办?
	 */
    public static void go(ArrayList<? extends Car> cars){  
    }
}

class Dog{

}

class BENZ extends Car{
}

class BMW extends Car{
}

// 父类
class Car{
}
<think>嗯,用户想了解Excel中的VLOOKUP函数的用法和参数含义。首先,我需要回忆一下VLOOKUP的基本结构。VLOOKUP是垂直查找函数,用于在表格的首列查找指定的值,然后返回该行中指定列的数据。它的四个参数分别是查找值、表格范围、列索引号和匹配模式。 接下来,我得确认每个参数的具体作用。第一个参数是lookup_value,也就是用户要查找的值,比如产品ID或者姓名。第二个参数是table_array,即查找的范围,这里要注意的是,查找值必须位于这个范围的第一列,否则函数无法正确工作。第三个参数是col_index_num,也就是用户想要返回的数据在表格范围中的第几列,这个列数是从表格范围的第一列开始算起的,不是整个工作表的列。第四个参数是range_lookup,决定是精确匹配还是近似匹配,通常用FALSE或0来指定精确匹配,避免错误。 然后,用户可能需要一个具体的例子来理解如何使用。比如,假设有一个产品价格表,用户想根据产品ID查找对应的价格。这时候,VLOOKUP就可以在ID列查找,然后返回价格列的数据。同时,要提醒用户注意表格范围最好使用绝对引用,比如$A$2:$C$100,这样在拖动公式时范围不会变化。 可能遇到的问题也需要考虑。比如,如果查找值不在表格的第一列,或者列索引号超过了表格的列数,函数会返回错误。此外,数据格式不一致也可能导致问题,比如查找值是数字,而表格中是文本格式的数字,这时候需要统一格式。还有,当出现#N/A错误时,可能是查找值不存在,或者匹配模式设置不正确,需要检查参数是否正确。 用户可能还会问到如何避免常见的错误,比如部分数据匹配出错的情况。这时候需要检查是否有多余的空格,或者数据格式不一致,或者表格范围没有锁定导致拖动时偏移。此外,XLOOKUP作为VLOOKUP的升级版,可能在某些情况下更方便,比如可以向左查找或者返回多列数据,这也是可以提及的内容。 最后,整理步骤,从基础语法到参数说明,再到具体案例,逐步引导用户理解如何使用VLOOKUP函数。同时,提供常见错误和解决方法,帮助用户在实际应用中避免问题。如果有必要,还可以比较VLOOKUP和其他查找函数的区别,比如HLOOKUP或XLOOKUP,但根据用户的问题,主要集中在VLOOKUP本身即可。</think>### Excel VLOOKUP函数详解 #### 一、基础语法与参数说明 VLOOKUP函数的语法为: $$=VLOOKUP(lookup\_value, table\_array, col\_index\_num, [range\_lookup])$$ 包含4个参数: 1. **lookup_value**(必填):要查找的值(如单元格引用或具体值) 2. **table_array**(必填):包含数据的表格范围(必须包含查找列和返回列) 3. **col_index_num**(必填):返回值所在列的序号(从table_array第一列开始计数) 4. **range_lookup**(可选):匹配类型 - `TRUE`/`1`:近似匹配(默认值,需数据升序排列) - `FALSE`/`0`:精确匹配(常用选项) [^1][^2] #### 二、使用步骤演示(工资表查询案例) 假设需要根据员工编号查询工资: 1. 建立查询单元格(如`B12`) 2. 输入公式: ```excel =VLOOKUP(A12, $A$2:$D$100, 4, 0) ``` - `A12`:待查询的员工编号 - `$A$2:$D$100`:锁定数据区域(绝对引用) - `4`:返回第4列(工资列) - `0`:精确匹配 [^2][^3] #### 三、常见错误与解决方法 | 错误现象 | 原因 | 解决方案 | |---------|------|---------| | #N/A | 查找值不存在 | 检查数据源或改用`IFERROR`容错 | | #REF! | 列序号超出范围 | 确认col_index_num ≤ 表格列数 | | 部分匹配失败 | 数据格式不一致 | 统一数值/文本格式 | | 结果错位 | 表格未锁定 | 使用`$`符号固定区域引用 | [^3][^4] #### 四、进阶技巧 1. **多条件查询**: 使用辅助列合并多个条件字段 ```excel =VLOOKUP(A2&B2, $D$2:$F$100, 3, 0) ``` 2. **通配符匹配**: `"*"`匹配任意字符,`"?"`匹配单个字符 ```excel =VLOOKUP("张*", $A$2:$C$100, 3, 0) ``` 3. **跨表查询**: 引用其他工作表数据 ```excel =VLOOKUP(A2, Sheet2!$A$2:$D$100, 4, 0) ``` [^1][^4]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值