首页 > 编程语言 >java9-泛型

java9-泛型

时间:2024-08-05 19:52:27浏览次数:16  
标签:Person 类型 泛型 new java9 public 赋值

1.泛型的简介

1.1 什么是泛型

        泛型是一种特殊的数据类型。 它是Java 的一个高级特性。在 Mybatis、Hibernate 这种持久化框架,泛型更是无处不在。

在这之前,不管我们在定义成员变量时,还是方法的形参时,都要规定他们的具体类型。所以提出猜想,有没有一种可能,一次声明,就可以给各种各样的值呢?所以,泛型这个概念就出来了。

泛型的定义:        

        我们在定义一个语法结构时,不用指明具体类型,而是先定义一个类型变量,在真正使用的时候再确定该变量的具体类型。

总结: 类型参数化

两个参数化:

        数据参数化:  就是使用形参接收具体数据(实际参数)
        类型参数化:  就是使用形参接收具体类型。

1.2 泛型的定义

 泛型,定义在一对尖括号中,也是一个标识符遵循大驼峰命名法通常都是用一个大写字母

public class Test1<T> {
}
class Person<T,M>{
}
class Calculate<T>{
    public T calculate(T a, T b){
        return a;
    }
}

2.泛型的应用 

2.1 泛型类的应用

        当我们将泛型用在类上时,这个类就叫做泛型类。

        泛型类:  泛型应用在类上。一般在类名后,使用尖括号括起来。用大写字母作为泛型参数。

演示代码:

import java.util.Date;

public class Person<T> {
    private T idCard;
    public Person(){

    }

    public Person(T idCard){
        this.idCard = idCard;
    }

    public static void main(String[] args) {
        //创建一个Person对象。需要给泛型参数赋值具体类型
        Person p = new Person<String>("cds123");
        Person<String> p2 = new Person<>("cds122");
        // 泛型参数,只能赋值引用类型,不能赋值八大基本数据类型
        Person<Long> p3 = new Person<>(3215466L);
        Date date = new Date();
        //小贴士:    实例化过程中,泛型只在一边给泛型参数赋值,但是两遍的尖括号都不能省略。
        Person<Date> p4 = new Person<>(date);
    }
}

/*
当一个子类继承带有泛型的父类时,一般情况下要给泛型参数赋值具体类名
 */

class Student extends Person<Integer>{
    public Student(Integer idCard){
        super(idCard);
    }
}
/*
子类的泛型参数可以给父类的泛型参数赋值。
下面的例子就是E赋值给了T。
 */

class Teacher<E> extends Person<E>{
    public Teacher(E idCard){
        super(idCard);
    }
}

/*
如果子类在定义期间,没有给泛型父类的泛型参数赋值,那么默认就是Object类型
 */
class Persident extends Person{
    public Persident(Object idCard){
        super(idCard);
    }

}

总结:

在实例化时,要给泛型参数赋具体值。实例化时两边的类名都可以赋值,也可以一边赋值,但是两边的尖括号不能去掉。在继承时也要赋值,如果没有赋值,那就默认object类型。也可以将子类的泛型赋值给父类。

2.2 泛型接口的应用

         将泛型用在接口上时,这个接口就叫做泛型接口。 泛型定义在接口名后。 用法和泛型类,一模一样。

测试代码:

import java.util.Arrays;
import java.util.Comparator;

/**
 * 泛型接口,泛型用在接口上,就叫泛型接口。
 * @param <T>
 */
public interface MyComparable<T,M> {
    /**
     * 两种类型进行比较
     * @param o1
     * @param o2
     * @return
     */


    public int mycompare(T o1, M o2);

    public static void main(String[] args) {
        Employee[] employees = new Employee[3];
        employees[0] = new Employee("佐伊",18);
        employees[1] = new Employee("建模",19);
        employees[2] = new Employee("ez",17);

        //使用比较器接口,来重新定义比较规则:  从泛型的角度来说,在实例化接口时,要给泛型参数传具体类型。
        Comparator c = new Comparator<Employee>(){
            //重写比较器里面的compare方法
            public int compare(Employee o1, Employee o2) {
                //调用了自定义的员工类里的比较方法。
                return o1.name.compareTo(o2.name);
            }
        };


        Arrays.sort(employees);
        System.out.println(Arrays.toString(employees));
    }


}
//子类实现接口 : 通常子类要给泛型接口的泛型参数赋值具体类型名。
//下面案例,就是给T和M都赋值了Employee这个类型。
class Employee implements MyComparable<Employee,Employee>, Comparator<Employee> {
    String name;
    int age;
    public Employee(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public String toString(){

        return "["+name+","+age+"]";
    }

    // 在我们自己定义的方法中来实现比较规则。
    public int mycompare(Employee o1, Employee o2) {
        return o1.age - o2.age;
    }

    @Override
    public int compare(Employee o1, Employee o2) {
        return mycompare(o1,o2);
    }

}

2.3 泛型方法的应用

        泛型不仅能用在类和接口上,还可以用在方法上。 需要把泛型定义在返回值类型前面。

测试代码:

import java.util.Objects;

public class MyUtil {

    public static <T> boolean equals(T t1,T t2){
        return t1.equals(t2);
    }

    public static void main(String[] args) {
        Cat cat = new Cat("咪咪");
        Cat cat1 = new Cat("咪咪");

        //泛型方法在调用期间,不需要指定具体类型,只需要传入具体对象
        //泛型方法调用期间,并没有给泛型参数赋值。下面的案例是c1给t1,c2给t2赋值,没有给T赋值。
        boolean a = MyUtil.equals(cat, cat1);
        System.out.println("equals"+a);
    }
}

class Cat{
    String name;
    public Cat(){
    }
    public Cat(String name){
        this.name = name;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Cat cat = (Cat) o;
        return Objects.equals(name, cat.name);
    }

    @Override
    public int hashCode() {
        return Objects.hashCode(name);
    }
}

注意:

在方法调用期间,不需要给泛型具体赋值,只需要传入变量即可。

3.泛型通配符

3.1 简介

        泛型通配符用 ? 表示,代表不确定的类型,是泛型的一个重要组成。 在调用时,表示我不关心具体类型。也可以使用通配符规定调用时,传入的类型的范围,即上边界,和下边界

3.2 简单应用 

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

/*
    泛型通配符: ?  用于表明不关心调用时的具体类型。
 */

public class MyUtil {
    /**
     * 将集合元素打印到控制台上
     */
    public static void print(List<?> lists){
        for(int i = 0; i<lists.size();i++){
            System.out.println(lists.get(i));
        }
    }

    /**
     * 上边界的定义: <? extends Number>
     *              具体使用的时候,可以是上边界的任何子类型或者是本类型。
     * @param list
     */

    public static void print2(List<? extends Number> list){

    }

    /**
     * 下边界的定义: <? super 具体类名>
     *              具体使用的时候,可以是下边界的任何父类型或者本类型。
     * @param list
     */
    public static void print3(List<? super Integer> list){
        for(int i = 0; i<list.size();i++){
            System.out.println(list.get(i));
        }
    }

    public static void main(String[] args) {
        List<Long> ns = new ArrayList<Long>();
        ns.add(1L);
        ns.add(2L);//注意 L 是Long类型不是long。
        ns.add(3L);
        MyUtil.print(ns);

        print2(new ArrayList<Long>());
        print2(new ArrayList<Number>());
//        print2(new ArrayList<Object>());最高到达Number类型

        //下边界的测试
        print3(new ArrayList<Number>());
        print3(new ArrayList<Object>());
        print3(new ArrayList<Integer>());
//        print3(new ArrayList<Long>());//Long和Integer没有关系。


    }

}

3.3 总结

        泛型是一种特殊的类型,你可以把泛型用在类、接口、方法上,从而实现一些通用算法。

        此外,使用泛型有三个步骤:定义类型变量使用类型变量确定类型变量

确定类型变量这一步中,你可以用泛型通配符来限制泛型的范围,从而实现一些特殊算法。(方法 <? extends 类名>上边界、 <? super 类名>下边界(都包括类名))。

标签:Person,类型,泛型,new,java9,public,赋值
From: https://blog.csdn.net/zhaogodzero/article/details/140934942

相关文章

  • 【Java基础知识3】泛型
    一、泛型的意义泛型的本质是将类型参数化,从而达到代码复用。即:在不创建新的类型下,通过泛型指定不同类型来控制形参具体类型,简单来讲就是,当我们不知道用什么数据类型接收数据的情况下,可以使用泛型来接收。代码示例:未使用泛型情况下:privatestaticintadd(inta,intb){......
  • c#:泛型
    泛型允许你定义一个类、接口或方法时不指定具体的数据类型,而是使用一个或多个类型参数类型安全:编译器在编译时检查类型,减少运行时错误。代码重用:相同的代码可以处理不同的数据类型,避免重复代码。性能:避免了装箱和拆箱的性能损失,尤其是在处理值类型时。点击查看代码usingS......
  • Java9 Process API
    在负责控制和管理操作系统进程的Java9ProcessAPI中已经有了相当大的改进。ProcessHandle类提供进程本机进程ID,开始时间,累计CPU时间,参数,命令,用户,父进程和子进程。ProcessHandle类还提供了检查进程活性并销毁进程的方法。它具有onExit方法,当进程退出时,CompletableFuture类......
  • 对于泛型和类型转换的优先级
    你们猜猜谁先打印,不看答案,能猜出来吗,写在评论区下面有3道题目,分别写出答案在评论区1、classTest{publicstaticvoidMain(){Foo("Hello");}publicstaticvoidFoo(objectx){Console.WriteLine("object");......
  • Java泛型的高级应用
    引言Java泛型是Java5引入的一项强大特性,它允许开发者在编写代码时指定类型参数,从而提高代码的复用性和安全性。尽管泛型在表面上看起来简单,但它的工作原理和高级应用却涉及许多复杂的主题,如类型擦除、类型推断、以及泛型在集合和自定义类中的应用。本文将深入探讨这些高......
  • 【数据结构】包装类和泛型
     ......
  • 如何在没有元类冲突的情况下将泛型类型与 PyQt 子类一起使用?
    我已经尝试过使用sip包装类型,并且当使用abc.ABCMeta进行子类化时效果很好。abc.ABC但它不适用于classQABCMeta(wrappertype,ABCMeta):passclassWidgetBase(QWidget,metaclass=QABCMeta):...classInterfaceWidget(WidgetBase,ABC):......
  • 当 functools.wraps() 用于泛型函数时,Mypy 1.10 报告错误
    TLDR;我有一个装饰器:更改函数签名包装的函数使用一些泛型类型参数除了我想使用的签名funtools.wraps以保留其余部分信息。有什么办法可以在不抱怨的情况下实现这一目标吗?mypy更多背景一个最小的工作示例如下所示:这......
  • 泛型擦除(Generics)
    在Java中,泛型(Generics)的“擦除”机制并不会阻止泛型的使用,反而是在保持向后兼容性和简化JVM设计的同时,允许泛型以一种类型安全的方式被使用。因为泛型的使用主要集中在编译时,当向集合添加不匹配的元素时编译会捕获到类型不匹配的错误。泛型擦除的含义类型信息的移除:在编......
  • 这一文,关于 Java 泛型的点点滴滴 二 (extends、super、<?> 通配符、泛型与反射)
    本文是《这一文,关于Java泛型的点点滴滴》的第二篇,也是最后一篇。在上一篇文章中我们介绍了关于Java泛型的基础知识,而在本文中,我们将深入Java泛型,介绍了extends、super、<?>通配符,并在最后介绍了使用反射获取泛型信息。在阅读本文之前,请先阅读上一篇文章:这一文,关于Jav......