【java】泛型编程

news2024/10/5 17:17:58

文章目录

    • 泛型类
    • 泛型与多态
    • 泛型方法
    • 泛型界限
      • 设置上界
      • 设置下界
    • 类型擦除
    • 函数式接口
      • Supplier供给型函数式接口
      • Consumer消费型函数式接口
      • Function函数型函数式接口
      • Predicate断言型函数式接口
      • 判空包装

泛型类

package com.test.entity;
public class Score<T> {
    String name;
    String id;
    public T value;

    public Score(String name, String id, T value)
    {
        this.name = name;
        this.id = id;
        this.value = value;
    }
}

import com.test.entity.Score;
public class Main {
    public static void main(String[] args) {
        Score<String> score1 = new Score<String>("计算机网络", "EP074512", "优秀");
        String value1 = score1.value;   //一旦类型明确,那么泛型就变成对应的类型了
        System.out.println(value1);
        Score<Integer> score2 = new Score<>("计算机网络", "EP074512", 99);
        int value2 = score2.value;
        System.out.println(value2);
    }
        }

优秀
99

public class Test<T>{
    private T value;
    public void setValue(T value) {
        this.value = value;
    }
    public T getValue() {
        return value;
    }
}

泛型与多态

子类实现此接口时,可以选择在实现类明确泛型类型,或是继续使用此泛型让具体创建的对象来确定类型

package com.test.entity;
public interface Study<T>
{
    T test(T a);
    //在实现接口或是继承父类时,如果子类是一个普通类,那么可以直接明确对应类型
}

import com.test.entity.Study;
public class Main {
    public static void main(String[] args) {
        A a = new A();
        Integer i = a.test(101);
        System.out.println(i);
    }
    static class A implements Study<Integer> {
        @Override
        public Integer test(Integer a) {
            return a;
        }
        //在实现接口或是继承父类时,如果子类是一个普通类,那么可以直接明确对应类型
    }
}
import com.test.entity.Study;
public class Main {
    public static void main(String[] args) {
        A<String> a = new A<>();
        String i = a.test("coleak");
        System.out.println(i);
        A<Integer> b = new A<>();
        int j = b.test(99);
        System.out.println(j);
    }
    static class A<T> implements Study<T> {
        //让子类继续为一个泛型类,那么可以不用明确
        @Override
        public T test(T a) {
            return a;
        }
    }
}

泛型方法

public class Main {
    public static void main(String[] args) {
        String str = test("Hello World!");
        System.out.println(str);
        int i=test(10);
        System.out.println(i);
        int k=test2("coleak");
        System.out.println(k);
    }
    private static <T> T test(T t) {   //在返回值类型前添加<>并填写泛型变量表示这个是一个泛型方法
        return t;
    }
        private static <T> int test2(String t){   //在返回值类型前添加<>并填写泛型变量表示这个是一个泛型方法
            return t.length();
    }
}
import java.util.Arrays;
public class Main {
    public static void main(String[] args) {
        String[] strings = new String[2];
        Main main = new Main();
        main.add(strings, "Hello");
        main.add(strings,"coleak");
        System.out.println(Arrays.toString(strings));
    }
    private <T> void add(T[] arr, T t){
        if(arr[0] ==null)
            arr[0] = t;
        arr[1]=t;
    }
}

[Hello, coleak]

import java.util.Arrays;
import java.util.Comparator;
public class Main {
    public static void main(String[] args) {
        Integer[] arr = {1, 4, 5, 2, 6, 3, 0, 7, 9, 8};
        Arrays.sort(arr, new Comparator<Integer>() {
            @Override
            public int compare(Integer o1, Integer o2) {   //两个需要比较的数会在这里给出
                return o2 - o1;
                //compare方法要求返回一个int来表示两个数的大小关系,大于0表示大于,小于0表示小于
                //这里直接o2-o1就行,如果o2比o1大,那么肯定应该排在前面,所以说返回正数表示大于
            }
        });
        System.out.println(Arrays.toString(arr));
    }
}

//简化版
import java.util.Arrays;
public class Main {
    public static void main(String[] args) {
        Integer[] arr = {1, 4, 5, 2, 6, 3, 0, 7, 9, 8};
        Arrays.sort(arr, (o1, o2) -> o2 - o1);   //瞬间变一行,效果跟上面是一样的
        System.out.println(Arrays.toString(arr));
    }
}

[9, 8, 7, 6, 5, 4, 3, 2, 1, 0]

泛型界限

设置上界

img

public class Score<T extends Number> {   
//设定类型参数上界,必须是Number或是Number的子类
    private final String name;
    private final String id;
    private final T value;

    public Score(String name, String id, T value) {
        this.name = name;
        this.id = id;
        this.value = value;
    }

    public T getValue() {
        return value;
    }
}

import com.test.entity.Score;
public class Main {
    public static void main(String[] args) {
        Score<?> score1 = new Score<>("数据结构与算法", "EP074512", 60.0);
        Score<?  extends Number> score2 = 
        new Score<>("数据结构与算法", "EP074512", 60.66);
        //可以看到,此时虽然使用的是通配符,但是不再是Object类型,而是对应的上界
        Score<Integer> score3 = new Score<>("数据结构与算法", "EP074512", 60);
        System.out.println(score1.getValue());
        System.out.println(score2.getValue());
        System.out.println(score3.getValue());
    }
}

设置下界

4aa52791-73f4-448f-bab3-9133ea85d850.jpg

public static void main(String[] args) {
    Score<? super Number> score = new Score<>("数据结构与算法基础", "EP074512", 10);
    Object o = score.getValue();
}

类型擦除

实际上在Java中并不是真的有泛型类型(为了兼容之前的Java版本)因为所有的对象都是属于一个普通的类型,一个泛型类型编译之后,实际上会直接使用默认的类型

如果我们给类型变量设定了上界,那么会从默认类型变成上界定义的类型

public abstract class A <T>{
    abstract T test(T t);
}
public abstract class A {
    abstract Object test(Object t);  //默认就是Object
}
public abstract class A <T extends Number>{   //设定上界为Number
    abstract T test(T t);
}
public abstract class A {
    abstract Number test(Number t);  //上界Number,因为现在只可能出现Number的子类
}
public static void main(String[] args) {
    A<String> a = new B();
    String  i = a.test("10");     //因为类型A只有返回值为原始类型Object的方法
}
public static void main(String[] args) {
    A a = new B();
    String i = (String) a.test("10");   //依靠强制类型转换完成的
}
public class B extends A<String>{
    @Override
    String test(String s) {
        return null;
    }
}
// Compiled from "B.java"
public class com.test.entity.B extends com.test.entity.A<java.lang.String> {
  public com.test.entity.B();
  java.lang.String test(java.lang.String);
  java.lang.Object test(java.lang.Object);   
    //桥接方法,这才是真正重写的方法,但是使用时会调用上面的方法
}

通过反编译进行观察,实际上是编译器帮助我们生成了一个桥接方法用于支持重写

函数式接口

Supplier供给型函数式接口

import com.test.entity.Student;
import java.util.function.Supplier;
public class Main {
    //专门供给Student对象的Supplier
    private static final Supplier<Student> STUDENT_SUPPLIER = Student::new;
    public static void main(String[] args) {
        Student student1 = STUDENT_SUPPLIER.get();
        Student student2 =new Student();
        student1.hello();
        student2.hello();
    }
}

Consumer消费型函数式接口

import com.test.entity.Student;
import java.util.function.Consumer;
import java.util.function.Supplier;
public class Main {
    private static final Supplier<Student> STUDENT_SUPPLIER = Student::new;
    private static final Consumer<Student> STUDENT_CONSUMER = student -> System.out.println(student+" 真好吃!");
    public static void main(String[] args) {
        Student student =STUDENT_SUPPLIER.get();
        STUDENT_CONSUMER   //我们可以提前将消费之后的操作以同样的方式预定好
                .andThen(stu -> System.out.println("我是吃完之后的操作!"))
                .andThen(stu -> System.out.println("好了好了,吃饱了!"))
                .accept(student);   //预定好之后,再执行
    }
}

com.test.entity.Student@3fb6a447 真好吃!
我是吃完之后的操作!
好了好了,吃饱了!

Function函数型函数式接口

@FunctionalInterface
public interface Function<T, R> {
    R apply(T t);   
    //这里一共有两个类型参数,其中一个是接受的参数类型,还有一个是返回的结果类型

    default <V> Function<V, R> compose(Function<? super V, ? extends T> before) {
        Objects.requireNonNull(before);
        return (V v) -> apply(before.apply(v));
    }

    default <V> Function<T, V> andThen(Function<? super R, ? extends V> after) {
        Objects.requireNonNull(after);
        return (T t) -> after.apply(apply(t));
    }

    static <T> Function<T, T> identity() {
        return t -> t;
    }
}
import java.util.function.Function;
public class Main {
    private static final Function<String,Integer> INTEGER_STRING_FUNCTION = String::length;
    public static void main(String[] args) {
        int number = INTEGER_STRING_FUNCTION.apply("coleak");
        System.out.println(number);
    }
}

6

import java.util.function.Function;
public class Main {
    private static final Function<Integer, String> INTEGER_STRING_FUNCTION = Object::toString;
    public static void main(String[] args) {
        String str = INTEGER_STRING_FUNCTION
                .compose((String s) -> s.length())   //将此函数式的返回值作为当前实现的实参
                .apply("lbwnb");   //传入上面函数式需要的参数
        System.out.println(str);
        System.out.println(str.getClass());
    }
}

public static void main(String[] args) {
    Boolean str = INTEGER_STRING_FUNCTION
            .andThen(String::isEmpty)   
        //在执行完后,返回值作为参数执行andThen内的函数式,最后得到的结果就是最终的结果了
            .apply(10);
    System.out.println(str);
}

public static void main(String[] args) {
    Function<String, String> function = Function.identity();   //原样返回
    System.out.println(function.apply("不会吧不会吧,不会有人听到现在还是懵逼的吧"));
}

Predicate断言型函数式接口

import com.test.entity.Student;
import java.util.function.Predicate;
public class Main {
    private static final Predicate<Student> STUDENT_PREDICATE = student -> student.score >= 60;
    public static void main(String[] args) {
        Student student = new Student();
        student.score = 80;
        if(STUDENT_PREDICATE.test(student)) {  
            //test方法的返回值是一个boolean结果
            System.out.println("及格了,真不错");
        } else {
            System.out.println("不及格");
        }
    }
}


import com.test.entity.Student;
import java.util.function.Predicate;
public class Main {
    private static final Predicate<Student> STUDENT_PREDICATE = student -> student.score >= 60;
    public static void main(String[] args) {
        Student student = new Student();
        student.score = 99;
        boolean b = STUDENT_PREDICATE
                .and(stu -> stu.score > 90)   //需要同时满足这里的条件,才能返回true
                .test(student);
        if(!b) System.out.println("Java到现在都没考到90分?你的室友都拿国家奖学金了");
    }
}

判空包装

import com.test.entity.Student;
import java.util.Optional;
public class Main {
    public static void main(String[] args) {
        test("coelak");
    }
    private static void test(String str){
        String s = Optional.ofNullable(str).orElse("我是为null的情况备选方案");
        System.out.println(s);
    }
    }
}
import com.test.entity.Student;
import java.util.Optional;
public class Main {
    public static void main(String[] args) {
        test("coelak");
    }
    private static void test(String str){
        Integer i = Optional
                .ofNullable(str)
                .map(String::length)   
            //使用map来进行映射,将当前类型转换为其他类型,或者是进行处理
                .orElse(-1);
        System.out.println(i);
    }
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/413322.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

一文搞懂Session和JWT登录认证

前言 目前在开发的小组结课项目中用到了JWT认证&#xff0c;简单分享一下&#xff0c;并看看与Session认证的异同。 登录认证&#xff08;Authentication&#xff09;的概念非常简单&#xff0c;就是通过一定手段对用户的身份进行确认。 我们都知道 HTTP 是无状态的&#xf…

模型实战(9)之YOLOv8预测模块predictor详解、预测视频后同时保存结果视频+目标帧

YOLOv8预测模块predictor详解、预测视频后同时保存结果视频+目标帧 Ultralytics YOLOv8Ultralytics YOLOv8是最新版本的YOLO对象检测和图像分割模型。 作为一种尖端的、最先进的(SOTA)模型,YOLOv8建立在以前版本的成功基础上,引入了新的功能和改进,以增强性能、灵活性和效率…

高速Serdes技术(FPGA领域应用)

目录引入一、Serdes&#xff08;概念-历程&#xff09;1、概念2、技术现状3、发展历程二、Serdes结构三、在FPGA领域中的运用四、Serdes跟Lvds的关系五、Xilinx 有关 serdes的文档六、参考文献引入 回顾接口技术发展历史&#xff0c;其实数据的传输最开始是低速的串行接口&…

202307读书笔记|《双向奔赴的爱,才是人间理想》——爱是双向奔赴,共同成长

《双向奔赴的爱&#xff0c;才是人间理想》作者燕七&#xff0c;读作者的第一本书是《鲸鱼安慰&#x1f433;了大海》可太美了&#xff0c;这次订阅通知这本&#xff0c;立马加入了书架&#xff0c;跑完步读了起来。没有第一本惊艳&#xff0c;但也不错&#xff0c;值得一读&am…

JavaScript对象的属性描述符(Property Descriptor)介绍

JavaScript对象的属性描述符&#xff08;Property Descriptor&#xff09;介绍 JavaScript 中的对象&#xff08;Object&#xff09;是一个包含相关数据和方法的集合&#xff0c;通常由一些变量和函数组成&#xff0c;我们称之为对象里面的属性&#xff08;property&#xff0…

java springboot工程RESTful入门案例 认识请求类型 参数

我们先创建一个java的springboot工程 然后 我们先用老方式试一下 在启动类的同级创建目录controller 下面创建一个类 叫 UserController 参考代码如下 package com.example.threshold.controller;import org.springframework.web.bind.annotation.GetMapping; import org.spri…

负载均衡与DNS轮询

负载均衡 load balance 负载均衡&#xff08;Load Balancing&#xff09;是一种将工作负载&#xff08;Workload&#xff09;分摊到多个计算资源&#xff08;服务器、存储设备、网络设备等&#xff09;上的技术&#xff0c;目的是提高系统的可用性、性能和扩展性。负载均衡可以…

序列化和反序列化二叉树 -----前序,中序,后序,层序

目录 一.序列化和反序列化 1.什么是序列化和反序列化 二.前序遍历 1.序列化 1.问题分析 2.代码实现 2.反序列化 1.问题分析 2.代码实现 三.后序遍历 1.序列化 1.思路分析 2.代码实现 2.反序列化 1.思路分析 2.代码实现 四.中序遍历 1.序列化 1.思路分析 2.代…

SpringBoot 使用Prometheus采集自定义指标数据

一、我们需要什么指标 对于DDD、TDD等&#xff0c;大家比较熟悉了&#xff0c;但是对于MDD可能就比较陌生了。MDD是Metrics-Driven Development的缩写&#xff0c;主张开发过程由指标驱动&#xff0c;通过实用指标来驱动快速、精确和细粒度的软件迭代。MDD可使所有可以测量的东…

RPC调用框架简单介绍

一.Thrift Apache Doris目前使用的RPC调度框架。Thrift是一款基于CS&#xff08;client -server&#xff09;架构的RPC通信框架&#xff0c;开发人员可以根据定义Thrift的IDL(interface decription language)文件来定义数据结构和服务接口&#xff0c;灵活性高&#xff0c;支持…

Leetcode.2583 二叉树中的第 K 大层和

题目链接 Leetcode.2583 二叉树中的第 K 大层和 Rating &#xff1a; 1374 题目描述 给你一棵二叉树的根节点 root和一个正整数 k 。 树中的 层和 是指 同一层 上节点值的总和。 返回树中第 k 大的层和&#xff08;不一定不同&#xff09;。如果树少于 k 层&#xff0c;则返…

INFINONE XC164单片机逆向记录(5)C166地址系统

本人所写的博客都为开发之中遇到问题记录的随笔,主要是给自己积累些问题。免日后无印象,如有不当之处敬请指正(欢迎进扣群 24849632 探讨问题); 写在专栏前面https://blog.csdn.net/Junping1982/article/details/129955766 INFINONE XC164单片机逆向记录(1)资料准备

Python爬虫知识回顾

之前一直沉溺于java&#xff0c;jsp&#xff0c;ssh&#xff0c;db等爬虫&#xff0c;现在又要开始走python的老路了。常用的requests库&#xff0c;通过requests对象的get方法&#xff0c;获取一个response对象。jsp的东西。 其中timeout,proxies,headers,cookies,verify,是我…

webgl-画指定颜色三角形

html <!DOCTYPE html> <head> <style> *{ margin: 0px; padding: 0px; } </style> </head> <body> <canvas id webgl> 您的浏览器不支持HTML5,请更换浏览器 </canvas> <script src"./main.js"></script&g…

JUC之CountDownLatch与CyclicBarrier

1.前言 在java.util.concurrent包中为我们提供了很多的线程同步工具类&#xff0c;例如CountDownLatch与CyclicBarrier&#xff0c;那么它们主要的用途是什么呢&#xff1f;且看后续分析。 2.CountDownLatch 2.1 什么是CountDownLatch CountDownLatch&#xff0c;顾名思义&…

从ReentrantLock角度解析AQS

一、概述 闲来不卷&#xff0c;随便聊一点。 一般情况下&#xff0c;大家系统中至少也是JDK8了&#xff0c;那想必对于JDK5加入的一系列功能并不陌生吧。那时候重点加入了java.util.concurrent并发包&#xff0c;我们简称为JUC。JUC下提供了很多并发编程实用的工具类&#xf…

风光及负荷多场景随机生成与缩减

目录 1 主要内容 计算模型 场景生成与聚类方法应用 2 部分程序 3 程序结果 4 程序链接 1 主要内容 该程序方法复现了《融合多场景分析的交直流混合微电网多时间尺度随机优化调度策略》3.1节基于多场景技术的随机性建模部分&#xff0c;该部分是随机优化调度的重要组成部分…

记录-css实现交融文字效果

这里给大家分享我在网上总结出来的一些知识&#xff0c;希望对大家有所帮助 CSS是有魔法的&#xff0c;我们今天来实现一个CSS的动画效果&#xff0c;只需要几行代码就可以搞定。 第一步、我们要将一行文字从中间展开 <!DOCTYPE html> <html lang"en"> &…

面试官:聊聊js原型

一分钟了解原型对象 js分为函数对象和普通对象 &#xff0c;每个对象都有__proto__属性&#xff0c;但是只有函数对象才有prototype属性&#xff0c;prototype属性就是函数的原型对象。 比如说 构造函数通过new 实化一个实例对象&#xff0c;实例对象的__proto__ 指向原型对象…

NumPy 基础知识 :6~10

原文&#xff1a;Numpy Essentials 协议&#xff1a;CC BY-NC-SA 4.0 译者&#xff1a;飞龙 六、NumPy 中的傅立叶分析 除其他事项外&#xff0c;傅立叶分析通常用于数字信号处理。 这要归功于它在将输入信号&#xff08;时域&#xff09;分离为以离散频率&#xff08;频域&am…