【java】泛型编程

简介: 【java】泛型编程

泛型类

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]

泛型界限

设置上界

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());
    }
}

设置下界

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);
    }
}


目录
相关文章
|
7天前
|
安全 Java 数据处理
Java并发编程:解锁多线程的潜力
在数字化时代的浪潮中,Java作为一门广泛使用的编程语言,其并发编程能力是提升应用性能和响应速度的关键。本文将带你深入理解Java并发编程的核心概念,探索如何通过多线程技术有效利用计算资源,并实现高效的数据处理。我们将从基础出发,逐步揭开高效并发编程的面纱,让你的程序运行得更快、更稳、更强。
|
4天前
|
Java 数据库连接 网络安全
JDBC数据库编程(java实训报告)
这篇文章是关于JDBC数据库编程的实训报告,涵盖了实验要求、实验环境、实验内容和总结。文中详细介绍了如何使用Java JDBC技术连接数据库,并进行增删改查等基本操作。实验内容包括建立数据库连接、查询、添加、删除和修改数据,每个部分都提供了相应的Java代码示例和操作测试结果截图。作者在总结中分享了在实验过程中遇到的问题和解决方案,以及对Java与数据库连接操作的掌握情况。
JDBC数据库编程(java实训报告)
|
10天前
|
存储 算法 Java
14 Java集合(集合框架+泛型+ArrayList类+LinkedList类+Vector类+HashSet类等)
14 Java集合(集合框架+泛型+ArrayList类+LinkedList类+Vector类+HashSet类等)
30 2
14 Java集合(集合框架+泛型+ArrayList类+LinkedList类+Vector类+HashSet类等)
|
23小时前
|
Java 开发者
在Java编程中,if-else与switch作为核心的条件控制语句,各有千秋。if-else基于条件分支,适用于复杂逻辑;而switch则擅长处理枚举或固定选项列表,提供简洁高效的解决方案
在Java编程中,if-else与switch作为核心的条件控制语句,各有千秋。if-else基于条件分支,适用于复杂逻辑;而switch则擅长处理枚举或固定选项列表,提供简洁高效的解决方案。本文通过技术综述及示例代码,剖析两者在性能上的差异。if-else具有短路特性,但条件增多时JVM会优化提升性能;switch则利用跳转表机制,在处理大量固定选项时表现出色。通过实验对比可见,switch在重复case值处理上通常更快。尽管如此,选择时还需兼顾代码的可读性和维护性。理解这些细节有助于开发者编写出既高效又优雅的Java代码。
6 2
|
23小时前
|
Java 开发者
在Java编程的广阔天地中,if-else与switch语句犹如两位老练的舵手,引领着代码的流向,决定着程序的走向。
在Java编程中,if-else与switch语句是条件判断的两大利器。本文通过丰富的示例,深入浅出地解析两者的特点与应用场景。if-else适用于逻辑复杂的判断,而switch则在处理固定选项或多分支选择时更为高效。从逻辑复杂度、可读性到性能考量,我们将帮助你掌握何时选用哪种语句,让你在编程时更加得心应手。无论面对何种挑战,都能找到最适合的解决方案。
5 1
|
23小时前
|
搜索推荐 Java 程序员
在Java编程的旅程中,条件语句是每位开发者不可或缺的伙伴,它如同导航系统,引导着程序根据不同的情况做出响应。
在Java编程中,条件语句是引导程序根据不同情境作出响应的核心工具。本文通过四个案例深入浅出地介绍了如何巧妙运用if-else与switch语句。从基础的用户登录验证到利用switch处理枚举类型,再到条件语句的嵌套与组合,最后探讨了代码的优化与重构。每个案例都旨在帮助开发者提升编码效率与代码质量,无论是初学者还是资深程序员,都能从中获得灵感,让自己的Java代码更加优雅和专业。
5 1
|
23小时前
|
Java
在Java编程的广阔天地中,条件语句是控制程序流程、实现逻辑判断的重要工具。
在Java编程中,if-else与switch作为核心条件语句,各具特色。if-else以其高度灵活性,适用于复杂逻辑判断,支持多种条件组合;而switch在多分支选择上表现优异,尤其适合处理枚举类型或固定选项集,通过内部跳转表提高执行效率。两者各有千秋:if-else擅长复杂逻辑,switch则在多分支选择中更胜一筹。理解它们的特点并在合适场景下使用,能够编写出更高效、易读的Java代码。
5 1
|
22小时前
|
缓存 负载均衡 安全
|
3天前
|
设计模式 算法 Java
Java编程中的设计模式:简化复杂性的艺术
在Java的世界中,设计模式如同一位智慧的导师,指引着开发者们在复杂的编码迷宫中找到出口。本文将深入浅出地探讨几种常见的设计模式,通过实例演示如何在Java项目实践中运用这些模式,从而提升代码的可维护性和扩展性。无论你是新手还是资深开发者,这篇文章都将为你打开一扇通往高效编码的大门。
12 1
|
6天前
|
设计模式 数据采集 安全
掌握Java并发编程:从基础到高级
Java语言以其强大的并发处理能力而著称,在多核处理器日益普及的今天,有效利用并发编程技术可以显著提高应用程序的性能。本文将深入浅出地介绍Java并发编程的核心概念、实用工具类和设计模式,并结合实例展示如何在Java中实现高效的并发处理。无论你是初学者还是有经验的开发者,这篇文章都将为你开启Java并发编程的大门,带你领略它的奥妙与魅力。
17 3