chessy 提高篇系列 阅读笔记 java提高篇(一)—–理解java的三大特性之封装 java提高篇(二)—–理解java的三大特性之继承 java提高篇(三)—–理解java的三大特性之多态 java提高篇(四)—java的四舍五入 java提高篇(五)—–抽象类与接口 java提高篇(六)—–使用序列化实现对象的拷贝 java提高篇(七)—–关键字static java提高篇(八)—–详解内部类 java提高篇(九)—–实现多重继承 java提高篇(十)—–详解匿名内部类 java提高篇(十一)—–强制类型转换 java提高篇(十二)—–代码块 java提高篇(十三)—–equals()方法总结 java提高篇(十四)—–字符串 java提高篇(十五)—–关键字final java提高篇(十六)—–异常(一) java提高篇(十七)—–异常(二)   java提高篇(十八)—–数组之一:认识JAVA数组 java提高篇(十九)—–数组之二 java提高篇(二十)—–集合大家族 java提高

封装的好处,

汇聚属性和方法

减少修改对 其他处的影响

控制get和set方法。

java提高篇(二)—–理解java的三大特性之继承

继承的好处

复用代码

所以继承的第一步是观察,抽象出共有部分,作为父类。

构造器只能调用,不能继承 super

在构造子类的时候,即使你不手动调用,编译器会自动调用一个无参的父类的构造器。

而且调用父类的构造器必须是 子类构造方法的 第一行代码。

protected的属性,对其他类是不可见,但对于继承者可见。

向上转型:将子类转型成父类

慎用继承,判断标准在  子类 向上转型 是不是必要的。

继承的缺陷:继承是一种强耦合关系。

java提高篇(三)—–理解java的三大特性之多态

多态就是 引用变量 到底 绑定到哪个 类上,到程序运行时才能确定,所以执行哪个方法 也就 到时候才能确定, 这样就实现了 一次调用 会根据情况 执行不同方法, 这就是多态。继承和封装是多态的基础。

向上转型后 只能调用 父类有的方法。

多态 一定要是 父类的引用 指向不同子类。

JNC的例子很不错。我没有看清,fun1(String) 的参数不同,所以重载,而不是重写。所以要调用父类的方法。

调用哪个方法,关键看指向子类,还是指向父类。 如果指向的是子类,那么调用一个方法,如果子类没有,那么就用父类的,如果子类重写了,就用子类的。 可以看出是子类的方法优先。

向上转型,会丢失 子类多出来的方法。

多态实现有两种方法, 重写和重载。 重载是编译时多态,算是静态的; 重写是动态的,依赖动态绑定。

多态的三个条件:继承,重写,向上转型

多态一定是父类有的方法,在子类重写了。

基于继承实现多态: 当子类重写父类的方法被调用时,继承链最末端的方法会被调用

基于接口的多态:多个类实现了一个接口。

被引用对象类型,决定了调用谁的方法,但这个方法必须在父类中定义过,子类中 重写了。

该优先级为:this.show(O)、super.show(O)、this.show((super)O)、super.show((super)O)。

java提高篇(四)—java的四舍五入

round()是向正无穷方向舍入。

round(13.5)      == 14

round(-13.5)     == -13

java提高篇(五)—–抽象类与接口

抽象类一定是用来继承的。

jdk1.8,接口中可以有静态方法,而且要实现该方法。  

抽象类是从下到上抽象出来的,接口是从上到下设计出来的。

java提高篇(六)—–使用序列化实现对象的拷贝

public class CloneUtils {
    @SuppressWarnings("unchecked")
    public static <T extends Serializable> T clone(T obj){
        T cloneObj = null;
        try {
            //写入字节流
            ByteArrayOutputStream out = new ByteArrayOutputStream();
            ObjectOutputStream obs = new ObjectOutputStream(out);
            obs.writeObject(obj);
            obs.close();
            
            //分配内存,写入原始对象,生成新对象
            ByteArrayInputStream ios = new ByteArrayInputStream(out.toByteArray());
            ObjectInputStream ois = new ObjectInputStream(ios);
            //返回生成的新对象
            cloneObj = (T) ois.readObject();
            ois.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return cloneObj;
    }
}

java提高篇(七)—–关键字static

static修饰的代码块是 静态代码块, JVM加载类的时候,就会执行这些代码,只执行一次。

static方法必须实现,不能是抽象方法。因为静态方法是可以直接调用的。静态方法就像C语言中的函数。

java提高篇(八)—–详解内部类

内部类的声明  OuterClass.InnerClass

实例化内部类,必须先实例化外部类,用外部类的实例对象.new (静态内部类除外)

匿名内部类,这个类首先要存在 ,可以是接口或者抽象类。

如果 在匿名内部类中 要使用 形参,这个形参必须是 final修饰的。

静态内部类 就是 一个普通的类,和外围的类没什么关系,只是 写到 一个外围类中了。

java提高篇(九)—–实现多重继承

内部类可以间接地 继承多个类。

或者实现多个接口。

java提高篇(十)—–详解匿名内部类

匿名内部类必须继承一个类 或者 实现一个接口。

构造代码块 能够实现构造器一样的作用,对于匿名内部类这种没有构造器的 类, 可以使用 构造快来 构造类。

在构造类时 执行顺序为 变量声明》构造快》构造函数

java提高篇(十一)—–强制类型转换

子类转父类 不存在转换,  父类转子类 是需要 强制转换的。

恢复真身

强制转换 在编译时 只会检查 是否有 继承关系,有则通过编译, 只有到运行时,才能发现ClassCastException

java提高篇(十二)—–代码块

静态代码块 可以 对静态变量 初始化。

同步代码块 synchronized  同一时间,只能有一个线程进入到 该代码块中。

构造代码块 可以初始化 实例变量。 编译器会将 构造代码块 添加到 每一个构造函数的 最前面。

构造代码块可以 简化 多个 构造函数。 但是构造块如果写的很分散也是很令人头疼的。

java提高篇(十三)—–equals()方法总结

float类型: 使用Float.foatToIntBits转换成int类型,然后使用==。  
double类型: 使用Double.doubleToLongBit转换成long类型,然后使用==。

在重写equals时 使用getClass,而不是 instanceof

java提高篇(十四)—–字符串

String

StringBuffer  jdk1.0就加入,线程安全, 使用synchronized 修饰 append方法实现。

StringBuilder  jdk1.5加入, 线程不安全, 速度更快。

java提高篇(十五)—–关键字final

静态方法也可以重写。 

java提高篇(十六)—–异常(一)

java提高篇(十七)—–异常(二)

 cause,可以保存原来的异常信息。 因为异常会在传递中,改变成别的异常。

 

java提高篇(十八)—–数组之一:认识JAVA数组

数组也是对象 [I

[代表维度, 几个就是几维

JVM对数组做了特殊处理

数组是在JVM中构造成对象的。

java提高篇(十九)—–数组之二

数组性能最高

使用Arrays.asList将 数组转化为List之后,是ArrayList类型的,这是一个Arrays的内部类,不是 java.util.ArrayList, 没有add方法。

java提高篇(二十)—–集合大家族

java提高篇(二一)—–ArrayList

ArrayList 内部就是 Object数组

 new Object[initialCapacity]

ArrayList是不同步的,如果需要同步,可以

List list = Collections.synchronizedList(new ArrayList(…)); 可以同步, 其中使用的是 synchronized对 对象加锁。

如果在指定index位置上加入元素 ,需要将index+1 到末尾的元素 全都向后移动一格,当数组很长时,很费时间 ,不如用LinkedList

每次扩容为原来的1.5倍

java提高篇(二二)—LinkedList

当列表很长,且需要经常 随机 增删时,用LinkedList

是一个 双向队列

没有考虑线程安全

java提高篇(二三)—–HashMap

java提高篇(二四)—–HashSet

HashSet是用HashMap来实现的, 是一个value全都是 PRESENT = new Object() 的 HashMap。

java提高篇(二五)—–HashTable

HashTable是线程安全的,put等方法用 synchronized修饰

Java提高篇(二六)——hashCode

hashCode是在数组中 确定位置的, equals才是 相等的依据。

hash的作用是 寻域

Java提高篇(二七)—–TreeMap

红黑树 - 平衡查找二叉树

在查找二叉树的基础上,为了实现平衡,又做了大量的工作。

Java提高篇(二八)—–TreeSet

TreeSet 是用 TreeMap实现的, value是一个固定的值PRESENT

详解java定时任务

Timer类是单线程的,如果任务执行过慢,会导致别的任务堆积。

TimeThread继承Thread

TimerTask实现了Runnable方法

java.util.Timer分析源码了解原理

简单说,Timer是一个单线程, 有一个任务队列,是用最小堆实现的,每次任务来了,都添加到队列中,队列可以自己扩容。

每个任务记录自己的状态,自己的执行实现,是否循环,是否需要延迟,以及下次执行时间。 队列中任务是按照下次执行时间 的 顺序排列的。

Timer把把下次执行时间 和 当前时间进行比较,如果时间到了,就执行方法。

java提高篇(二九)—–Vector

Vector用 synchronized实现 线程安全。不过已经是古董了。JDK1.0加入。

java提高篇(三十)—–Iterator

迭代器的出现,是为了使得遍历方法统一。不然必须知道内部结构,才能够知道怎么遍历。

Iterator模式

每一种容器,根据自己的数据结构特点,构造自己的Iterator类,对客户方法统一, next,  hasNext, remove

Java提高篇(三一)—–Stack

Stack的实现是利用Vector, 用Vector实现Stack很容易,push就在数组上自增,pop就递减。

有一个面试题,如何用两个栈 实现 队列的操作

用两个栈实现一个队列——我作为面试官的小结

Java提高篇(三二)—–List总结

文中有一张图 说 LinkedList是线程安全的, 这个应该是错的。

Vector是线程安全的, 它的方法上有 synchronized 。

Java提高篇(三三)—–Map总结

Map的映射就是用空间 换区 时间, 非常值得。

Map中 resize 是很耗费开销的。 因为要 全部重新hash一次, 如果本身size很大的话,就更明显了。

负载因子 和 调整容量有关

负载因子是空间 和 时间的 折中。

Java提高篇(三四)—–fail-fast机制

fail-fast是在操作迭代器时 产生的。多出现于多线程中。

一个线程在迭代,另一个线程在修改,就会报错了。

Java提高篇(三五)—–Java集合细节(一):请为集合指定初始容量

对于已知的情景,请为容器指定初始容量,因为扩容是很耗时的。

Java提高篇(三六)—–Java集合细节(二):asList的缺陷

避免使用基本数据类型数组 转化为 列表,这样 会把 数组本身当做元素 转化成列表的,而不是 数组中的元素 ,修改的方法就是 使用 如Integer这样的对象。

asList生成的列表不可操作。因为返回的ArrayList 不是 java.util.ArrayList,  只是名字相同而已,这个ArrayList是 java.util.Arrays的内部类。  这真的是个 假的 List。没有add方法。

Java提高配(三七)—–Java集合细节(三):subList的缺陷

subList的所有操作,都会作用在原列表上。不是一个新的列表。

生成子列表后,不要去操作源列表了。  这个有点别扭。

Java提高篇(三八)—–Java集合细节(四):保持compareTo和equals同步

需要保持 compareTo  和 equals 方法 一致。