整理学习Java时记得笔记
设计模式的六大原则
1. 开闭原则(Open Close Principle)
开闭原则就是说对扩展开放,对修改关闭。在程序需要进行拓展的时候, 不能去修改原有的代码,实现一个热插拔的效果。所以一句话概括就是: 为了使程序的扩展性好,易于维护和升级。想要达到这样的效果,我们需 要使用接口和抽象类,后面的具体设计中我们会提到这点上。
不要让一个类承受太多职责
2. 里氏代换原则(Liskov Substitution Principle)
里氏代换原则(Liskov Substitution Principle LSP)面向对象设计的基本原则之一。 里氏代换原则中说,任何基类可以出现的地方,子类一定可以出现。 LSP是继承复用的基石, 只有当衍生类可以替换掉基类,软件单位的功能不受到影响时,基类才能真正被复用,而衍 生类也能够在基类的基础上增加新的行为。里氏代换原则是对“开-闭”原则的补充。实现“开-闭”原则 的关键步骤就是抽象化。而基类与子类的继承关系就是抽象化的具体实现,所以里氏代换原则是对实现抽象化的具体步骤的规范。
所谓封装,是不改变原有的代码或安全的改变原有的代码,尽量不改变代码 凡是父类发现的地方可以用子类来替换,尽量使用多态,尽量依赖于父类,抽象类和接口
3. 依赖倒转原则(Dependence Inversion Principle)
这个是开闭原则的基础,具体内容:针对接口编程,依赖于抽象而不依赖于具体。
4. 接口隔离原则(Interface Segregation Principle)
这个原则的意思是:使用多个隔离的接口,比使用单个接口要好。还是一个降低类之间 的耦合度的意思,从这儿我们看出,其实设计模式就是一个软件的设计思想,从大型软件架构出发, 为了升级和维护方便。所以上文中多次出现:降低依赖,降低耦合。
接口最小原则
5. 迪米特法则(最少知道原则)(Demeter Principle)
为什么叫最少知道原则,就是说:一个实体应当尽量少的与其他实体之间发生相互作用,使得系统功能模块相对独立。
向外公布,开方越少越好,封装 继承:子类的替代父类的引用,实践子类
6. 单一职责原则(Single Responsibility Principle)
定义:不要存在多于一个导致类变更的原因。通俗的说,即一个类只负责一项职责。
Serializable接口
1. 什么是序列化
简单说就是为了保存在内存中的各种对象的状态(也就是实例变量,不是方法),并且可以把保存的对象状态再读出来。虽然你可以用你自己的各种各样的方法来保存object states,但是Java给你提供一种应该比你自己好的保存对象状态的机制,那就是序列化。
2. 什么情况下需要序列化
a、当你想把的内存中的对象状态保存到一个文件中或者数据库中时候; b、当你想用套接字在网络上传送对象的时候; b、当你想通过RMI传输对象的时候;
3、当对一个对象实现序列化时,究竟发生了什么?
在没有序列化前,每个保存在堆(Heap)中的对象都有相应的状态(state),即实例变量(instance ariable)
JDBC编程步骤
1、加载驱动程序: 2、获得数据库连接: 3、创建Statement\PreparedStatement对象。
BlockingQueue
阻塞队列,从阻塞这个词可以看出,在某些情况下对阻塞队列的访问可能会造成阻塞。被阻塞的情况主要有如下两种:
- 当队列满了的时候进行入队列操作
- 当队列空了的时候进行出队列操作 因此,当一个线程试图对一个已经满了的队列进行入队列操作时,它将会被阻塞,除非有另一个线程做了出队列操作;同样,当一个线程试图对一个空队列进行出队列操作时,它将会被阻塞,除非有另一个线程进行了入队列操作。
c3p0数据库连接池
在系统初始化的时候,将数据库连接作为对象存储在内存中,当用户需要访问数据库时,并非建立一个新的连接,而是从连接池中取出一个已建立的空闲连接对象。使用完毕后,用户也并非将连接关闭,而是将连接放回连接池中,以供下一个请求访问使用。而连接的建立、断开都由连接池自身来管理。同时,还可以通过设置连接池的参数来控制连接池中的初始连接数、连接的上下限数以及每个连接的最大使用次数、最大空闲时间等等。也可以通过其自身的管理机制来监视数据库连接的数量、使用情况等。
有关synchronized在父子类中的用法
构造方法每次都是构造出新的对象,不存在多个线程同时读写同一对象中的属性的问题,所以不需要同步 。 如果父类中的某个方法使用了 synchronized关键字,而子类中也覆盖了这个方法,默认情况下子类中的这个方法并不是同步的,必须显示的在子类的这个方法中加上 synchronized关键字才可。当然,也可以在子类中调用父类中相应的方法,这样虽然子类中的方法并不是同步的,但子类调用了父类中的同步方法,也就相当子类方法也同步了。
ThreadLocal
JDK 1.2的版本中就提供java.lang.ThreadLocal,ThreadLocal为解决多线程程序的并发问题提供了一种新的思路。使用这个工具类可以很简洁地编写出优美的多线程程序,ThreadLocal并不是一个Thread,而是Thread的局部变量。
java中的四舍五入
1、ROUND_UP:远离零方向舍入。向绝对值最大的方向舍入,只要舍弃位非0即进位。 2、 ROUND_DOWN:趋向零方向舍入。向绝对值最小的方向输入,所有的位都要舍弃,不存在进位情况。 3、 ROUND_CEILING:向正无穷方向舍入。向正最大方向靠拢。若是正数,舍入行为类似于ROUND_UP,若为负数,舍入行为类似于ROUND_DOWN。Math.round()方法就是使用的此模式。 4、 ROUND_FLOOR:向负无穷方向舍入。向负无穷方向靠拢。若是正数,舍入行为类似于ROUND_DOWN;若为负数,舍入行为类似于ROUND_UP。 5、 HALF_UP:最近数字舍入(5进)。这是我们最经典的四舍五入。 6、 HALF_DOWN:最近数字舍入(5舍)。在这里5是要舍弃的。 7、 HAIL_EVEN:银行家舍入法。
数据类型的转换
数据类型的转换,分为自动转换和强制转换。自动转换是程序在执行过程中 “ 悄然 ” 进行的转换,不需要用户提前声明,一般是从位数低的类型向位数高的类型转换;强制类型转换则必须在代码中声明,转换顺序不受限制。 自动数据类型转换 自动转换按从低到高的顺序转换。不同类型数据间的优先关系如下: 低 ———————————————> 高 byte ,short, char-> int -> long -> float -> double
强制数据类型转换
强制转换的格式是在需要转型的数据前加上 “( )” ,然后在括号内加入需要转化的数据类型。有的数据经过转型运算后,精度会丢失,而有的会更加精确。
float占4个字节为什么比long占8个字节大呢?
因为底层的实现方式不同。
浮点数的32位并不是简单直接表示大小,而是按照一定标准分配的。 第1位,符号位,即S 接下来8位,指数域,即E。 剩下23位,小数域,即M,取值范围为[1 ,2 ) 或[0 , 1) 然后按照公式: V=(-1)^s * M * 2^E 也就是说浮点数在内存中的32位不是简单地转换为十进制,而是通过公式来计算而来,通过这个公式虽然,只有4个字节,但浮点数最大值要比长整型的范围要大。
一个算法应该具有以下五个重要的特征
1、有穷性(Finiteness)
算法的有穷性是指算法必须能在执行有限个步骤之后终止;
2、确切性(Definiteness)
算法的每一步骤必须有确切的定义;
3、输入项(Input)
一个算法有0个或多个输入,以刻画运算对象的初始情况,所谓0个输入是指算法本身定出了初始条件;
4、输出项(Output)
一个算法有一个或多个输出,以反映对输入数据加工后的结果。没有输出的算法是毫无意义的;
5、可行性(Effectiveness)
算法中执行的任何计算步骤都是可以被分解为基本的可执行的操作步,即每个计算步都可以在有限时间内完成(也称之为有效性)。
分析基本数据类型的特点,最大值和最小值。
-
基本类型:int 二进制位数:32 包装类:java.lang.Integer 最小值:Integer.MIN_VALUE= -2147483648 (-2的31次方) 最大值:Integer.MAX_VALUE= 2147483647 (2的31次方-1)
-
基本类型:short 二进制位数:16 包装类:java.lang.Short 最小值:Short.MIN_VALUE=-32768 (-2的15此方) 最大值:Short.MAX_VALUE=32767 (2的15次方-1)
-
基本类型:long 二进制位数:64 包装类:java.lang.Long 最小值:Long.MIN_VALUE=-9223372036854775808 (-2的63次方) 最大值:Long.MAX_VALUE=9223372036854775807 (2的63次方-1)
-
基本类型:float 二进制位数:32 包装类:java.lang.Float 最小值:Float.MIN_VALUE=1.4E-45 (2的-149次方) 最大值:Float.MAX_VALUE=3.4028235E38 (2的128次方-1)
-
基本类型:double 二进制位数:64 包装类:java.lang.Double 最小值:Double.MIN_VALUE=4.9E-324 (2的-1074次方) 最大值:Double.MAX_VALUE=1.7976931348623157E308 (2的1024次方-1)
线程调度算法是平台独立的
线程调度分为协同式调度和抢占式调度,Java使用的是抢占式调度,也就是每个线程将由操作系统来分配执行时间,线程的切换不由线程本身来决定(协同式调度)。这就是平台独立的原因。
配置jdbc的url
在不同的操作系统中,出现乱码的问题
在新版本的(好像是5.4)mysql中,必须显示的指定useSSL参数 useSSL=false&useUnicode=true&characterEncoding=utf-8&serverTimezone=UTC
MyBatis/Ibatis中#和$的区别
-
”#”将传入的数据都当成一个字符串,会对自动传入的数据加一个双引号。如:order by #user_id#,如果传入的值是111,那么解析成sql时的值为order by “111”, 如果传入的值是id,则解析成的sql为order by “id”.
-
”$”将传入的数据直接显示生成在sql中。如:order by $user_id$,如果传入的值是111,那么解析成sql时的值为order by user_id, 如果传入的值是id,则解析成的sql为order by id.
ps:在使用mybatis中还遇到<![CDATA[]]>的用法,在该符号内的语句,将不会被当成字符串来处理,而是直接当成sql语句,比如要执行一个存储过程。
synchronized与volatile的区别
- synchronized很强大,既可以保证可见性,又可以保证原子性,而volatile不能保证原子性!
- ThreadLocal存放的值是线程内共享的,线程间互斥的,主要用于线程内共享一些数据,避免通过参数来传递
- volatile不需要加锁,比synchronized更轻量级,不会阻塞线程 从内存可见性角度讲,volatile读相当于加锁,volatile写相当于解锁 synchronized既能保证可见性,又能保证原子性,而volatile只能保证可见性,无法保证原子性
运行时数据区
运行时数据区包括:虚拟机栈区,堆区,方法区,本地方法栈,程序计数器 虚拟机栈区 :也就是我们常说的栈区,线程私有,存放基本类型,对象的引用和 returnAddress ,在编译期间完成分配。 堆区 , JAVA 堆,也称 GC 堆,所有线程共享,存放对象的实例和数组, JAVA 堆是垃圾收集器管理的主要区域。 方法区 :所有线程共享,存储已被虚拟机加载的类信息,常量,静态变量,即时编译器编译后的代码等数据。这个区域的内存回收目标主要是针对常量池的对象的回收和对类型的卸载。 程序计数器 :线程私有,每个线程都有自己独立的程序计数器,用来指示下一条指令的地址 jvm为每个新创建的线程都分配一个堆栈。堆栈以帧为单位保存线程的状态。jvm对堆栈只进行两种操
Java中数组的复制效率高的
System.arraycopy()源码。可以看到是native方法:native关键字说明其修饰的方法是一个原生态方法,方法对应的实现不是在当前文件,而是在用其他语言(如C和C++)实现的文件中。 可以将native方法比作Java程序同C程序的接口。
public class Test{
public static void main(String[] args){ //javac Test.java
System.out.println(args[0]+""+args[1]+""+args[2]);//java Test one two three
} //会打印onetwothree
}
URL(Uniform Resource Locator)
URL:统一资源定位符,能够对因特网的资源进行定位。 URL一般有四部分组成: <协议>://<主机>:<端口>/<路径> 现在最常用的<协议>为http协议。协议>路径>端口>主机>协议>
<主机>是指主机在因特网上的域名。主机号=ip地址+子网掩码 http协议的默认<端口>为80(可以省略)。 <路径>是指要活的的文件的路径 路径>端口>主机>