IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> Java知识库 -> 日志 - 4 - @Repository、ssm整合模板、lambda与泛型方法、streamAPI -> 正文阅读

[Java知识库]日志 - 4 - @Repository、ssm整合模板、lambda与泛型方法、streamAPI

时间:2022年5月21日


上午

首先查询了@Component系列注解,很有印象,这几个注解我只用过@Controller……
参考文章被我放到spring收藏里了。

感觉差不多了之后就尝试写lambda,没想到上来踩了个大坑:lambda不能赋值给泛型方法。

目前正尝试理解lambda不能与泛型方法联动的理由。

  • @Component系列注解
    • @Component

      因为没有语义,常用来将非controller、service、dao包下的类交给spring,比如pojo、entity。

    • @Controller

      无需多说,老熟人了。

    • @Service

      这个可能要放到实现类(impl)上,反正我xml里配置的是实现类。
      ________________________________
      通过@Autowired注解实现类的mapper属性时,该属性可能会划波浪线,那是因为sprig找不到mapper的实现类。此时,在applictionContext.xml中将它们配置成<bean>,其mapper属性也是找不到对象的(赋值一定要用ref而不是value)。
      实际上,mapper确实没有实现类,它的接口对应的是mapper.xml。
      在applicationContext.xml中配置org.mybatis.spring.mapper.MapperScannerConfigurer的<bean>可以让spring找到这些xml文件。

    • @Repository

      注解在dao包的类上。
      ________________________________
      配置了org.mybatis.spring.mapper.MapperScannerConfigurer的<bean>后,似乎就用不到这个注解了。

    • @Mapper

      这是mybatis的注解,用来告诉mybatis被它注解的类应该有个mapper.xml。
      ________________________________
      由于是mybatis的注解而不是spring的,这个注解并不能让spring将被它注解的类配置到applicationContext.xml中成为<bean>,也就是说,spring不能找到 被@Mapper注解的类。


总之,学到这里就对spring+mybatis有个模板了:

mybatis-config.xml
一、配置<settings>,开启日志、二级缓存等。

applicationContext.xml
二、用<context:property-placeholder>载入database.properties。
三、配置datasource的<bean>
四、配置SqlSessionFactoryBean的<bean>,传入datasource和configLocation(mybatis-condif.xml)
五、配置MapperScannerConfigurer的<bean>,传入SqlSessionFactoryBean和放置mapper的包。

applicationContext.xml
六、开<context:component-scan>,传入被扫描的包(多个包则开多个)
七、controller与service包中使用相关注解

顺便把spring+springmvc也写在这里:

applicationContext.xml
一、开<mvc:annotation-driven>,和<context:annotation-config>不是一个东西。
二、开<mvc:default-servlet-handler>,用于阻止spring的DispatcherServlet拦截前端对css、js、img等静态资源的请求。
三、配置org.springframework.web.servlet.view.InternalResourceViewResolver的<bean>,spring的视图解析器(话说这东西必须得配置吗?

web.xml
四、配置org.springframework.web.servlet.DispatcherServlet,传入applicationContext.xml。
五、配置org.springframework.web.filter.CharacterEncodingFilter,传入字符集名(是spring用于转换前后端字符集的内置filter)。

啊,浑身清爽 ~ ~

springboot+各种东西,这点还不太熟悉。

欠缺的部分:事务、spring中开启mapperscan后是否还要把mapper.xml配置给mybatis、


下午

看见 官方文档(英文)说lambda不支持泛型方法后,我就立马放弃了。不过好歹也算是为它烦恼了一个小时的,不留点记录怎么能行呢?

官方文档上记载了lambda不支持泛型方法,知道这件事是从别的文章上,不过文章有些短,就直接把官方文档搬过来了。

文档上说lambda不适应拥有类型参数(type parameter)的方法,那么什么是类型参数呢?

<E> E get(E e);

这个 E 就是类型参数,“<E>” 是在定义 E 这个类型参数。

已经很明显了,泛型就是通过类型参数(type parameter)来定义的,lambda不适应携带类型参数的方法,就是在直言无法支持泛型方法。

为什么呢?我的理解是这样的:

在泛型方法中定义的类型参数(E)只能在这个泛型方法中使用,脱离了这个泛型方法就再也没办法获取这个类型参数了。
而lambda本身就是为了在方法之外 “定义” 方法,既然已经身置泛型方法之外了,那就无论如何都不可能使用 E 这个类型了,就算再定义一个 E,此 E 非彼 E 也是不能用的。

干嘛非得使用泛型方法里的 E 呢?
你想啊,lambda是在干什么?是在重写函数式接口的唯一抽象方法。
那重写方法有什么条件?参数列表完全一致,返回值一致,方法名一致。
参数列表完全一致,这就要求你lambda必须用我泛型方法里定义的这个 E,而不是你自己定义的什么 T、V、K。哪怕你定义了一个 E,那也不是我泛型方法里的 E,和我的参数列表不一致,就不算重写我的方法。

lambda:你还想要我怎样???毁灭吧!

不过在 玩耍 debug 的过程中倒是发现了另外一件有趣的事情,双冒号表达式是可以支持泛型方法的……

不想了不想了,pass。

接下来是双冒号表达式 “MyClass::instance_method” 用法的使用条件:

一、抽象方法的参数必须比实例方法(instance_method)的参数多一个
二、多出来的这个参数必须是class类型的
三、多出来的这个参数必须在参数列表的首位(最左侧)。


接下来是我已经期待了两天的时刻:把lambda常见的应用场景收集起来!

话虽如此,但也就找到两条,其中一条算不算常用还很难说…( _ _)ノ|

  • lambda的常用场景

    new Thread(Runnable),创建一个线程,定义线程执行的代码。
    JButten_instance.addActionListener(ActionListener),给jbutton上监控,定义监控的执行代码。

  • java.util.stream.Stream

    这里有一篇 已经把stream解释得很清晰的文章,就是有点长,好在可以根据目录直接定位到stream那一段。
    这里有另一篇 也很详细地讲解了stream的文章(简书),就是有点多,好在也有目录(doge)

    三个特征:
    一、若不进行终端操作,所有代码都 不执行
    二、用了终端操作之后,这个流就 不能用了(可以保存成集合或数组,从而反复使用,缺点是每次使用都得再封装成流)。
    三、流不是集合,对流进行操作不是在对集合进行操作,无论如何都不会改变集合中的元素

    基本数据类型流:IntStream、LongStream、DoubleStream
    >>> toArray(),返回(拆封为)基本数据类型数组
    >>> boxed(),转换为 包装类对象流
    >>> 内置sum()、average()、max()、min()
    >>> Random_instance.ints(size, origin, bound),返回一个 IntStream 实例,其中size为元素数目,origin为最小值,bound为最大值,且左闭右开。(同样地,可以使用doubles(),longs())。
    >>> IntStream.range(start, end),返回一个IntStream实例,其中start为最小值,end为最大值,步长默认为1,左闭右开(DoubleStream没有这个静态方法。rangeClosed()可以包含右边界)
    ________________________________
    基本数据类型流的collect()无法通过collectors.toList()将它们封装成集合(没有这种重载),因为基本数据类型本来就没办法直接放到集合里。

    串行流(sequential())、并行流(parallel())、无序流(unordered())
    这方面有点模糊,可能是我还没有看到描述得很清晰的文档,目前对它们的了解仅限于:一个线程、多个线程、破坏有序集合的顺序。
    至于list.stream()究竟到手那种流……可能 是串行流?
    ________________________________
    对无序流有点在意,因为 javadoc 说对于[2,4,6]形成的集合,无序流模式下计算map(a->a*2)可能给出[12,4,8]这种结果,所以给它排序是很重要的,除非根本不在意它的顺序(这种场景还是蛮多的)。

    • 创建(包装为)stream

      list.stream(),从集合实例中获取流对象(以下简称 “流”)
      list.parallelStream(),从集合中获取并行流(另外两种流通过流对象转换)

      Arrays.stream(T[]),通过 T 数组构建一个流(有入参为int[]、long[]、double[]的重载方法,分别获取IntStream、LongStream、DoubleStream)

      Stream.of(T…),用一串元素构成流(类似Arrays.asList())

      Stream.Iterate(T, UnaryOperator<T>),迭代计算一个初始值,以每次得到的结果作为元素形成流(需要用 limit() 约束其迭代次数,否则它就是一个无限流,可能会被其他流操作截断为有限流)
      Stream.generate(supplier),根据被定义的供给者(supplier)获取数个元素,形成流(同上,以 limit() 约束)

    • 流操作(中间操作)

      limit(long),仅保留流中前n个元素(如果是无序流,因为流是无序的,所以不知道究竟保留了哪些元素)
      filter(predicate),筛选元素(保留使predicate.test()返回true的)。
      distinct(),去重。
      skip(long),跳过前n个元素。
      ________________________________
      这该死的 sql 既视感(笑死

      map(Function),按照Function的 “定义” 计算每一个元素,其结果映射为新的流(能用来获取对象属性,简直神迹)
      mapToXXX(ToXXXFunction),映射为 基本数据流(XXX为:Int、Long、Double)。
      flatMap(Function),将每个元素转换为流,最后合并成一个大流(同样,有int、long、double适用的方法)。
      ________________________________
      不能和下面的 reduce()放到一起还蛮可惜的,这回是hadoop既视感(笑死,我大数据还没入门

      sorted(),按照默认规则排序
      sorted(Comparator),传入一个比较器(函数式接口)

    • 终端操作(用了就会把流 消耗掉 的操作)

      reduce(T, BinaryOperator),根据二元算子(BinaryOperator)的 “定义” 进行迭代计算,得到一个 T 类型的返回值(参数 T 参与第一次迭代)。
      reduce(BinaryOperator),流中第一个元素与第二个元素进行第一次迭代,直至得到最终结果。
      ________________________________
      迭代:每次计算的结果作为下一次计算的参数之一。
      此方法不会影响流中元素,仅返回计算结果。

      XXXMatch(predicate),对每个元素进行测试(XXX:all,要求全部为true;any:任意一个为true;none,不能有true)
      findXXX(),获取一个元素(XXX:First,流中第一个;Any,任意一个)

      max(Comparator),传入比较器,返回最大值
      min(Comparator),传入比较器,返回最小值

      count(),返回元素总数(类似数组的 length,集合的 size())
      foreach(Consumer),对流中每个元素做些什么 ,但是禁止色色,另一件神器。
      collect(Collector),返回(拆封成)一个集合(一般Collectors的方法获取实参,Collectors 不是 Collector的实现类)
      toArray(IntFunction<A[]>),返回(拆封成)一个数组(传入 Integer[]::new 这种形式即可,有亿点复杂,换成 lambda 应该是这样的 a->new Integer[a],a 代表流的大小

    • Collectors(很多方法没放到这里)

      toList(),让collect()返回List集合。
      toSet(),让collect()返回Set集合。

我是真没想到一写就写了一下午,关键是文章还没看完……

此处 并没有 把Stream的所有方法枚举 把别人文章上的方法都搬过来了倒是真的

后记

有种整个下午都写跑题了的感觉,不过学了stream发现这东西是真好用。

遗留:

  • 收集日常可以用到lambda的方法(怨气……
  • 了解spring事务相关的部分(怨气*2……
  Java知识库 最新文章
计算距离春节还有多长时间
系统开发系列 之WebService(spring框架+ma
springBoot+Cache(自定义有效时间配置)
SpringBoot整合mybatis实现增删改查、分页查
spring教程
SpringBoot+Vue实现美食交流网站的设计与实
虚拟机内存结构以及虚拟机中销毁和新建对象
SpringMVC---原理
小李同学: Java如何按多个字段分组
打印票据--java
上一篇文章      下一篇文章      查看所有文章
加:2022-05-24 17:59:01  更:2022-05-24 18:00:52 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/23 20:18:25-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码