searchusermenu
  • 发布文章
  • 消息中心
点赞
收藏
评论
分享
原创

优先考虑泛型方法

2024-05-29 09:08:35
15
0

主要介绍泛型方法的使用

如果方法参数或者返回值是类型可变的容器,则需要使用泛型方法,使用泛型方法对参数进行限制的示例如下:

public class Demo01 {

    private static final Logger LOG = LoggerFactory.getLogger(Demo01.class);

    // 不使用泛型方法,无法对参数进行限制
    public static Set UnionWithoutGeneric(Set s1, Set s2) {
        Set result = new HashSet(s1);
        result.addAll(s2);
        return result;
    }

    // 使用泛型方法,可以对参数进行限制
    public static <E> Set<E> UnionUseGeneric(Set<E> s1, Set<E> s2) {
        Set<E> result = new HashSet<>(s1);
        result.addAll(s2);
        return result;
    }

    @Test
    public void test() {
        Set<String> s1 = Sets.newHashSet("a", "b", "c");
        Set<Integer> s2 = Sets.newHashSet(1, 2, 3, 4);

        Set<String> res1 = UnionWithoutGeneric(s1, s2);
        // 2024-01-16 09:48:54,127 | INFO | Demo01.java.test(): 41 - [a, 1, b, 2, c, 3, 4]
        LOG.info(res1.toString());

        // 使用泛型方法,可以避免堆污染
        // Set<String> objects = UnionUseGeneric(s1, s2);
        Set<Integer> res2 = unionUseGeneric(s2, s3);
        // 2024-01-16 09:55:18,275 | INFO | Demo01.java.test(): 50 - [1, 2, 3, 4, 5, 6, 7, 8]
        LOG.info(res2.toString());
    }
}

集合排序方法的标准写法

public static <E extends Comparable<E>> E max(Collection<E> c, boolean failFast) {
        if (c.isEmpty() && failFast) {
            throw new IllegalArgumentException("Empty Collection");
        }

        E result = null;
        for (E e : c) {
            if (result == null || e.compareTo(result) > 0) {
                result = Objects.requireNonNull(e);
            }
        }

        return result;
    }

恒等函数示例:

static class Demo11 {
        static <T> Function<T, T> identity() {
            return t -> t;
        }
    }

协变、逆变

public class Covariance {
    public static final Logger LOG = LoggerFactory.getLogger(Covariance.class);

    public static void testvCovariance(List<? extends Apple> lst) {
        // 只能调用读取方法,无法调用修改方法
        Apple apple = lst.get(0);
        // lst.add(new BigApple());
        LOG.info("Covariance:" + lst);
    }

    public static void testContravariance(List<? super Apple> lst) {
        // 调用读取方法只能读到Object类型
        Object object = lst.get(0);
        // 一般只调用修改方法
        lst.add(0, new BigApple());
        LOG.info("Contravariance:" + lst);
    }

    @Test
    public void test() {
        List<Fruit> lst1 = Lists.newArrayList(new Fruit());
        List<Orange> lst2 = Lists.newArrayList(new Orange());
        List<Apple> lst3 = Lists.newArrayList(new Apple());
        List<BigApple> lst4 = Lists.newArrayList(new BigApple());

//        testvCovariance(lst1);
//        testvCovariance(lst2);
        // Covariance:[com.pcx.chapter01.Apple@6295d394]
        testvCovariance(lst3);
        // Covariance:[com.pcx.chapter01.BigApple@fdefd3f]
        testvCovariance(lst4);

        // Contravariance:[com.pcx.chapter01.BigApple@d83da2e, com.pcx.chapter01.Fruit@a4102b8]
        testContravariance(lst1);
//        testContravariance(lst2);
        // Contravariance:[com.pcx.chapter01.BigApple@11dc3715, com.pcx.chapter01.Apple@6295d394]
        testContravariance(lst3);
//        testContravariance(lst4);
    }
}

使用泛型实现异构容器

public class Favourites {
    private final Map<Class<?>, Object> favourite = Maps.newHashMap();

    private static final Logger LOG = LoggerFactory.getLogger(Favourites.class);

    public <T> T getFavourite(Class<T> type) {
        return type.cast(favourite.get(type));
    }

    public <T> void putFavourite(Class<T> type, T instance) {
        favourite.put(Objects.requireNonNull(type), type.cast(instance));
    }

    @Test
    public void test() {
        Favourites f = new Favourites();
        f.putFavourite(String.class, "Java");
        f.putFavourite(Integer.class, 1231);

        String f1 = f.getFavourite(String.class);
        Integer f2 = f.getFavourite(Integer.class);
        LOG.info(f1);
        LOG.info("" + f2);
    }
}

总结

  1. 泛型定义:<E extends Comparable<E>> E
  2. 泛型方法可以通过先定义返回值进行限制;
  3. 泛型容器取东西,用super,将东西放入泛型容器则使用extend;
  4. 如果参数化类型是一个生产者,即提供数据则使用 <? extends T>,只能调用其读取方法;
  5. 如果它表示一个消费者,那就使用 <? super T>,只能调用其设置方法。
0条评论
0 / 1000
pancx
3文章数
0粉丝数
pancx
3 文章 | 0 粉丝
pancx
3文章数
0粉丝数
pancx
3 文章 | 0 粉丝
原创

优先考虑泛型方法

2024-05-29 09:08:35
15
0

主要介绍泛型方法的使用

如果方法参数或者返回值是类型可变的容器,则需要使用泛型方法,使用泛型方法对参数进行限制的示例如下:

public class Demo01 {

    private static final Logger LOG = LoggerFactory.getLogger(Demo01.class);

    // 不使用泛型方法,无法对参数进行限制
    public static Set UnionWithoutGeneric(Set s1, Set s2) {
        Set result = new HashSet(s1);
        result.addAll(s2);
        return result;
    }

    // 使用泛型方法,可以对参数进行限制
    public static <E> Set<E> UnionUseGeneric(Set<E> s1, Set<E> s2) {
        Set<E> result = new HashSet<>(s1);
        result.addAll(s2);
        return result;
    }

    @Test
    public void test() {
        Set<String> s1 = Sets.newHashSet("a", "b", "c");
        Set<Integer> s2 = Sets.newHashSet(1, 2, 3, 4);

        Set<String> res1 = UnionWithoutGeneric(s1, s2);
        // 2024-01-16 09:48:54,127 | INFO | Demo01.java.test(): 41 - [a, 1, b, 2, c, 3, 4]
        LOG.info(res1.toString());

        // 使用泛型方法,可以避免堆污染
        // Set<String> objects = UnionUseGeneric(s1, s2);
        Set<Integer> res2 = unionUseGeneric(s2, s3);
        // 2024-01-16 09:55:18,275 | INFO | Demo01.java.test(): 50 - [1, 2, 3, 4, 5, 6, 7, 8]
        LOG.info(res2.toString());
    }
}

集合排序方法的标准写法

public static <E extends Comparable<E>> E max(Collection<E> c, boolean failFast) {
        if (c.isEmpty() && failFast) {
            throw new IllegalArgumentException("Empty Collection");
        }

        E result = null;
        for (E e : c) {
            if (result == null || e.compareTo(result) > 0) {
                result = Objects.requireNonNull(e);
            }
        }

        return result;
    }

恒等函数示例:

static class Demo11 {
        static <T> Function<T, T> identity() {
            return t -> t;
        }
    }

协变、逆变

public class Covariance {
    public static final Logger LOG = LoggerFactory.getLogger(Covariance.class);

    public static void testvCovariance(List<? extends Apple> lst) {
        // 只能调用读取方法,无法调用修改方法
        Apple apple = lst.get(0);
        // lst.add(new BigApple());
        LOG.info("Covariance:" + lst);
    }

    public static void testContravariance(List<? super Apple> lst) {
        // 调用读取方法只能读到Object类型
        Object object = lst.get(0);
        // 一般只调用修改方法
        lst.add(0, new BigApple());
        LOG.info("Contravariance:" + lst);
    }

    @Test
    public void test() {
        List<Fruit> lst1 = Lists.newArrayList(new Fruit());
        List<Orange> lst2 = Lists.newArrayList(new Orange());
        List<Apple> lst3 = Lists.newArrayList(new Apple());
        List<BigApple> lst4 = Lists.newArrayList(new BigApple());

//        testvCovariance(lst1);
//        testvCovariance(lst2);
        // Covariance:[com.pcx.chapter01.Apple@6295d394]
        testvCovariance(lst3);
        // Covariance:[com.pcx.chapter01.BigApple@fdefd3f]
        testvCovariance(lst4);

        // Contravariance:[com.pcx.chapter01.BigApple@d83da2e, com.pcx.chapter01.Fruit@a4102b8]
        testContravariance(lst1);
//        testContravariance(lst2);
        // Contravariance:[com.pcx.chapter01.BigApple@11dc3715, com.pcx.chapter01.Apple@6295d394]
        testContravariance(lst3);
//        testContravariance(lst4);
    }
}

使用泛型实现异构容器

public class Favourites {
    private final Map<Class<?>, Object> favourite = Maps.newHashMap();

    private static final Logger LOG = LoggerFactory.getLogger(Favourites.class);

    public <T> T getFavourite(Class<T> type) {
        return type.cast(favourite.get(type));
    }

    public <T> void putFavourite(Class<T> type, T instance) {
        favourite.put(Objects.requireNonNull(type), type.cast(instance));
    }

    @Test
    public void test() {
        Favourites f = new Favourites();
        f.putFavourite(String.class, "Java");
        f.putFavourite(Integer.class, 1231);

        String f1 = f.getFavourite(String.class);
        Integer f2 = f.getFavourite(Integer.class);
        LOG.info(f1);
        LOG.info("" + f2);
    }
}

总结

  1. 泛型定义:<E extends Comparable<E>> E
  2. 泛型方法可以通过先定义返回值进行限制;
  3. 泛型容器取东西,用super,将东西放入泛型容器则使用extend;
  4. 如果参数化类型是一个生产者,即提供数据则使用 <? extends T>,只能调用其读取方法;
  5. 如果它表示一个消费者,那就使用 <? super T>,只能调用其设置方法。
文章来自个人专栏
Java设计模式
3 文章 | 1 订阅
0条评论
0 / 1000
请输入你的评论
0
0