主页

2017编程提高第2节课(作业)

问题 重构一个简单的log打印,使之符合开闭原则(OCP) 解题 这个星期的作业似乎比上个星期的要简单,重构起来思路也很清晰,不过仍然有一些令我迷惑的地方,这个也在下面会讲到 分析 如图只有5个文件,功能分别为 DateUtil 在log中拼接上时间信息 Logger 提供主log方法 MailUtil 使用邮件发送log SMSUtil 使用sms发送log 当然啦,我相信这些方法都是瞎掰的,所以不用管,其实只要看一下Logger这个类中的方法就可以了,Logger类内容如下 public class Logger { public final int RAW_LOG = 1; public final int RAW_LOG_WITH_DATE = ...

阅读更多

2017编程提高第2节课——面向对象设计(2)

面向对象设计的原则 单一职责原则 (SRP) 开闭原则 (OCP) Liskov 替换原则 (LSP) 接口隔离原则 (ISP) 依赖倒置原则 (DIP)   SOLID 开闭原则(OCP) 可复用的“基石” 软件模块对扩展是开放的 当需求发生改变时,可以对模块进行扩展 软件模块对修改是封闭的 对模块进行扩展时, 无须改动模块的源代码。 似乎是矛盾的 ? 缺点 对扩展开放: 可以添加新的水果类 但是每次添加新的水果类,就需要修改ShopCart中的逻辑 修改后 对扩展开放 可以任意的添加新的水果类:香蕉...

阅读更多

2017编程提高第1.5节课——Java并发编程(1)

回顾一下 并发编程中最重要的两个概念:进程、线程 这里的栈、堆等概念都是操作系统层面的概念,并不特指某一种语言的设计方式,如Java虚拟机实际上是操作系统的一个进程 操作系统中使用虚拟内存映射的方式扩展每个进程可用的内存,好像每个进程都拥有全部的内存空间,实际上是通过操作系统调度让一个进程空闲的内存释放出来给其他进程使用 线程和进程 多线程中的代码、数据和文件均是各个线程共享的,每个线程拥有一套独立的寄存器和堆栈(逻辑上独立,实际上是同一个寄存器和堆栈空间的不同片), 为什么要用线程? 浏览器 线程1显示图像 线程2从网络接收数据 文字处理器 线程1显示图形 线程2读取用户键盘输入 ...

阅读更多

2017编程提高第1节课(作业)

问题 重构一个简单邮件发送,使之符合单一职责原则(SRP) 解题 分析 我们知道的是单一职责原则简单来说就是一个类只负责一件事,所以我们的任务是把含有多件事的类拆分开,所以先来看一下原代码中的结构和流程 这里用思维导图简单地表示了一下类结构和业务流程 流程 这个邮件处理的流程比较简单,如上图所示,即读取三个数据 商品降价数据 邮件发送服务器数据 需要发送的用户数据 然后根据以上三个信息发送邮件即可,当然其中还涉及一些数据的处理,但这三个获取数据的步骤+发送邮件就构成了整个逻辑,重构将以实现这四件事为中心来重构 类结构 从途中可以明显看到,所有的获取数据和处理都放在了PromotionMail这个类中,显然不符合单一职责原则,所以这个类中的方法必须拆分,我们首先可...

阅读更多

2017编程提高第1节课——面向对象设计(1)

从需求开始谈起 需求总是不完整的,错误的,容易让人产生误解 需求一直在变化 用户对需求的看法,可能在与开发人员讨论以及看到软件新的可能性后发生变化 随着对问题的熟悉, 开发人员对问题领域的看法也会变化 不是需求在变, 而是人们对需求的理解在变化 如何去应对变化? 软件工程层面→敏捷开发(常沟通,常迭代),通过多沟通来及时获取需求的变更,然后快速迭代来适应需求的变更 编码层面→封装变化 例子 假设你在一个会议上担当讲师, 听课的人在课后还要去听其他课程, 但他们不知道下一堂课的听课地点,你的责任就是, 确保大家都知道下一节课去哪儿上。 结构化的分析方法 自顶向下,逐层分解 获取听课人的名单 ...

阅读更多

计算机网络面试题集锦

OSI,TCP/IP,五层协议的体系结构,以及各层协议 OSI分层 (7层): 物理层 数据链路层 网络层 传输层 会话层 表示层 应用层 TCP/IP分层(4层): 网络接口层 网际层 运输层 应用层。 五层协议 (5层): 物理层 数据链路层 网络层 运输层 应用层 每一层的协议如下: 物理层:RJ45、CLOCK、IEEE802.3 (中继器,集线器) 数据链路:PPP、FR、HDLC、VLAN、MAC (网桥,交换机) 网络层:IP、ICMP、ARP、RARP、OSPF、IPX、RIP、IGRP、 (路由器) 传输层:TCP、UDP、SPX 会话层:NFS、SQL、NETB...

阅读更多

Java面试题集锦

Java基础 什么是Java虚拟机?为什么Java被称作是“平台无关的编程语言”? Java虚拟机是一个可以执行Java字节码的虚拟机进程。Java源文件被编译成能被Java虚拟机执行的字节码文件。 Java被设计成允许应用程序可以运行在任意的平台,而不需要程序员为每一个平台单独重写或者是重新编译。Java虚拟机让这个变为可能,因为它知道底层硬件平台的指令长度和其他特性。 JDK和JRE的区别是什么? Java运行时环境(JRE)是将要执行Java程序的Java虚拟机。它同时也包含了执行applet需要的浏览器插件。 Java开发工具包(JDK)是完整的Java软件开发包,包含了JRE,编译器和其他的工具(比如:JavaDoc,Java调试器),可以让开发者开发、编译、执行Jav...

阅读更多

Java修饰符

梗概 Java提供了很多的修饰符,修饰符用于描述类/方法/变量的一些属性,主要分为两类 访问修饰符 非访问修饰符 访问修饰符 用于描述该类/方法/变量的被访问的权限,关键字有四个,权限范围如下: 修饰符 包外 子类 包内 类内 public √ √ √ √ protected   √ √ √ default     √ √ ...

阅读更多

简单的JNI介绍和实例

native关键字 native是与C++联合开发的时候用的!使用native关键字说明这个方法是原生函数,也就是这个方法是用C/C++语言实现的,并且被编译成了DLL,由java去调用。 这些函数的实现体在DLL中,JDK的源代码中并不包含,你应该是看不到的。对于不同的平台它们也是不同的。这也是java的底层机制,实际上java就是在不同的平台上调用不同的native方法实现对操作系统的访问的。总而言之: native 是用做java 和其他语言(如c++)进行协作时使用的,也就是native 后的函数的实现不是用java写的。 既然都不是java,那就别管它的源代码了,我们只需要知道这个方法已经被实现即可。 native的意思就是通知操作系统, 这个函数你必须给我实现...

阅读更多

原码、反码和补码

概述 相信每一个学计算机的同学都头疼过原码,补码和反码这三个东西,甚至有时候还会冒出一个移码 我们人类在计数的时候,用的都是十进制,但是计算机可不认这个,它们的世界用的是二进制来表示数,这个时候我们如果想要了解它们的世界是怎么样的,那么首先就要认识它们是怎么数数的 我们把我们正常计数用的表示方法表示的数称为“真值”,把机器里面表达的数称为“机器数” 原码 概念 原码(true form) 是一种计算机中对数字的二进制定点表示方法.原码表示法在数值前面增加了一位符号位(即最高位为符号位):正数该位为0,负数该位为1(0有两种表示:+0和-0),其余位表示数值的大小. 数学表示如下(有的书上会约定符号位和数值位之间用逗号隔开,所以表达式会有所不同,这里的以没有逗号隔开的为准) 若$X$...

阅读更多

位运算

简介 我们都知道计算机里的数据实际上是通过二进制进行储存的,所以我们在计算机上的所有操作其实都是在操作这些二进制数据 位运算,意思就是在实际编程中对把数据当做二进制数进行运算操作,因为计算机实际上也是把数据转化为二进制数进行运算,所以我们直接使用二进制的运算方式计算的效率就会很高 试想如果是十进制运算的话,计算机还要先把十进制运算转化为二进制运算才开始计算,而我们直接使用二进制运算就跳过了中间”编译”的过程,这也是为什么我们说位运算的效率高. 种类 在Java里位运算共有7种,如下表 名称 Java 按位与 a & b 按位或 a |...

阅读更多

集合专题1 Collection

简介 Collection的相关关系图如下 Collection是一个接口,它主要的两个分支是:List 和 Set。 List和Set都是接口,它们继承于Collection List 有序1,可以有重复的元素 Set 无序,不可以有重复元素 List和Set都有它们各自的实现类。 为了方便,我们抽象出了AbstractCollection抽象类,它实现了Collection中的绝大部分函数;这样,在Collection的实现类中,我们就可以通过继承AbstractCollection省去重复编码。AbstractList和AbstractSet都继承于AbstractCollection,具体的List实现类继承于AbstractList,而Set的实现类则继承于...

阅读更多

集合专题3 LinkedList

简介 LinkedList 和 ArrayList 一样,都实现了 List 接口,但其内部的数据结构有本质的不同。LinkedList 是基于链表实现的(通过名字也能区分开来),所以它的插入和删除操作比 ArrayList 更加高效。但也是由于其为基于链表的,所以随机访问的效率要比 ArrayList 差。 public class LinkedList<E> extends AbstractSequentialList<E> implements List<E>, Deque<E>, Cloneable, java.io.Serializable{ ...... } 继承: AbstractSequentialList 继承...

阅读更多

集合专题2 ArrayList

简介 ArrayList 可以理解为动态数组,用 MSDN 中的说法,就是 Array 的复杂版本。与 Java 中的数组相比,它的容量能动态增长。ArrayList 是 List 接口的可变数组的实现。实现了所有可选列表操作,并允许包括 null 在内的所有元素。除了实现 List 接口外,此类还提供一些方法来操作内部用来存储列表的数组的大小。 每个 ArrayList 实例都有一个容量,该容量是指用来存储列表元素的数组的大小。它总是至少等于列表的大小。随着向 ArrayList 中不断添加元素,其容量也自动增长。自动增长会带来数据向新数组的重新拷贝,因此,如果可预知数据量的多少,可在构造 ArrayList 时指定其容量。在添加大量元素前,应用程序也可以使用 ensureCapac...

阅读更多

插入排序(Insertion Sort)

概念 插入排序是一种简单直观的排序算法. 通过构建有序序列,对于未排序数据,在已排序序列中从后向前扫描,找到相应位置并插入。插入排序在实现上,通常采用in-place排序,因而在从后向前扫描过程中,需要反复把已排序元素逐步向后挪位,为最新元素提供插入空间。 步骤 从第一个元素开始,该元素可以认为已经被排序 取出下一个元素,在已经排序的元素序列中从后向前扫描 如果该元素(已排序)大于新元素,将该元素移到下一位置 重复步骤3,直到找到已排序的元素小于或者等于新元素的位置 将新元素插入到该位置后 重复步骤2~5 举例 例1 现有一组数组[5, 6, 3, 1, 8, 7, 2, 4],共有八个记录,排序过程如下: [5] 6 3 1 8 7 2 4 我们...

阅读更多