一、面向对象设计方式:
万物皆对象
程序是对象的集合,通过发送消息来彼此调用对方
每个对象都拥有其类型
某一特定类型的所有对象可接受同样的消息
你可以通过创建包含现有对象集合的包的方式来创建新类型的对象
继承is-a is-like-a 组合has-a
代码的复用: 继承 重写方法 父类变量指向子类实例 子类实例转换为父类实例
集合:list 列表 存储序列 map 关联数组 建立对象之间的关系 set存储一类对象
重写对象的equals方法时必须对hashcode方法进行重写,set存放对象时先对hashcode进行判断 equals判断时可能为空的对象放到后边
Java其他的特点 垃圾处理 异常处理
二、引用 基本数据类型 作用域
类中内容解析 成员 方法(名字、参数、返回值、方法体)名字和参数确定方法唯一性 如何调用方法—对象.方法名 return表示已经执行完成,离开此方法 此方法返回什么值 方法的结束 return 异常
命名空间区别类名相同的类import导入 static关键字修饰的是类属性或类方法能直接通过类名调用 最大的用法就是不创建对象时调用它
代码风格 包名小写 (驼峰规则)类名首字母大写 方法和变量首字母小写后面每个单词首字母大写
注释编写 帮助文件生成 用/** */括起来的是显示内容,可嵌入html代码
三、= == !=可操作所有对象 + +=可操作String类型
别名对象 把一个变量指向的对象赋给另一个变量 有一个改变时另一个也会改变
运算符
正则 -?可能为负或为正 \转义 \d数字 \D非数字 \w单词 \W非单词 x+一次或多次
x?一次或一次都没有 x*零次或多次 x{n}n次 x{n,m}至少n次至多m次
Pattern匹配的正则,Match去比较 正则中两个常用类
自增自减 Pattern Matcher
比较 ==比较的是地址 equals比较的是内容
短路 &&如果前面的false后边不在运行后边内容
||前面是true不在运行后边内容
位运算 &与运算 |或运算 ^异或运算(若不同结果是1) ~非运算 <<左移 <<<无符号左移 boolean不能进行算术运算可进行&^|位运算和条件运算 char int等不可进行条件运算float和double不能进行条件运算和位运算
三目运算
类型转换 基本数据类型 类
科学技术4e-4是4x10-4
三种循环 while do..while for while和do。While的区别 do。。while至少执行一次 for中可以定义多个变量,类型必须一致
break 中断当前循环(最内层)若想中断所有循环添加标签 return跳出循环的同时中断方法
continue 跳出当前循环 进入下一次循环 带标签的continue跳到标签位置继续执行
swith。。case swith()中的内容只能是能自动转换成int型的数据即byte short char int类型
如果符合条件的case后没有break则继续执行 直到遇见break停止
Math.Random()产生随机数范围是[0.0,1)
四、构造方法 重写 默认不写的是无参构造器若写有参的会把无参的覆盖 这时需要把默认的无参构造方法写出来
区分重写方法 参数类型和顺序上区分
重载过程中基本类型的转换问题大à小强制转 小à大自动转换
this调用方法的那个对象 this()如果在构造方法第一行(只能在第一行) 则调用别的构造方法
static方法深入 不含有this的方法 静态方法不可调用非静态反过来 可以 相当于全局
垃圾回收自动回收也可手动回收 手动回收不一定执行 垃圾回收只于内存有关
成员的初始化 基本数据类型如果不初始化就会有默认值(char初始值为0打印时为 ) 类的不初始化默认为null
类初始化时:类在加载时,先初始化类中变量(先静态再动态,只在必要时才创建,静态变量只在第一次实例化时执行一次,构造方法的this或super后执行动态变量的初始化)再执行构造方法
这地方谨记在普通成员变量在构造器中的this或super关键字后初始化
再有继承关系时 类加载时先初始化类中静态变量 然后父类构造方法(构建父类实例 顺序和类初始化时一样在this之后初始化父类非静态变量)然后本类的构造方法实例化类(super之后初始化子类非静态变量)
数组初始化 java中数组长度不可修改 从0开始最大索引length-1 数组中可以放置对象
五、包名(域名倒过来) 如果导包冲突时 就在new时加上具体的包名
访问权限 public protected private 和默认
每个单元只能有一个public类(也可一个都没有) 且文件名和public类名相同
重点:访问权限是给客户端程序员定制的规则 同时也简化了他们对类的理解
复用类 组合和继承
Java三大特性 继承、封装、多态
继承 继承父类中的参数和方法(public)
构造器第一行是super则调用父类相应的构造器(this调用自身的构造器)super和this只可用在构造器第一行
继承和组合的选择 has-a组合(一般用private) is-a继承(需要向上转型时选择继承)
继承时判断调用子类还是父类的方法要看变量的具体指向(不看变量类型) 指向谁就调用谁的访法
final关键字,修饰类方法变量时表示是最终的不可变的 final修饰的变量必须在定义处或构造器中实例化 修饰类表示不可继承不可改
七、多态 用方法的动态绑定来实现 父类定义一个变量指向其子类的实例 调用时调用的是子类中的方法也就是内存中指向的那个实例的方法
抽象方法 只有方法声明没有方法体 抽象类不能被实例化
避免在构造器中调用其它方法(如果调用子类方法,此时只能有默认初始值,不符要求)
用继承表达行为上的差异 用组合表达状态上的变化
八、接口与内部类
接口 实现多继承 原因1、可以有多个向上转型基类(核心--为了能够向上转型为不止一个基类型)2、防止创建该类对象
类中可以定义接口 接口中也可定义接口(接口中的成员全是public修饰)
内部类 类中的内部类可以隐藏实现 只给用户一个基类或接口的引用
内部类有它特定的作用范围 在语句块外边调用内部类就会失去效果
匿名内部类调用外部对象 该对象必须是final型的 对匿名内部类而言 他没有构造器 实例初始化的效果就是构造器 不能重载 故只有一个
内部类自动拥有对其外围类所有成员的访问权(反过来有限制)
嵌套类(静态内部类) 可包含static元素和嵌套类 而普通内部类不可以如果不是嵌套类 static只可以用在最外层的类中
嵌套类可放在接口中 可以嵌套进类中编写本类的测试代码
获取内部类实例 p.new C(); p是外部类的实例
调用内部类需要一个外部类的实例
内部类的继承有特殊的语法 构造方法中 old.super(); 内部类不会被重载 它是独立的
局部内部类和匿名内部类的区别是局部内部类可拥有构造器,当需要多个对象时就用局部内部类
内部类的作用 可以实现多继承(外部类继承一个,内部类继承一个,调用方法获取内部类实例) 内部类是独立的 可以做自己的动作 灵活性好
★子类继承或实现父类或接口重写方法时 方法的修饰符范围不能小于父类
回调 一个类全部都是封闭的,只提供一个对外的能产生一个内部类的实例的方法,这个内部类实现了一个接口并且有一个方法能访问外部类的方法,调用时可把这个方法当做钩子调用外部类的私有方法
回调可以理解为有一个问题自己解决不了,但是别人能解决,这时他去询问别人,当别人解决掉这个问题后再把结果给他
九、异常与错误
异常作为一个对象 可以手动添加或定义 异常就是用名称来定义发生的问题(就是在程序不能正确处理的时候,启用别的处理方式)把正常代码与处理错误的代码分开执行
try…catch 捕获处理异常 后跟finally表示无论是否异常都要执行(把除内存之外的资源恢复到原始状态)一个catch只能捕捉一个异常
throw抛出一个异常
throws抛出异常给下一级 在方法后边
异常链 捕获一个异常然后抛出一个异常 并把原始信息保存下来 没参数cause构造函数不含参数cause的异常 调用initCause方法(把普通异常转化为运行异常是就是用cause的构造方法)
运行时异常(RuntimeException()的子类)在编码中唯一可以忽略的异常(其他的编译器强制实施)
方法重载时子类方法继承父类方法的异常
子类构造器中异常说明必须包含基类构造器的异常说明(子类只能继续抛出父类抛得异常 如果想捕获就与super关键字用在第一行冲突)
继承时子类方法中异常不多于父类()子类方法中的异常可不写(也可写父类异常的子类) 调用方法时捕获父类异常
?构造器中的异常 若打开一个程序 打开时抛出异常 则执行关闭此程序(不在finally中定义下面的程序还将继续使用初始化的对象,如需在后边关闭 设置一个表示初始化是否成功的标记)
异常匹配:如果最近的异常能正确匹配 程序就不在继续往下寻找
用RuntimeException来包装“被检查的异常”
十、RTTI(run-time type identification)在运行期间识别一个对象类型
当你只有一个指向对象的基类的引用时 找到确切类型
RTTI形式1、直接转,2、Class类中的方法(getSuperClass()等等) 3、instenceof
三种类初始化 直接new Class.forName() Gc.class;
Class.forName(“Gc”);找不到?(需要加上包名)
动态instanceof 用isinstance()方法 前面跟类后边跟测试对象
Instance(属于 子类也属于父类类型)和equals(等于 子类和父类分开)
newInstance()调用的是无参构造方法
RTTI编译期打开和检查.class文件 反射在运行期执行
反射时调用方法中传递参数时 需要的对象是它反射的实例对象
数组与容器
区别:效率(数组比ArrayList高) 类型(数组里面是特定类型) 持有基本类型能力(数组能保存基本数据类型)
数组
数组定义初始化 三种赋值方式(整体赋值,遍历赋值,一个数组赋给另一个)
Arrays类中提供管理数组的静态方法
数组比较 相等是基于内容,内容一样数组就相等
填充数组
数组元素的比较(实现comparable接口 重写compareTo方法 该类型的数组排序时调用compareTo方法来判断先后顺序) 如果想自定义排序方式实现Comparator
数组查找 必须先排序再查找
容器
容器可以直接打印
容器可以存储任何对象(基本类型除外 他们不是真正的对象不是Object的子类 也就是在取数据时不能转换成基本类型)
迭代器 Iterator
产生无意识的递归调用时 用super关键字解决
有数组创造list 再有list创造set map
ArrayList插入移除速度慢 快速访问速度快 LinkedList正好相反
Set:HashSet(为快速查找设计 无序) TreeSet(按比较元素进行排序comparable) LinkedHashSet(查找快 按插入顺序进行排序)HashSet性能好 遍历时LinkedHashSet比较好
Map:HashMap(性能好无序查询快速)LinkedHashMap(链表维持内部顺序就是原来插入顺序 访问时被访问的元素会自动排到后边)TreeMap(按比较进行排序comparable)
Map中HashMap最好
如果要使用自己的类作为map中的键必须重写equals(五个特性)和hashcode方法
用hashcode的作用在于查询速度
List中若想插入另一个遍历的list的数据时遍历用ListIterator
在操作数组转化的list或用sublist截取list时 应new一个新的list 防止出现异常
hashMap的键和HashSet中的元素是按hashcode排列 存放的如果是对象的话从写对应类的equals和hashCode方法
和hash相关的都是为了快速查询而来的 linked是遍历最快
把容器设置为只读或者线程同步都有特殊的方法
并发容器
十二
inputstream和outputStream中的in和out都是相对于内存来说的 从文件进入内存为in 从内存进入文件为out
IO重点 编码解码 需要指定编码用InputStreamRead(inputstream,ecoding) 封装 read()返回的是读取的字节的int值 read(byte[]bytes)返回的是读取的字节数
String.getBytes()是编码
File文件类
输入InputStream Read 都有read()方法 输入流的父类
输出OutputStream write 都有write()方法 输出流的父类
对文件读写时 记得关闭打开的流
FilterInputStream的子类有:BufferedInputStream(写入缓存)DataInputStream(把数据类型写入输入流) FilterOutputStream子类中有个PrintStream(产生格式化输出)
打印流只有PrintStream和PrintWriter
新IO ,nio FileChannel 通道 可改变数据流 ByteBuffer 字节缓存 存取字符时需要转码(Charset)
写入文件时 最后一定要先flush()在关闭
ByteBuffer有单独保存基本数据类型的方法
字节数组写到文件 先用ByteBuffer.wrap()包装起来 再用getChannel在inputStream中打开一个通道 然后把ByteBuffer保存到FileChannel中
CharBuffer和IntBuffer等都是ByteBuffer上的一个视图 和FileChannel交互的是ByteBuffer
ByteBuffer中包含参数的get或put方法不会引起position的改变
MappedByteBuffer大文件映射 可对大文件局部操作 写时用RandomAccessFile
文件加锁 只能在在通道上加锁 防止输出乱码 在输出时再转换类型
压缩 Gzip zip 输入输出直接封装成zip(gzip)inputStream zip(gzip)outputstream即可 不局限于压缩文件也可压缩网络数据
对象序列化 将实现serializable的对象转换成字节序列 并可在以后恢复这个对象(对象中的不需要恢复的属性用transient(瞬时)修饰)static修饰的也需要手动序列化 用ObjectOutputStream和ObjectInputStream 序列化得到的是一个对象 找到相应的类才能起作用 可通过添加与Externalizable 类似的writeObject()方法来选择序列化内容
实现Externalizable (WriteExternal(),ReadExternal()) 指派一个替代对象(重新构造,调用构造器)
正则:find()任意部位 matches()和lookingAt()从开头 matches()整个成功才成功
File file=new File(".");是指所有目录吗
十三
写一个线程 继承Thread类 重写run()方法(线程执行体) 调用start()时线程启用 sleep()睡眠 放到try块中 有可能被打断 如果必须控制执行顺序最好别用线程
Yield()当前线程进入就绪状态,相当于重新调度一次
优先级 很多程序处于阻塞状态等待运行时有效果
后台线程 当所有非后台线程都结束 这个程序就结束了 后台程序不再执行 后台线程派生的线程也是后台线程
Jion()调用其他线程 并等待他执行完 相当于方法调用
实现runnable接口创建线程 创建时需要新建Thread对象 把runnable对象传入它的构造器 由于runnable是个接口 所以它允许多继承 可以把很多事物放到一个类中 调用时方便(选用runnable(灵活性)后代码复杂都会增加 如果不是必须一般选用Thread)
同步:保证了 可见性(数据可见) 有序性(执行有序 不会被打断)
Synchronized同步关键字 为对象加锁 有对象访问时别的对象不能访问 表示拿到锁才能执行 同步锁加在“访问共享资源的代码段上”(不是在共享对象上,在访问时加锁)
Volatile 保证可见性 任何改变都会被所有线程发现(适合用在一个变量被几个共享,通过线程对这个变量赋值操作)
原子操作 不可分割 变量类型不包括double和long 原子性对基本类型读取或赋值时才有效
最安全的同步 如果要对一个方法同步 最好把剩余的方法也同步
Sleep()不释放锁 wait()释放锁 打断他们要抛出runtimeException();
写线程时 wait()和notify()需要放到synchronized块中 wait()和notify()方法需要先获取对象锁才能继续 必须加锁 而sleep()不必
有动作的对象用线程 把所执行的动作放到线程里面
选择thread runnable 线程中加while(true)? 错误处理(RuntimeException)
单元测试
每个测试必须是public,不接受任何参数,返回值void,并且有一个“test”开头的方法名,setUp()方法创建一个通用集合并初始化(也可在构造器中初始化) tearDown()方法执行清除工作(可选)
每个测试都会创建一个对象
单元测试就是写新的方法去测试原来的方法,测试类中的变量可以再构造器中实例化也可以在方法中实例化
断言(assert):我断言后边的表达式是正确的 如果错误则报异常
DBC(design by Contract 有一个契约存在于服务端与客户端之间)中 断言可以被作为检测指令 相当于是服务端与客户端有几条规则 检验他们是否符合规则(先检条件(precondition,直接检验 相当于方法调用)、后检条件(postcondition 用assert 修饰 作为断言)、不变量检测(用assert invariant()--检测容器内部内容是否合法,不合法抛出异常))
这些检验相当于程序运行期间调用方法进行检测
Make自动化所有事物 Ant用xml文件保存java文件间的关系 做到跨平台
日志,9个级别OFF(Integer.MAX_VALUE),SEVERE(1000),WARNING(900),INFO(800)
CONFIG(700),FINE(500),FINER(400),FINEST(300),ALL(IntegerMAX_VALUE)
想要改变输出方式就需要用到处理器(直接调用addHandler()方法) 处理器就是将日志导出的工具 发布LogRecord(记录日志)的内容
自己编写处理器:继承Handler类 要实现piblish(),flush(),close()方法
可以加过滤器Filter得到想要的内容 也可加Format格式化内容,工作过程是先让LogRecord进入Filter或Format中过滤或格式化,然后再输出
Logger.setFilter() fileHandler.setFormatter()
本章三个要点,1、JUnit 2、Ant 3、日志
附录 A
对象没有作用域,引用有作用域 final修饰的常量指向对象不是表示对象内容不可修改,而是表示不能指向其他对象
如果想修改内部参数而又不影响其他的引用,这时可以制作一个对象的副本(新建一个对象,把值附过来)
克隆是时 实现cloneable接口 从写父类的clone方法定义为public 在方法中调用父类的clone()方法super.clone()---用try...catch捕捉并抛出异常
克隆组合对象时要对内部应用逐个克隆,对ArrayList进行深层克隆时要对其中的每个对象进行克隆
采用序列化也可进行克隆 只是效率上比较低
克隆四点要点 1、实现Cloneable接口,2、重写clone方法,3、调用父类super.clone方法,4、在clone中捕捉异常 如果因为protect不能调用clone方法时,用反射机制强制调用
只读类:进行运算时要返回一个新的对象,每次都不改变原有的初始对象
缺点---频繁的创建对象 系统开销比较大,解决办法就是创建伴随类,就像String有伴随类StringBuffer
CMD 命令下输入Java -jar ***.jar 参数运行jar文件
万物皆对象
程序是对象的集合,通过发送消息来彼此调用对方
每个对象都拥有其类型
某一特定类型的所有对象可接受同样的消息
你可以通过创建包含现有对象集合的包的方式来创建新类型的对象
继承is-a is-like-a 组合has-a
代码的复用: 继承 重写方法 父类变量指向子类实例 子类实例转换为父类实例
集合:list 列表 存储序列 map 关联数组 建立对象之间的关系 set存储一类对象
重写对象的equals方法时必须对hashcode方法进行重写,set存放对象时先对hashcode进行判断 equals判断时可能为空的对象放到后边
Java其他的特点 垃圾处理 异常处理
二、引用 基本数据类型 作用域
类中内容解析 成员 方法(名字、参数、返回值、方法体)名字和参数确定方法唯一性 如何调用方法—对象.方法名 return表示已经执行完成,离开此方法 此方法返回什么值 方法的结束 return 异常
命名空间区别类名相同的类import导入 static关键字修饰的是类属性或类方法能直接通过类名调用 最大的用法就是不创建对象时调用它
代码风格 包名小写 (驼峰规则)类名首字母大写 方法和变量首字母小写后面每个单词首字母大写
注释编写 帮助文件生成 用/** */括起来的是显示内容,可嵌入html代码
三、= == !=可操作所有对象 + +=可操作String类型
别名对象 把一个变量指向的对象赋给另一个变量 有一个改变时另一个也会改变
运算符
正则 -?可能为负或为正 \转义 \d数字 \D非数字 \w单词 \W非单词 x+一次或多次
x?一次或一次都没有 x*零次或多次 x{n}n次 x{n,m}至少n次至多m次
Pattern匹配的正则,Match去比较 正则中两个常用类
自增自减 Pattern Matcher
比较 ==比较的是地址 equals比较的是内容
短路 &&如果前面的false后边不在运行后边内容
||前面是true不在运行后边内容
位运算 &与运算 |或运算 ^异或运算(若不同结果是1) ~非运算 <<左移 <<<无符号左移 boolean不能进行算术运算可进行&^|位运算和条件运算 char int等不可进行条件运算float和double不能进行条件运算和位运算
三目运算
类型转换 基本数据类型 类
科学技术4e-4是4x10-4
三种循环 while do..while for while和do。While的区别 do。。while至少执行一次 for中可以定义多个变量,类型必须一致
break 中断当前循环(最内层)若想中断所有循环添加标签 return跳出循环的同时中断方法
continue 跳出当前循环 进入下一次循环 带标签的continue跳到标签位置继续执行
swith。。case swith()中的内容只能是能自动转换成int型的数据即byte short char int类型
如果符合条件的case后没有break则继续执行 直到遇见break停止
Math.Random()产生随机数范围是[0.0,1)
四、构造方法 重写 默认不写的是无参构造器若写有参的会把无参的覆盖 这时需要把默认的无参构造方法写出来
区分重写方法 参数类型和顺序上区分
重载过程中基本类型的转换问题大à小强制转 小à大自动转换
this调用方法的那个对象 this()如果在构造方法第一行(只能在第一行) 则调用别的构造方法
static方法深入 不含有this的方法 静态方法不可调用非静态反过来 可以 相当于全局
垃圾回收自动回收也可手动回收 手动回收不一定执行 垃圾回收只于内存有关
成员的初始化 基本数据类型如果不初始化就会有默认值(char初始值为0打印时为 ) 类的不初始化默认为null
类初始化时:类在加载时,先初始化类中变量(先静态再动态,只在必要时才创建,静态变量只在第一次实例化时执行一次,构造方法的this或super后执行动态变量的初始化)再执行构造方法
这地方谨记在普通成员变量在构造器中的this或super关键字后初始化
再有继承关系时 类加载时先初始化类中静态变量 然后父类构造方法(构建父类实例 顺序和类初始化时一样在this之后初始化父类非静态变量)然后本类的构造方法实例化类(super之后初始化子类非静态变量)
数组初始化 java中数组长度不可修改 从0开始最大索引length-1 数组中可以放置对象
五、包名(域名倒过来) 如果导包冲突时 就在new时加上具体的包名
访问权限 public protected private 和默认
每个单元只能有一个public类(也可一个都没有) 且文件名和public类名相同
重点:访问权限是给客户端程序员定制的规则 同时也简化了他们对类的理解
复用类 组合和继承
Java三大特性 继承、封装、多态
继承 继承父类中的参数和方法(public)
构造器第一行是super则调用父类相应的构造器(this调用自身的构造器)super和this只可用在构造器第一行
继承和组合的选择 has-a组合(一般用private) is-a继承(需要向上转型时选择继承)
继承时判断调用子类还是父类的方法要看变量的具体指向(不看变量类型) 指向谁就调用谁的访法
final关键字,修饰类方法变量时表示是最终的不可变的 final修饰的变量必须在定义处或构造器中实例化 修饰类表示不可继承不可改
七、多态 用方法的动态绑定来实现 父类定义一个变量指向其子类的实例 调用时调用的是子类中的方法也就是内存中指向的那个实例的方法
抽象方法 只有方法声明没有方法体 抽象类不能被实例化
避免在构造器中调用其它方法(如果调用子类方法,此时只能有默认初始值,不符要求)
用继承表达行为上的差异 用组合表达状态上的变化
八、接口与内部类
接口 实现多继承 原因1、可以有多个向上转型基类(核心--为了能够向上转型为不止一个基类型)2、防止创建该类对象
类中可以定义接口 接口中也可定义接口(接口中的成员全是public修饰)
内部类 类中的内部类可以隐藏实现 只给用户一个基类或接口的引用
内部类有它特定的作用范围 在语句块外边调用内部类就会失去效果
匿名内部类调用外部对象 该对象必须是final型的 对匿名内部类而言 他没有构造器 实例初始化的效果就是构造器 不能重载 故只有一个
内部类自动拥有对其外围类所有成员的访问权(反过来有限制)
嵌套类(静态内部类) 可包含static元素和嵌套类 而普通内部类不可以如果不是嵌套类 static只可以用在最外层的类中
嵌套类可放在接口中 可以嵌套进类中编写本类的测试代码
获取内部类实例 p.new C(); p是外部类的实例
调用内部类需要一个外部类的实例
内部类的继承有特殊的语法 构造方法中 old.super(); 内部类不会被重载 它是独立的
局部内部类和匿名内部类的区别是局部内部类可拥有构造器,当需要多个对象时就用局部内部类
内部类的作用 可以实现多继承(外部类继承一个,内部类继承一个,调用方法获取内部类实例) 内部类是独立的 可以做自己的动作 灵活性好
★子类继承或实现父类或接口重写方法时 方法的修饰符范围不能小于父类
回调 一个类全部都是封闭的,只提供一个对外的能产生一个内部类的实例的方法,这个内部类实现了一个接口并且有一个方法能访问外部类的方法,调用时可把这个方法当做钩子调用外部类的私有方法
回调可以理解为有一个问题自己解决不了,但是别人能解决,这时他去询问别人,当别人解决掉这个问题后再把结果给他
九、异常与错误
异常作为一个对象 可以手动添加或定义 异常就是用名称来定义发生的问题(就是在程序不能正确处理的时候,启用别的处理方式)把正常代码与处理错误的代码分开执行
try…catch 捕获处理异常 后跟finally表示无论是否异常都要执行(把除内存之外的资源恢复到原始状态)一个catch只能捕捉一个异常
throw抛出一个异常
throws抛出异常给下一级 在方法后边
异常链 捕获一个异常然后抛出一个异常 并把原始信息保存下来 没参数cause构造函数不含参数cause的异常 调用initCause方法(把普通异常转化为运行异常是就是用cause的构造方法)
运行时异常(RuntimeException()的子类)在编码中唯一可以忽略的异常(其他的编译器强制实施)
方法重载时子类方法继承父类方法的异常
子类构造器中异常说明必须包含基类构造器的异常说明(子类只能继续抛出父类抛得异常 如果想捕获就与super关键字用在第一行冲突)
继承时子类方法中异常不多于父类()子类方法中的异常可不写(也可写父类异常的子类) 调用方法时捕获父类异常
?构造器中的异常 若打开一个程序 打开时抛出异常 则执行关闭此程序(不在finally中定义下面的程序还将继续使用初始化的对象,如需在后边关闭 设置一个表示初始化是否成功的标记)
异常匹配:如果最近的异常能正确匹配 程序就不在继续往下寻找
用RuntimeException来包装“被检查的异常”
十、RTTI(run-time type identification)在运行期间识别一个对象类型
当你只有一个指向对象的基类的引用时 找到确切类型
RTTI形式1、直接转,2、Class类中的方法(getSuperClass()等等) 3、instenceof
三种类初始化 直接new Class.forName() Gc.class;
Class.forName(“Gc”);找不到?(需要加上包名)
动态instanceof 用isinstance()方法 前面跟类后边跟测试对象
Instance(属于 子类也属于父类类型)和equals(等于 子类和父类分开)
newInstance()调用的是无参构造方法
RTTI编译期打开和检查.class文件 反射在运行期执行
反射时调用方法中传递参数时 需要的对象是它反射的实例对象
数组与容器
区别:效率(数组比ArrayList高) 类型(数组里面是特定类型) 持有基本类型能力(数组能保存基本数据类型)
数组
数组定义初始化 三种赋值方式(整体赋值,遍历赋值,一个数组赋给另一个)
Arrays类中提供管理数组的静态方法
数组比较 相等是基于内容,内容一样数组就相等
填充数组
数组元素的比较(实现comparable接口 重写compareTo方法 该类型的数组排序时调用compareTo方法来判断先后顺序) 如果想自定义排序方式实现Comparator
数组查找 必须先排序再查找
容器
容器可以直接打印
容器可以存储任何对象(基本类型除外 他们不是真正的对象不是Object的子类 也就是在取数据时不能转换成基本类型)
迭代器 Iterator
产生无意识的递归调用时 用super关键字解决
有数组创造list 再有list创造set map
ArrayList插入移除速度慢 快速访问速度快 LinkedList正好相反
Set:HashSet(为快速查找设计 无序) TreeSet(按比较元素进行排序comparable) LinkedHashSet(查找快 按插入顺序进行排序)HashSet性能好 遍历时LinkedHashSet比较好
Map:HashMap(性能好无序查询快速)LinkedHashMap(链表维持内部顺序就是原来插入顺序 访问时被访问的元素会自动排到后边)TreeMap(按比较进行排序comparable)
Map中HashMap最好
如果要使用自己的类作为map中的键必须重写equals(五个特性)和hashcode方法
用hashcode的作用在于查询速度
List中若想插入另一个遍历的list的数据时遍历用ListIterator
在操作数组转化的list或用sublist截取list时 应new一个新的list 防止出现异常
hashMap的键和HashSet中的元素是按hashcode排列 存放的如果是对象的话从写对应类的equals和hashCode方法
和hash相关的都是为了快速查询而来的 linked是遍历最快
把容器设置为只读或者线程同步都有特殊的方法
并发容器
十二
inputstream和outputStream中的in和out都是相对于内存来说的 从文件进入内存为in 从内存进入文件为out
IO重点 编码解码 需要指定编码用InputStreamRead(inputstream,ecoding) 封装 read()返回的是读取的字节的int值 read(byte[]bytes)返回的是读取的字节数
String.getBytes()是编码
File文件类
输入InputStream Read 都有read()方法 输入流的父类
输出OutputStream write 都有write()方法 输出流的父类
对文件读写时 记得关闭打开的流
FilterInputStream的子类有:BufferedInputStream(写入缓存)DataInputStream(把数据类型写入输入流) FilterOutputStream子类中有个PrintStream(产生格式化输出)
打印流只有PrintStream和PrintWriter
新IO ,nio FileChannel 通道 可改变数据流 ByteBuffer 字节缓存 存取字符时需要转码(Charset)
写入文件时 最后一定要先flush()在关闭
ByteBuffer有单独保存基本数据类型的方法
字节数组写到文件 先用ByteBuffer.wrap()包装起来 再用getChannel在inputStream中打开一个通道 然后把ByteBuffer保存到FileChannel中
CharBuffer和IntBuffer等都是ByteBuffer上的一个视图 和FileChannel交互的是ByteBuffer
ByteBuffer中包含参数的get或put方法不会引起position的改变
MappedByteBuffer大文件映射 可对大文件局部操作 写时用RandomAccessFile
文件加锁 只能在在通道上加锁 防止输出乱码 在输出时再转换类型
压缩 Gzip zip 输入输出直接封装成zip(gzip)inputStream zip(gzip)outputstream即可 不局限于压缩文件也可压缩网络数据
对象序列化 将实现serializable的对象转换成字节序列 并可在以后恢复这个对象(对象中的不需要恢复的属性用transient(瞬时)修饰)static修饰的也需要手动序列化 用ObjectOutputStream和ObjectInputStream 序列化得到的是一个对象 找到相应的类才能起作用 可通过添加与Externalizable 类似的writeObject()方法来选择序列化内容
实现Externalizable (WriteExternal(),ReadExternal()) 指派一个替代对象(重新构造,调用构造器)
正则:find()任意部位 matches()和lookingAt()从开头 matches()整个成功才成功
File file=new File(".");是指所有目录吗
十三
写一个线程 继承Thread类 重写run()方法(线程执行体) 调用start()时线程启用 sleep()睡眠 放到try块中 有可能被打断 如果必须控制执行顺序最好别用线程
Yield()当前线程进入就绪状态,相当于重新调度一次
优先级 很多程序处于阻塞状态等待运行时有效果
后台线程 当所有非后台线程都结束 这个程序就结束了 后台程序不再执行 后台线程派生的线程也是后台线程
Jion()调用其他线程 并等待他执行完 相当于方法调用
实现runnable接口创建线程 创建时需要新建Thread对象 把runnable对象传入它的构造器 由于runnable是个接口 所以它允许多继承 可以把很多事物放到一个类中 调用时方便(选用runnable(灵活性)后代码复杂都会增加 如果不是必须一般选用Thread)
同步:保证了 可见性(数据可见) 有序性(执行有序 不会被打断)
Synchronized同步关键字 为对象加锁 有对象访问时别的对象不能访问 表示拿到锁才能执行 同步锁加在“访问共享资源的代码段上”(不是在共享对象上,在访问时加锁)
Volatile 保证可见性 任何改变都会被所有线程发现(适合用在一个变量被几个共享,通过线程对这个变量赋值操作)
原子操作 不可分割 变量类型不包括double和long 原子性对基本类型读取或赋值时才有效
最安全的同步 如果要对一个方法同步 最好把剩余的方法也同步
Sleep()不释放锁 wait()释放锁 打断他们要抛出runtimeException();
写线程时 wait()和notify()需要放到synchronized块中 wait()和notify()方法需要先获取对象锁才能继续 必须加锁 而sleep()不必
有动作的对象用线程 把所执行的动作放到线程里面
选择thread runnable 线程中加while(true)? 错误处理(RuntimeException)
单元测试
每个测试必须是public,不接受任何参数,返回值void,并且有一个“test”开头的方法名,setUp()方法创建一个通用集合并初始化(也可在构造器中初始化) tearDown()方法执行清除工作(可选)
每个测试都会创建一个对象
单元测试就是写新的方法去测试原来的方法,测试类中的变量可以再构造器中实例化也可以在方法中实例化
断言(assert):我断言后边的表达式是正确的 如果错误则报异常
DBC(design by Contract 有一个契约存在于服务端与客户端之间)中 断言可以被作为检测指令 相当于是服务端与客户端有几条规则 检验他们是否符合规则(先检条件(precondition,直接检验 相当于方法调用)、后检条件(postcondition 用assert 修饰 作为断言)、不变量检测(用assert invariant()--检测容器内部内容是否合法,不合法抛出异常))
这些检验相当于程序运行期间调用方法进行检测
Make自动化所有事物 Ant用xml文件保存java文件间的关系 做到跨平台
日志,9个级别OFF(Integer.MAX_VALUE),SEVERE(1000),WARNING(900),INFO(800)
CONFIG(700),FINE(500),FINER(400),FINEST(300),ALL(IntegerMAX_VALUE)
想要改变输出方式就需要用到处理器(直接调用addHandler()方法) 处理器就是将日志导出的工具 发布LogRecord(记录日志)的内容
自己编写处理器:继承Handler类 要实现piblish(),flush(),close()方法
可以加过滤器Filter得到想要的内容 也可加Format格式化内容,工作过程是先让LogRecord进入Filter或Format中过滤或格式化,然后再输出
Logger.setFilter() fileHandler.setFormatter()
本章三个要点,1、JUnit 2、Ant 3、日志
附录 A
对象没有作用域,引用有作用域 final修饰的常量指向对象不是表示对象内容不可修改,而是表示不能指向其他对象
如果想修改内部参数而又不影响其他的引用,这时可以制作一个对象的副本(新建一个对象,把值附过来)
克隆是时 实现cloneable接口 从写父类的clone方法定义为public 在方法中调用父类的clone()方法super.clone()---用try...catch捕捉并抛出异常
克隆组合对象时要对内部应用逐个克隆,对ArrayList进行深层克隆时要对其中的每个对象进行克隆
采用序列化也可进行克隆 只是效率上比较低
克隆四点要点 1、实现Cloneable接口,2、重写clone方法,3、调用父类super.clone方法,4、在clone中捕捉异常 如果因为protect不能调用clone方法时,用反射机制强制调用
只读类:进行运算时要返回一个新的对象,每次都不改变原有的初始对象
缺点---频繁的创建对象 系统开销比较大,解决办法就是创建伴随类,就像String有伴随类StringBuffer
CMD 命令下输入Java -jar ***.jar 参数运行jar文件