import java.util.*;

public class Test {
    public static void main(String[] args) {
//        GenericMethods.test();
//        GenericVarargs.test();
        BasicGeneratorDemo.test();
    }
}

/*
    如论合适,如果使用泛型方法可以取代将整个类泛型化,那么就应该只使用泛型方法
    因为它可以使事情更清楚明白。另外,对于一个static的方法而言,无法访问泛型类
    的类型参数,所以,如果static方法需要使用泛型的能力,就必须使其成为泛型方法
 */

class GenericMethods {
    public <T> void f(T x) {
        System.out.println(x.getClass().getName());
    }

    public static void test() {
        GenericMethods gm = new GenericMethods();
//        gm.f("");
//        gm.f(1);
//        gm.f(1.0);
//        gm.f('c');
//        gm.f(gm);
        gm.f(New.map());
    }
}

/*
    需求:
        利用方法的推导功能,简化我们创建集合类时的编码,但是这个工作
        现在已经不需要了,因为IDE和编译器都可以满足自动推导的功能。
 */
class New {
    public static <K,V> Map<K,V> map() {
        return new HashMap<>();
    }
}

/*
    类型推导只对赋值操作有效果,其他时候并不起作用。如果你将一个泛型方法
    调用的结果(例如New.map())作为参数,传递给另一个方法时,这时候编译
    器并不会执行类型推导。这种情况下,编译器认为:调用泛型方法后,其返回值
    被赋给了一个Object类型的变量
        ——现在好像可以哦
 */
class LimtsOfInference {
    static void f(Map<String, List<? extends Map>> arg) {

    }

    static void test() {
        f(New.map());
    }
}
/*
    泛型方法中,显式指明类型的语法。要显式指明类型,必须在点操作符
    与方法名之间插入尖括号,然后把类型置于尖括号内。
        ——这些知识点,有点不适用了,现在
 */
class LimtsOfInference2 {
    static void f(Map<String, List<? extends Map>> arg) {

    }

    static void test() {
        f(New.<String,List<? extends Map>>map());
    }
}

/*
    15.4.2 可变参数与泛型方法
 */
class GenericVarargs {
    public static <T> List<T> makeList(T... args) {
        List<T> result = new ArrayList<>();
        for (T item : args) {
            result.add(item);
        }
        return result;
    }

    static void test() {
        List<String> ls = makeList("A");
        System.out.println(ls);

        ls = makeList("A", "B", "C");
        System.out.println(ls);

        ls = makeList("adfasdfsafsdf".split(""));
        System.out.println(ls);
    }
}

/*
    15.4.3 用于Generator的泛型方法
 */
interface Generator<T>{
    T next();
}
class Generators {
    //给我一个容器,给我一个生成器,我帮你把容器填满,只省下了几行for循环的代码
    public static <T> Collection<T> fill(Collection<T> coll, Generator<T> gen, int len) {
        ; i < len; i++) {
            coll.add(gen.next());
        }
        return coll;
    }
}

/*
    15.4.4 一个同游的Generator

    下面的程序,可以为任何类构造一个Generator,只要该类具有默认的构造器,为了
    减少类型的声明,它提供了一个泛型的方法,用于生成BasicGenerator。我感觉我
    上一个小节的代码,也可以为任何类构造了一个Generator啊

    我觉得真正的区别会在这儿,以往的Generator,是需要自己去实现next()部分的
    代码的,而这个Generator却不用,你传给它一个Class对象,它就能为你生成许多
    个对象,是真正意义上的简化了操作
 */
class BasicGenerator<T> implements Generator<T> {

    private Class<T> type;

    public BasicGenerator(Class<T> type) {
        this.type = type;
    }

    @Override
    public T next() {
        try {
            return type.newInstance();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
        return null;
    }

    public static <T> Generator<T> create(Class<T> type) {
        return new BasicGenerator<>(type);
    }
}

class CounterObject {
    ;
    private final long id = counter++;

    public long id() {
        return id;
    }

    public String toString() {
        return "Counted Object "+id;
    }
}

class BasicGeneratorDemo {
    static void test() {
        Generator<CounterObject> g = BasicGenerator.create(CounterObject.class);
        ; i < ; i++) {
            System.out.println(g.next());
        }
    }
}

/*
    15.4.5 简化元组的使用
 */

class TwoTuple<A, B> {
    public final A first;
    public final B second;

    public TwoTuple(A first, B second) {
        this.first = first;
        this.second = second;
    }

    public String toString() {
        return "(" + first + "," + second + ")";
    }
}

/*
    这个方案只是在创建的时候,给简化了一下,统一了一下创建的接口
 */
class Tuple {
    public static <A, B> TwoTuple<A, B> tuple(A a, B b) {
        return new TwoTuple<>(a, b);
    }
}

/*
    问题:
        方法f()返回一个参数化的TwoTuple对象,而f2()返回的是非参数化的
        TwoPuple对象。在这个例子中,编译器并没有f2()的警告信息,因为我们
        并没有将其返回值作为参数化对象使用。在某种意义上,它被“向上转型”为
        一个非参数化的TwoTuple。然而,如果试图将f2()的返回值转型为参数化
        的TwoTuple,编译器就会发出警告
            ——有点尴尬,参数化其实就是指的泛型化
 */
class TupleTest {
    static TwoTuple<String, String> f() {
        return Tuple.tuple("AAA","BBB");
    }

    static TwoTuple f2() {
        return  Tuple.tuple("BBB","CCC");
    }

    static void test(){}
}

/*
    15.4.6 一个Set实用工具

    需求:
        用Set表示集合的各种关系,如交集、并集、、补集
 */
class Sets {
    public static <T> Set<T> union(Set<T> a, Set<T> b) {
        Set<T> result = new HashSet<>(a);
        a.addAll(b);
        return result;
    }

    public static <T> Set<T> intersection(Set<T> a, Set<T> b) {
        Set<T> result = new HashSet<>(a);
        result.retainAll(b);
        return result;
    }

    public static <T> Set<T> difference(Set<T> superset, Set<T> subset){
        Set<T> result = new HashSet<>(superset);
        result.retainAll(subset);
        return result;
    }

    public static <T> Set<T> complement(Set<T> a, Set<T> b) {
        return difference(union(a,b),intersection(a,b));
    }
}

enum Letters{
    A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z
}

/*
    EnumSet:
        用来从enum直接创建Set,在这儿,我们向static方法EnumSet.range()传入某个范围的
        第一个元素和最后一个元素,然后它将返回一个Set,其中包括该范围内的所有元素
 */

class LettersDemo {
    static void test() {
        /*
            我看案例中,有一个import static.generics.watercolors.Watercolos.*
            又看到他解释说:为了方便起见(可以直接使用enum中的元素名),下面的实例以
            static的方式引入Watercolors。
                ——这种写法,我从来没有用过,标记一下
         */
        Set<Letters> l1 = EnumSet.range(Letters.A, Letters.D);
        //。。。
    }
}

Java编程思想:泛型方法的更多相关文章

  1. Java编程思想(11~17)

    [注:此博客旨在从<Java编程思想>这本书的目录结构上来检验自己的Java基础知识,只为笔记之用] 第十一章 持有对象 11.1 泛型和类型安全的容器>eg: List<St ...

  2. 《Java编程思想》读书笔记

    前言 这个月一直没更新,就是一直在读这本<Java编程思想>,这本书可以在Java业界被传神的一本书,无论谁谈起这本书都说好,不管这个人是否真的读过这本书,都说啊,这本书很好.然后再看这边 ...

  3. Java编程思想(后)

    Java编程思想(后) 持有对象 如果一个程序只包含固定数量的且其生命期都是已知的对象,那么这是一个非常简单的程序. Java中的库基本类型: List, Set, Queue和Map --- 称为集 ...

  4. Java中的泛型 --- Java 编程思想

    前言 ​ 我一直都认为泛型是程序语言设计中一个非常基础,重要的概念,Java 中的泛型到底是怎么样的,为什么会有泛型,泛型怎么发展出来的.通透理解泛型是学好基础里面中非常重要的.于是,我对<Ja ...

  5. JAVA编程思想——分析阅读

    需要源码.JDK1.6 .编码风格参考阿里java规约 7/12开始 有点意识到自己喜欢理论大而泛的模糊知识的学习,而不喜欢实践和细节的打磨,是因为粗心浮躁导致的么? cron表达式使用 设计能力.领 ...

  6. Java编程思想 笔记

    date: 2019-09-06 15:10:00 updated: 2019-09-24 08:30:00 Java编程思想 笔记 1. 四类访问权限修饰词 \ 类内部 本包 子类 其他包 publ ...

  7. 《Java编程思想》读书笔记(二)

    三年之前就买了<Java编程思想>这本书,但是到现在为止都还没有好好看过这本书,这次希望能够坚持通读完整本书并整理好自己的读书笔记,上一篇文章是记录的第一章到第十章的内容,这一次记录的是第 ...

  8. JAVA编程思想(第四版)学习笔记----4.8 switch(知识点已更新)

    switch语句和if-else语句不同,switch语句可以有多个可能的执行路径.在第四版java编程思想介绍switch语句的语法格式时写到: switch (integral-selector) ...

  9. 《Java编程思想》学习笔记(二)——类加载及执行顺序

    <Java编程思想>学习笔记(二)--类加载及执行顺序 (这是很久之前写的,保存在印象笔记上,今天写在博客上.) 今天看Java编程思想,看到这样一道代码 //: OrderOfIniti ...

  10. #Java编程思想笔记(一)——static

    Java编程思想笔记(一)--static 看<Java编程思想>已经有一段时间了,一直以来都把笔记做在印象笔记上,今天开始写博客来记录. 第一篇笔记来写static关键字. static ...

随机推荐

  1. linux下计划任务学习记录

    0x01 计划任务简介 linux 中计划任务主要分为”循环执行”和”只执行一次”两种,分别对应的时 crond 服务 和 atd 服务: 0x02 只执行一次的计划任务 0x02.1 atd 服务说 ...

  2. SqlServer 更改复制代理配置文件参数及两种冲突策略设置

    原文:SqlServer 更改复制代理配置文件参数及两种冲突策略设置 由于经常需要同步测试并更改代理配置文件属性,所以总结成脚本,方便测试. 可更新订阅的冲突策略有两种情况:一是在发布中冲突,即订阅数 ...

  3. 奇虎360选择IPO “壳概念”很受伤

    黄一帆   “市场正呈现出为一幕经典影像:在绚丽的霞光笼罩下,蔚蓝色的大海边,在金色的海岸上,欢笑的孩子们踮起脚尖,刚好看见原来海平面露出的航船桅杆——那是缓缓驶来的注册制号:而转过头来,则是沙滩上大 ...

  4. Tcptrack —— TCP 连接的嗅探器

    分享 <关于我> 分享  [中文纪录片]互联网时代                 http://pan.baidu.com/s/1qWkJfcS 分享 <HTML开发MacOSAp ...

  5. Elasticsearch ML

    Elastic公司在收购了Prelert半年之后,终于在Elasticsearch 5中推出了Machine Learning功能.Prelert本身就擅长做时序性数据的异常检测,从这点上讲也比较契合 ...

  6. Postman调试中文出现乱码问题

    最近在通过postman调试接口的时候,发现post的数据在中文的时候,传输到后台变成了问号(???),经过网上的资料与验证,找到了解决方案:在请求头中添加charset=UTF-8的属性,后续在进行 ...

  7. 判断本地系统目录下是否存在XML文件,如果不存在就创建一个XMl文件,若存在就在里面执行添加数据

    这是我为项目中写的一个测试的例子, 假如,您需要这样一个xml文件, <?xml version="1.0" encoding="utf-8"?> ...

  8. Spring之bean生命始末

    可以为Bean定制初始化后的生命行为,也可以为Bean定制销毁前的生命行为.举例:ba06包.首先,这些方法需要在Bean类中事先定义好:是方法名随意的public void方法. 其次,在配置文件的 ...

  9. RSA der加密 p12解密以及配合AES使用详解

    在前面的文章中我有说过AES和RSA这两种加密方式,正好在前段时间再项目中有使用到,在这里再把这两种加密方式综合在一起写一下,具体到他们的使用,以及RSA各种加密文件的生成. 一: RSA各种加密相关 ...

  10. 每天学点node系列-stream

    在编写代码时,我们应该有一些方法将程序像连接水管一样连接起来 -- 当我们需要获取一些数据时,可以去通过"拧"其他的部分来达到目的.这也应该是IO应有的方式. -- Doug Mc ...