Java 学习笔记(一)

Java 学习笔记(一)


要点

  1. 任何时候你的整数表达式包含byte,short,int及字面量数字,在进行计算以前,所有表达式的类型被提升(promoted)到整型。
  2. Java上溯类型与绑定。
  3. System.in 和 System.out 是java中的标准输入输出流,一般情况下代表从控制台输入和输出到控制台
  4. 所有Spring Bean 默认都是单例。
  5. final类型的变量一定要初始化,因为final的变量不可更改。
  6. 浅复制:将一个对象复制后,基本数据类型的变量都会重新创建,而引用类型,指向的还是原对象所指向的。
  7. 集合类只能容纳对象句柄
    深复制:将一个对象复制后,不论是基本数据类型还有引用类型,都是重新创建的。简单来说,就是深复制进行了完全彻底的复制,而浅复制不彻底。
  8. comparable 与 comparator 的区别。
    Java 中的两种排序方式:
    Comparable 自然排序。(实体类实现)
    Comparator 是定制排序。(无法修改实体类时,直接在调用方创建)
  9. session与cookie的区别

设计模式

设计模式的六大原则

  1. 开闭原则(Open Close Principle)开闭原则就是说对扩展开放,对修改关闭。在程序需要进行拓展的时候,不能去修改原有的代码,实现一个热插拔的效果。所以一句话概括就是:为了使程序的扩展性好,易于维护和升级。想要达到这样的效果,我们需要使用接口和抽象类,后面的具体设计中我们会提到这点。
  2. 里氏代换原则(Liskov Substitution Principle)里氏代换原则(Liskov Substitution Principle LSP)面向对象设计的基本原则之一。 里氏代换原则中说,任何基类可以出现的地方,子类一定可以出现。 LSP是继承复用的基石,只有当衍生类可以替换掉基类,软件单位的功能不受到影响时,基类才能真正被复用,而衍生类也能够在基类的基础上增加新的行为。里氏代换原则是对“开-闭”原则的补充。实现“开-闭”原则的关键步骤就是抽象化。而基类与子类的继承关系就是抽象化的具体实现,所以里氏代换原则是对实现抽象化的具体步骤的规范。—— From Baidu 百科
  3. 依赖倒转原则(Dependence Inversion Principle)这个是开闭原则的基础,具体内容:真对接口编程,依赖于抽象而不依赖于具体。
  4. 接口隔离原则(Interface Segregation Principle)这个原则的意思是:使用多个隔离的接口,比使用单个接口要好。还是一个降低类之间的耦合度的意思,从这儿我们看出,其实设计模式就是一个软件的设计思想,从大型软件架构出发,为了升级和维护方便。所以上文中多次出现:降低依赖,降低耦合。
  5. 迪米特法则(最少知道原则)(Demeter Principle)为什么叫最少知道原则,就是说:一个实体应当尽量少的与其他实体之间发生相互作用,使得系统功能模块相对独立。
  6. 合成复用原则(Composite Reuse Principle)原则是尽量使用合成/聚合的方式,而不是使用继承。

内存回收

两个最基本的java回收算法:复制算法和标记清理算法
复制算法:两个区域A和B,初始对象在A,继续存活的对象被转移到B。此为新生代最常用的算法
标记清理:一块区域,标记可达对象(可达性分析),然后回收不可达对象,会出现碎片,那么引出
标记-整理算法:多了碎片整理,整理出更大的内存放更大的对象
两个概念:新生代和年老代
新生代:初始对象,生命周期短的
永久代:长时间存在的对象
整个java的垃圾回收是新生代和年老代的协作,这种叫做分代回收。
P.S:Serial New收集器是针对新生代的收集器,采用的是复制算法
Parallel New(并行)收集器,新生代采用复制算法,老年代采用标记整理
Parallel Scavenge(并行)收集器,针对新生代,采用复制收集算法
Serial Old(串行)收集器,新生代采用复制,老年代采用标记整理
Parallel Old(并行)收集器,针对老年代,标记整理
CMS收集器,基于标记清理
G1收集器:整体上是基于标记 整理 ,局部采用复制
综上:新生代基本采用复制算法,老年代采用标记整理算法。cms采用标记清理。


Java内存区域

运行时数据区

  1. 程序计数器
  2. Java虚拟机栈
  3. 本地方法栈
  4. Java堆
  5. 方法区
  6. 运行时常量池
  7. 直接内存(并非虚拟机运行时数据区)

四种引用

  • 强引用
    只要引用存在,垃圾回收器永远不会回收
    Object obj = new Object();
    //可直接通过obj取得对应的对象 如obj.equels(new Object());
    而这样 obj对象对后面new Object的一个强引用,只有当obj这个引用被释放之后,对象才会被释放掉,这也是我们经常所用到的编码形式。
  • 软引用
    非必须引用,内存溢出之前进行回收,可以通过以下代码实现
    Object obj = new Object();
    SoftReference sf = new SoftReference(obj);
    obj = null;
    sf.get();//有时候会返回null
    这时候sf是对obj的一个软引用,通过sf.get()方法可以取到这个对象,当然,当这个对象被标记为需要回收的对象时,则返回null;
    软引用主要用户实现类似缓存的功能,在内存足够的情况下直接通过软引用取值,无需从繁忙的真实来源查询数据,提升速度;当内存不足时,自动删除这部分缓存数据,从真正的来源查询这些数据。
  • 弱引用
    第二次垃圾回收时回收,可以通过如下代码实现
    Object obj = new Object();
    WeakReference wf = new WeakReference(obj);
    obj = null;
    wf.get();//有时候会返回null
    wf.isEnQueued();//返回是否被垃圾回收器标记为即将回收的垃圾
    弱引用是在第二次垃圾回收时回收,短时间内通过弱引用取对应的数据,可以取到,当执行过第二次垃圾回收时,将返回null。
    弱引用主要用于监控对象是否已经被垃圾回收器标记为即将回收的垃圾,可以通过弱引用的isEnQueued方法返回对象是否被垃圾回收器标记。
  • 虚引用
    垃圾回收时回收,无法通过引用取到对象值,可以通过如下代码实现
    Object obj = new Object();
    PhantomReference pf = new PhantomReference(obj);
    obj=null;
    pf.get();//永远返回null
    pf.isEnQueued();//返回是否从内存中已经删除
    虚引用是每次垃圾回收的时候都会被回收,通过虚引用的get方法永远获取到的数据为null,因此也被成为幽灵引用。
    虚引用主要用于检测对象是否已经从内存中删除。

⑴强引用(StrongReference)
强引用是使用最普遍的引用。如果一个对象具有强引用,那垃圾回收器绝不会回收它。当内存空间不足,Java虚拟机宁愿抛出OutOfMemoryError错误,使程序异常终止,也不会靠随意回收具有强引用的对象来解决内存不足的问题。 ps:强引用其实也就是我们平时A a = new A()这个意思。

⑵软引用(SoftReference)
如果一个对象只具有软引用,则内存空间足够,垃圾回收器就不会回收它;如果内存空间不足了,就会回收这些对象的内存。只要垃圾回收器没有回收它,该对象就可以被程序使用。软引用可用来实现内存敏感的高速缓存(下文给出示例)。
软引用可以和一个引用队列(ReferenceQueue)联合使用,如果软引用所引用的对象被垃圾回收器回收,Java虚拟机就会把这个软引用加入到与之关联的引用队列中。

⑶弱引用(WeakReference)
弱引用与软引用的区别在于:只具有弱引用的对象拥有更短暂的生命周期。在垃圾回收器线程扫描它所管辖的内存区域的过程中,一旦发现了只具有弱引用的对象,不管当前内存空间足够与否,都会回收它的内存。不过,由于垃圾回收器是一个优先级很低的线程,因此不一定会很快发现那些只具有弱引用的对象。
弱引用可以和一个引用队列(ReferenceQueue)联合使用,如果弱引用所引用的对象被垃圾回收,Java虚拟机就会把这个弱引用加入到与之关联的引用队列中。

⑷虚引用(PhantomReference)
“虚引用”顾名思义,就是形同虚设,与其他几种引用都不同,虚引用并不会决定对象的生命周期。如果一个对象仅持有虚引用,那么它就和没有任何引用一样,在任何时候都可能被垃圾回收器回收。
虚引用主要用来跟踪对象被垃圾回收器回收的活动。虚引用与软引用和弱引用的一个区别在于:虚引用必须和引用队列 (ReferenceQueue)联合使用。当垃圾回收器准备回收一个对象时,如果发现它还有虚引用,就会在回收对象的内存之前,把这个虚引用加入到与之 关联的引用队列中。

ReferenceQueue queue = new ReferenceQueue ();

PhantomReference pr = new PhantomReference (object, queue);

程序可以通过判断引用队列中是否已经加入了虚引用,来了解被引用的对象是否将要被垃圾回收。如果程序发现某个虚引用已经被加入到引用队列,那么就可以在所引用的对象的内存被回收之前采取必要的行动。

判断对象已死:

  1. 引用计数算法
  2. 可达性分析算法

垃圾收集:

  1. 标记-清除算法
  2. 复制算法
  3. 标记-整理算法
  4. 分代收集算法

垃圾收集器:

串行:
  1. Serial收集器(最基本、发展历史最久)简单、高效、无线程交互开销
  2. Serial Old收集器(Serial的老年代版本)
    主要意义:给Client模式下的虚拟机使用
并发:

1.ParNew收集器(即Serial收集器的多线程版本)
2.Parallel Scavenge收集器“吞吐量优先收集器”

无法与CMS收集器配合
吞吐量 = 运行用户代码时间/(运行用户代码时间+垃圾收集时间)
3. Parallel Old收集器(Parallel Scavenge收集器的老年代版本)

使用多线程和“标记-整理”算法
4. CMS(Concurrent Mark Sweep)收集器

基于“标记-清除算法”
目标:获取最短回收停顿时间
运作过程:
I. 初始标记(Stop the world)
II. 并发标记
III. 重新标记(Stop the world,比初始标记长)
IV. 并发清除
缺点:
I. 对CPU资源非常敏感
II. 无法处理浮动垃圾
III. 由于使用“标记-清除”算法导致大量空间碎片
5. G1(Garbage-First)收集器:面向服务端应用

特点:
I. 并行与并发
II. 分代收集
III. 空间整合
整体上看是基于“标记-整理”,局部(两个region之间)是基于“复制”算法
IV. 可预测的停顿
步骤(不记维护Remembered Set操作):
I. 初始标记
II. 并发标记
III. 最终标记
IV. 筛选回收


垃圾回收

  • 新生代=Eden区+2个survival区,比值8:1:1
  • 对象优先在Eden分配,空间不足会发生minor GC

字节码文件

  • 文件头4个字节称为“魔数”,值为CAFEBAEBE
  • 紧接着“魔数”的4个字节是Class文件的版本号,第5、6个字节是次版本号,第7、8个是主版本号
  • 主版本号后面接着的是常量池入口:

入口处为一个u2类型的数据,代表常量池容量计数值(从1开始)

  • 常量池结束后紧接着的两个字节代表访问标志,用于识别一些类或者接口层次的访问信息

多线程

  • volatile关键字
  1. 使得用volatile关键字的变量修改后的数值会写回JVM的主内存(但仍然非线程安全)
  2. 禁止指令重排序优化

Spring

依赖注入的三种方式

1. 接口注入
2. Setter方法注入
3. 构造方法注入


计算机网络

ISO-OSI参考模型

ISO-OSI
应用层HTTP、SMTP、MIME、FTP、DNS、TELNET
表示层
会话层
传输层TCP、UDP
网络层IP、ICMP、ARP
数据链路层
物理层

HTTP、HTTPS

  • http是无状态协议,不会保存web浏览器进程的信息(如不会因为浏览器在短短几秒钟内访问2次就不接受第二次服务请求)
  • HTTP1.0使用非持续连接(短连接),HTTP2.0使用持续连接(长连接)
  • 持续连接(长连接)两种工作方式:非流水线方式与流水线方式
  • https相当于http+ssl

传输层(TCP、UDP)

数据链路层


数据库

主键和唯一索引的区别

主键是一种约束,唯一索引是一种索引,两者在本质上是不同的。
主键创建后一定包含一个唯一性索引,唯一性索引并不一定就是主键。
唯一性索引列允许空值,而主键列不允许为空值。
主键列在创建时,已经默认为空值 + 唯一索引了。
主键可以被其他表引用为外键,而唯一索引不能。
一个表最多只能创建一个主键,但可以创建多个唯一索引。
主键更适合那些不容易更改的唯一标识,如自动递增列、身份证号等。
在 RBO 模式下,主键的执行计划优先级要高于唯一索引。 两者可以提高查询的速度。

事务的概念

事务的概念来自于两个独立的需求:并发数据库访问,系统错误恢复。

一个事务是可以被看作一个单元的一系列SQL语句的集合。

事务的特性(ACID)

  • A, atomacity 原子性 事务必须是原子工作单元;对于其数据修改,要么全都执行,要么全都不执行。通常,与某个事务关联的操作具有共同的目标,并且是相互依赖的。如果系统只执行这些操作的一个子集,则可能会破坏事务的总体目标。原子性消除了系统处理操作子集的可能性。
  • C, consistency 一致性
    事务将数据库从一种一致状态转变为下一种一致状态。也就是说,事务在完成时,必须使所有的数据都保持一致状态(各种 constraint 不被破坏)。
  • I, isolation 隔离性 由并发事务所作的修改必须与任何其它并发事务所作的修改隔离。事务查看数据时数据所处的状态,要么是另一并发事务修改它之前的状态,要么是另一事务修改它之后的状态,事务不会查看中间状态的数据。换句话说,一个事务的影响在该事务提交前对其他事务都不可见。
  • D, durability 持久性
    事务完成之后,它对于系统的影响是永久性的。该修改即使出现致命的系统故障也将一直保持。

悲观锁

在关系数据库管理系统里,悲观并发控制(又名“悲观锁”,Pessimistic Concurrency Control,缩写“PCC”)是一种并发控制的方法。它可以阻止一个事务以影响其他用户的方式来修改数据。如果一个事务执行的操作都某行数据应用了锁,那只有当这个事务把锁释放,其他事务才能够执行与该锁冲突的操作。
悲观并发控制主要用于数据争用激烈的环境,以及发生并发冲突时使用锁保护数据的成本要低于回滚事务的成本的环境中。

乐观锁

在关系数据库管理系统里,乐观并发控制(又名“乐观锁”,Optimistic Concurrency Control,缩写“OCC”)是一种并发控制的方法。它假设多用户并发的事务在处理时不会彼此互相影响,各事务能够在不产生锁的情况下处理各自影响的那部分数据。在提交数据更新之前,每个事务会先检查在该事务读取数据后,有没有其他事务又修改了该数据。如果其他事务有更新的话,正在提交的事务会进行回滚。乐观事务控制最早是由孔祥重(H.T.Kung)教授提出。

常见的mysql数据库优化操作

  1. Index索引
  1. 少用SELECT *
    可能有的人查询数据库时,遇到要查询的都会select,这是不恰当的行为。我们应该取我们要用的数据,而不是全取,因为当我们select时,会增加web服务器的负担,增加网络传输的负载,查询速度自然就下降 。
  2. 开启查询缓存
    大多数的MySQL服务器都开启了查询缓存。这是提高性最有效的方法之一,而且这是被MySQL的数据库引擎处理的。当有很多相同的查询被执行了多次的时候,这些查询结果会被放到一个缓存中,这样,后续的相同的查询就不用操作表而直接访问缓存结果了。
  3. 使用NOT NULL
    很多表都包含可为NULL(空值)的列,即使应用程序并不需要保存 NULL 也是如此 ,这是因为可为NULL是列的默认属性。通常情况下最好指定列为 NOT NULL,除非真的需要存储NULL值。如果查询中包含可为NULL的列,对 MySQL 来说更难优化 ,因为可为 NULL 的列使 得索引、索引统计和值比较都更复杂 。可为NULL 的列会使用更多的存储空间 ,在MySQL里也需要特殊处理 。当可为NULL 的列被索引肘,每个索引记录需要一个额外的字节,在 MyISAM 里甚至还可能导致固定大小的索引 (例如只有一个整数列的索引) 变成可变大小的索引。
      通常把可为 NULL 的列改为 NOT NULL 带来的性能提升比较小 ,所以 (调优时) 没有 必要首先在现有schema中查找井修改掉这种情况 ,除非确定这会导致问题。但是, 如果计划在列上建索引 ,就应该尽量避免设计成可为 NULL 的列。当然也有例外 ,例如值得一提的是,InnoDB 使用单独的位 (bit ) 存储 NULL 值 ,所 以对于稀疏数据由有很好的空间效率 。但这一点不适用于MyISAM 。
  4. 避免在 where 子句中使用 or 来连接
    如果一个字段有索引,一个字段没有索引,将导致引擎放弃使用索引而进行全表扫描,如:
    select id from t where num=10 or Name = ‘admin’
    可以这样查询:
    select id from t where num = 10
    union all
    select id from t where Name = ‘admin’
  5. 多使用varchar/nvarchar
    使用varchar/nvarchar代替 char/nchar ,因为首先变长字段存储空间小,可以节省存储空间,其次对于查询来说,在一个相对较小的字段内搜索效率显然要高些。
  6. 避免大数据量返回
    这里要考虑使用limit,来限制返回的数据量,如果每次返回大量自己不需要的数据,也会降低查询速度。
  7. where子句优化
    where 子句中使用参数,会导致全表扫描,因为SQL只有在运行时才会解析局部变量,但优化程序不能将访问计划的选择推迟到运行时;它必须在编译时进行选择。然 而,如果在编译时建立访问计划,变量的值还是未知的,因而无法作为索引选择的输入项。
    应尽量避免在 where 子句中对字段进行表达式操作,避免在where子句中对字段进行函数操作这将导致引擎放弃使用索引而进行全表扫描。不要在 where 子句中的“=”左边进行函数、算术运算或其他表达式运算,否则系统将可能无法正确使用索引。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值