> 文章列表 > 【java】泛型编程

【java】泛型编程

【java】泛型编程

文章目录

    • 泛型类
    • 泛型与多态
    • 泛型方法
    • 泛型界限
    • 类型擦除
    • 函数式接口
      • 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> {@Overridepublic 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> {//让子类继续为一个泛型类,那么可以不用明确@Overridepublic 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>() {@Overridepublic 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]

泛型界限

设置上界

【java】泛型编程

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

设置下界

【java】泛型编程

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>{   //设定上界为Numberabstract 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>{@OverrideString 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对象的Supplierprivate 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);}
}

股票知识