Java基础知识

Level 1 Level 2 Level 3 Level 4 Level 5 Level 6 Level 7 Level 8 Level 9 Level 10 Level 11
Java基础 面向对象(OOP) 封装(抽象) 普通类 组合(has-a) 组合的形式 使用某个类的一个对象
将该类的一个对象置于某个新类中 如果组合是动态发生的,称为聚合
UML表示:
枚举
内部类 内部类 语法 .new:类名+.new创建内部类的对象
.this:类名+.this得到外部类的对象
特征 不能通过引用外部类的名字方式创建,仅能通过外部类的对象创建内部类对象
不能包含static方法和static字段
不管嵌套多少层,都可以访问外围类的所有成员
内部类可以由多个实例,每个实例拥有自己爹状态信息
单个外围类中,可以让多个内部类以不同方式实现同一个接口或继承同一个类
嵌套类(静态内部类) 语法 可以通过外部new 外部类名 + 嵌套类名方式创建对象
类用static关键字修饰
特征 不能从嵌套类对象中访问非晶态外围类的对象
可以包含static方法和属性
嵌套类可以作为接口的一部分,作为接口的嵌套类
创建嵌套类对象时,不需要依赖于外围类对象的创建
局部内部类 特征 存在于方法体内或作用域内,仅方法或作用域中可以访问
语法 局部内部类不能有访问说明符,因为它只在作用域中生效
并不是说,作用域中的局部内部类是在作用域满足条件时候才被创建的,它在编译时,作为类被编译过了
匿名内部类 语法 new + 需要向上转型成的类的类名+( )+ { +方法体 + } + ;
特征 生成的匿名内部类,是创建时指定的类型的导出类或接口实现
匿名内部类需要使用外部定义的对象,需要参数引用是final的
通过实例初始化方式,创建匿名内部类的对象
只能实现一个接口
共有特性 通过外部对象默认的引用,链接到了外部对象,因此可以访问外部类的所有成员
内部类相对于外部类独立存在
内部类的继承,需要在构造器中指定通过外围类对象调用super()方法
在外围类的继承关系中内部类不能被覆盖,子类中与基类中同名的内部类是独立的两个类
可以指定子类中的内部类继承基类中的内部类,这样,内部类的方法可以被覆盖,支持向上转型
内部类编译后也会生成.class文件,它的命名规则是:外围类名字+ $ +内部类名字,匿名内部类是通过编译器简单的产生一个数字作为其标识符
闭包 一个可调用的对象,记录了一些信息,这些信息来自于创建它的作用域
回调
接口 特征 接口同样需要访问权限修饰,如果不给定访问权限的限定,默认只有包访问权限
接口中也包含域,但都是隐式的static和final的
接口中的方法,默认是public的
接口可以多重继承(一个实现类,去实现多个接口,也可以定义一个新的接口,去继承多个接口)
接口的适配
接口嵌套 类内部嵌套的private接口,只能交由拥有权使用它的对象使用
接口之间可以嵌套,并且接口的规则被严格执行
实现某个接口时,并不需要实现此接口内部嵌套的接口
private接口不能在定义它的类之外被实现
default方法 default方法可以有方法体
如果A类实现接口B,B中含有default方法,A类会继承B方法
如果A类同时实现接口B和C,在B和C中都定义了default方法f(),在A中需要重写方法f()
如果A类继承B类,B类实现接口C,C中定义了default方法f(),B中也存在方法f(),A类继承B类中的方法
抽象类 抽象方法
接口与抽象类 相同点
不同点
继承(is-a) 概念 源类(超类、基类、父类)
副本(导出类、继承类、子类)
UML表示:
单根继承:Object
特性 子类使用默认构造器初始化,会默认先调用基类的默认构造器初始化基类
通过带参数构造器初始化子类,需要显式地调用父类带参数的构造器初始化基类,否则只会调用默认的构造器初始化基类
由于存在继承与组合同时使用的情况,在调用一些自定义的清理方法时,需要注意执行顺序,应该与构造顺序相反
在继承关系中,方法的重载不会被屏蔽,符合访问权限的情况下,重载方法仍可以正常调用
重载与覆盖 重载
覆盖
多态(后期绑定、动态绑定) 向上转型:将导出类看作是它的基类的过程 继承
接口
绑定 前期绑定
后期绑定(动态绑定、运行时绑定) final(private)关键字修饰的方法,关闭动态绑定
静态方法(静态域)是在编译期就解析的,因此也不具有多态性
构造器的调用顺序 将分配给对象的存储空间初始化成二进制零,引用对象,一般初始化为null
调用基类的构造器
按照声明的顺序调用成员变量的初始化方法
调用导出类的构造器主体
因为构造器在多态形态下的不稳定性,需要尽量依照如下准则:
用尽可能简单的方法,使对象进入正常状态,如果可以的话,避免调用其他方法,在构造器中唯一可以安全调用的那些方法使基类中的final(private)方法。
协变返回类型
多态的表现形式 方法的重载
继承结构中方法的覆盖
接口的不同实现
抽象方法的不同实现
类型识别与泛型 向下转型
类型识别 RTTI(RunTime Type Identification) Class对象 特性 类加载器:所有的类都是在对其第一次使用时,动态加载到JVM中的,当程序创建第一个对类的静态成员的引用时,就会加载这个类。
一旦某个类的Class对象被载入内存,它就被用来创建这个类的所有对象
获取class对象引用的方式 Class.forName(String arg) (arg必须传递类的全限定名)
如果已经拥有了一个类的对象,可以调用obj.getClass()方法
使用类字面常量获取class对象,Integer.class
对比 使用Class.forName()方法生成class对象,会直接完成类加载的三个步骤
使用类字面常量生成class对象,一开始不会初始化,直到第一次使用类的静态域,类才会初始化(使用static final 的编译期常量,不会对类进行初始化,但如果static final 修饰的引用,指向的是一个表达式,这个静态变量被使用时,类就会被初始化)
生成class的步骤 加载:类加载器查找字节码,从这些字节码中生成一个Class对象
链接:对类的字节码进行一些验证,为静态域分配存储空间,并且如果必须的话,解析这个类创建的对其他类的所有引用
初始化:如果该类有超类,则对其初始化。执行当前类的静态初始化器和静态初始化块
常用方法 forName(String arg) 获取class对象
getName() 产生全限定类名
getSimpleName() 产生不包含包名的类名
getCanonicalName() 产生全限定类名
isInterface() 判断是否是接口
getSuperclass() 查询其直接基类,返回基类的class对象,可以借此查询完整的继承结构
newInstance() 实现虚拟构造器,在不知道具体类型的前提下,正确创建当前类的对象
Class对象的比较 instantsof
Class.isInstance()
结果相同 保持了类型的概念,即继承结构下的向上转型
equals
==
结果相同 未考虑继承,只是比较当前引用指向的对象是否相等
泛化使用class引用 通过使用泛型语法,可以让编译器强制执行额外的类型检查
将泛型语法用于Class对象,newInstance()方法,在某种程度上,返回的是对象的确切类型,而并非Object。但如果需要泛化的类型是超类,由于编译器只能允许泛化表达式,去表示“某个类,是另一个确切类的超类”,即Class ,由于这种含糊性,这时候上述的确切的类型,就无法获得,而只能通过Object类的引用指向它
RTTI形式 传统的类型转换,RTTI确保类型转换的的正确性
代表对象类型的Class对象,通过查询Class对象可获取运行时所需的信息
instanceof关键字,判断对象是否是某个特定类型的实例
反射 与RTTI的区别 RTTI想要知道某个对象的确切类型,这个类型在编译时必须已知,即.class文件对于JVM必须是可获取的,编译器在编译时打开和检查.class文件
对于反射机制来说,.class文件在编译时是不可获取的,所以是在运行时打开和检查.class文件
类库 Field get()
set()
getFilds()
Method invoke()
getMethods()
Constructor newInstance()
getConstructors()
反射使类中的信息都透明了。(后门)
代理 一般代理
动态代理 Proxy.newProxyInstanc() 创建动态代理 参数 类加载器:可以从已经被加载的对象中获取其类加载器
大力实现的接口列表(不是类或抽象类)
InvocationHandler接口的一个实现
invoke()方法 代理对象
要执行的方法对象
请求参数
空对象 声明一个Null接口
使用嵌套类(空对象是单例的),实现Null接口,定义空对象
泛型 基础概念 泛型(目的):希望类或方法能够具最广泛的表达能力
参数化类型:将具体的类型参数化,将类型定义为参数形式(类型形参),在使用/调用时传递具体类型(类型实参)
元组:将一组对象直接打包存储于其中的一个单一对象,这个容器对象允许读取其中的元素,但不允许向其中存放新的对象(数据传送对象、信使)。
类型参数推断
边界:对象进入和离开方法的地点
基本语法 泛型类
泛型接口
泛型方法 将参数列表置于返回值之前
泛型方法如果需要显式的指明类型,静态方法必须要加上类名,非静态方法必须使用this.关键字,例如:New.f();。this.g();。
匿名内部类
特性 基本类型无法作为泛型参数,通过自动拆箱装箱可以实现基本类型的泛型参数传递
类型推断只对赋值操作有效
擦除 在泛型代码内部无法获得任何有关泛型参数的类型信息
泛型类型参数将擦除到它的第一个边界
泛型类型只有在静态类型检查期间才会出现(即在编译期,完成对传递进来的参数的额外类型检查,对返回的参数进行相关的转型,自动转型到边界类型,而后进行擦除),这一切都在边界处完成
擦除的补偿:(引入类型标签) 使用T参数表示泛型,无法通过new创建对象 原因 擦除,不知道T的真实类型
编译器无法验证T是否具有无参构造器
替代方法 传递工厂对象,使用工厂对象创建新的实例(警惕那些不具有默认构造器的类,比如Integer)
模版方法设计模式,通过子类创建对象
泛型数组 通过普通方式,仅可以声明引用,无法创建一个泛型数组,因为擦除过后,编译器认为数组是Object类型的,而数组的特殊性,会导致在运行时,通过向下转型,会抛出异常
如果将泛型数组中的元素单独拿出来转型,是可以成功的
产生正确类型的泛型数组,可以通过引入类型标签,Class type,通过Array.newInstance(type,sizee)方法创建正确类型的数组。而且可以直接被使用
边界 使用无界泛型参数可以调用的方法,只能是Object中存在的方法
通配符 一些约定俗成的表示方法 ?:一般表示不确定的Java类型
T:一般表示一个具体的Java类型
K,V:代表键值对表示Key,Value
E:一般表示Element
extends(上界/子类型通配符) 此泛型持有的对象类型,只能是上界本身以及上界类型的导出类
? extends A & B
使用了子类型通配符,不能传递类型参数给泛型参数,因为编译器无法知道传递的是哪一个子类型(如 T extends A, 编译器只知道T 应该传递近来的是A的导出类,但不知道具体是哪一个导出类,可能是B,也可能是C,因此,当声明一个对象后,向其中进行赋值操作时,可能同时传递B或者C,如果调用合法,会导致泛型类同时持有两种类型,导致类型不安全),但是可以 声明A a 的引用去获取对象,因为无论如何得到的对象,都是A的导出类。或这通过向下转型,将T对象的引用指向该对象
super(下界/超类型通配符) 即此泛型持有的对象类型,只能为下界或下界类型的基类
可以向使用超类通配符声明的对象的方法中,传递类型参数给泛型类型,但这是违反静态类型安全的(因为,通过T super A 表示T 是A的导出类,规定了下界是A,因此向泛型中传递A的子类都是合法的),但是无法从中获取任何泛型类型的返回值(比如,T super A ,只知道T是A的基类,无法明确是哪个基类,直接通过T 的引用指向得到的对象,类型不安全)可以通过Object类型声明的引用去获取该对象
无界通配符 几种通配符方法,传递不同参数的不同处理方式
捕获转换
几个问题 基本类型不能作为类型参数 Java的自动拆箱装箱可以使用包装类实现,但自动拆箱装箱无法应用于数组
如果自动拆箱装箱出现性能问题,就需要专门适配基本类型的容器版本(如:Org.apache.commons.collections.primitives
一个类无法实现一个泛型接口的两种变体,由于擦除的原因,最终展现出来的两种变体,实际上是具有相同的类型信息的
传递泛型类型的参数的方法无法被重载,擦除的原因,重载后的两个方法,参数签名相同,因此无法编译
基类劫持接口,即基类实现了泛型接口,子类也实现泛型接口时,向其中传递进新的泛型类型参数,将无法工作,除非传递进去的泛型类型参数与基类传递进去的一致
其他 引申概念及实现 自限定类型 古怪的循环泛型:父类用子类替代其参数,泛型基类变成了一种其所有导出类的公共功能模版
自限定:强制泛型当作自己的边界参数来使用,强制要求正在定义的类当作参数传递给基类,可以保证类型参数必须与正在定义的类相同,自限定限制只能作用于继承关系
意义 产生协变参数类型
特性 非泛型方法中,参数类型不能随子类型发生变化
混型 使用接口产生混型效果
使用装饰器模式
与动态代理混合,通过动态代理,申城的类的动态类型将会是已经混入的组合类型
潜在类型机制 反射
适配器仿真潜在类型机制
子主题
将函数对象用作策略 函数式编程的前身?
容器 容器结构 Iterable(顶层接口) Collection(独立元素的序列) List ArrayList 数据结构:数组
特点 优势 擅长随机访问元素
劣势 在List中间插入和移除元素较慢
特殊方法
LinkedList 数据结构:双向链表
特点 子主题
特殊方法 getFirst() == element()(Queue中定义的方法):返回列表的头,但不移除,列表为空时抛出异常
peek(),方法类似于getFirst(),但是在列表为空时,返回null
removeFirst() == remove() (Queue中定义)移除并返回列表的头,列表为空时,抛出异常
poll()方法类似于removeFirst(),列表为空时,返回null
addFirst()在列表头添加元素
add() == offer() == addLast(),在列表尾端添加元素
removeLast(),移除并返回列表的最后一个元素
可以被当作栈来使用(后进先出的容器 LIFO) getFirst()、addFirst()、removeFirst(),模拟栈当中对元素的操作
Set HashSet 数据结构:HashMap
特点 散列排布
插入的元素必须实现hashcode()方法
LinkedHashSet 数据结构 继承自HashSet,相同的数据结构
特点 维护插入的元素的顺序
插入的元素必须实现hashcode()方法
SortedSet TreeSet 数据结构 HashMap
特点 元素有序排列(按照自然排序或自定义排序规则)
插入的元素必须实现Comparable接口,当加入未实现该接口的元素对象,会抛出异常
特殊方法 Object first() 返回容器中的第一个元素
Object last() 返回容器中的最后一个元素
Comparator comparator() 返回当前Set使用的Comparator
SortedSet subSet(forElement toElement), 返回Set子集,从fromElement(包含)到toElement(不包含)
SortedSet head(toElement) , 生成此Set子集,由小于toElement的元素组成
SortedSet tailSet(fromElement) 生成Set子集,由大于或等于fromElement的元素组成
加入Set的元素必须定义equals()方法确保对象的唯一性
Queue(先进先出的容器 FIFO) 接口方法 offer(),允许的情况下,将元素插入到队尾,或者返回false
peek(),队列为空时,返回null
element(),队列为空时,抛出异常
不移除的情况下返回队头
poll(),队列为空时,返回null
remove(),队列为空时,抛出异常
移除并返回队头
实现 PriorityQueue(优先级队列) 数据结构 数组
特点 通过comparable接口控制优先级
LinkedList
他们之间的差异在于排序方式
还有一些并发情况下使用的队列
Map(映射表) HashMap 数据结构 数组(桶位)+ 链表 + 红黑树
特点 散列存储,查询更快
负载因子:0.75
桶长度:16
LinkedHashMap 数据结构 数组(桶位)+ 链表 + 红黑树
特点 取得键值对的顺序是其插入顺序,或者是最近最少使用的(LRU)顺序
迭代时更快,访问仅比HashMap慢一些
SortedMap TreeMap 数据结构 数组(桶位) + 红黑树
特点 查看键或键值对,它会被排序,顺序取决于Comparable 或Comparator
特殊方法 subMap
WeakHashMap 弱键映射,允许释放映射所指向的对象
ConcurrentHashMap 线程安全的map
IdentityHashMap 使用== 替换equals()对键的比较的散列表映射,专门为解决特殊问题设计的
那些发挥重要作用的抽象类 AbstractCollection
AbstractList
AbstractSet
AbstractMap
提供了该容器的部分实现
可选操作 定义:即在容器的具体类型中未选择实现的一些方法,这些方法的调用一般会抛出UnsupportedOperationException
例子,比如通过Arrays.asList生成的固定尺寸的列表,任何可能引起扩容操作的方法在这里均不可用,可以说是可选择的
原理:面向对象中,对接口的实现,或者继承,一般来说,应该遵守去复用或者实现父类中的方法,通过多态机制,可以调用具体类型中应该调用的方法。然而,有时候,接口模板中,定义的方法,并不是很符合所有使用场景,或不符合当前类的某些特性,但可能又需要覆盖/复用父类中的大部分方法,防止代码重复,或者遵守接口制约。因此选择空的实现,或者选择抛出异常(类库中更常用)的方式,让这个方法,在当前这个类中,不可操作。
意义:防止接口爆炸
散列码 equals() 条件 自反性
对称性
传递性
一致性
对于任何不是null的x,x.equals(null),一定返回false
hashcode() 书写散列性更好的hashcode()方法,应该充分考虑各个域,对每个域计算一个散列码
规则 boolean c=(f ? 0 : 1)
byte、char、short、int c = (int) f
long c = (int) (f ^(f>>>32))
float c = Float.floatToIntBits(f);
double long l = Double.doubleToLongBits(f);
c = (int)(l^(l>>>32));
Object c = f.hashCode();
数组 对每个元素应用上述规则
惯例:result = 37 * result + c
Java1.0/1.1的容器 Vector类和Enumeration接口
HashTable
Stack
BitSet
工具 Collections fill(list,object),用来填充list,但是只能替换list当中已经存在的元素,不能添加新元素
nCopies(count,object),使用对象,填充list
其他方法可以参考Java编程思想第四版P512
Arrays Arrays.asList() 有时候需要通过显式的类型参数说明,指定需要创建的List类型,如:Arrays.asList(array),表示指定生成的list的类型参数为A
该方法会生成一个在Arrays中内置的ArrayList类,底层数据结构是数组,不支持扩容操作,因此如果有意图使容器大小发生改变的操作,就会抛出异常
equals(),比较两个数组是否相等
deepEquals(),用于多维数组
fill(),填充数组
sort(),排序数组,对于没有实现Comparable或者没有传递Comparator的类,调用会抛出异常
binarySearch(),在已经排序的数组中查找元素
复制数组:System.arraycopy() (效率比for循环更高)
Comparable 实现此接口中的compareTo()方法,相等返回0,当前对象小于参数返回负数,当前对象大于参数返回正数
Comparator 可以单独创建类去实现这个接口的compare()方法,然后将这个comparator对象传递给Arrays.sort()方法
数组 特点 效率 对于随机访问,数组比其他数据结构底层支持的容器效率更高,因为数组是简单的线性序列,数组的每个元素均为一个引用,指向具体的内存地址,内存地址中又指向真实对象的实际内存地址
对于弹性数组数据结构,严格的尺寸,又可以避免弹性扩容带来的额外开销
类型 泛型之前,数组是最好的持有具体类型的方式
保存基本类型的能力 数组可以保存基本类型,而容器不行,容器必须通过自动拆箱装箱来实现基本数据类型的保存,自动包装机制很便捷,数组唯一优势的一点就是在这过程中,效率比自动包装机制更高一些
数组是一级对象,数组标识符其实是一个引用,指向堆中创建的一个真实对象,这个对象泳衣保存指向其他对象的引用
数组初始化方法 声明数组变量,创建一个数组的引用,在使用之前,进行初始化
使用new 去初始化数组,元素均为默认值
声明数组变量,初始化后,逐个给元素赋值
使用聚集初始化语法
多维数组 数组嵌套,即上一层数组中的元素,由下一层数组组成
粗糙数组:每一个对象列表的长度都不相同
迭代器 概念:轻量级对象,可以遍历并选择序列中的对象,而客户端程序员不必知道或关心该序列底层结构
主要结构 在容器中组合Iterator接口 接口中含有一些遍历所必须的方法 next()
hasNext()
remove()
在容器的具体类型中,实现迭代器以及迭代器方法
除Iterator外,List容器中采用Iterator的子类ListIterator
意义:统一了容器的访问方式,可以不用通过获取size,然后构建循环,就可以完成容器的遍历
问题:Iterator只能够向前移动,而ListIterator可以完成双向移动,并且可以通过set()方法,替换它访问过的最后一个元素
Java I/O 系统 File类(既可以代表一个文件名称,又可以代表一根目录下的一组文件名称) 方法列表 list() 返回一个字符数组,由文件名构成)
list(FilenameFilter filter) 返回字符数组,由filter实现过滤(回调accept()函数实现)
listFiles(FilenameFilter filter)返回file的数组
FilenameFilter接口 accept(File dir,String name) 接收一个目录和文件名称,用来匹配文件名
输入、输出流(基于字节的流) InputStream 结构 ByteArrayInputStream 缓冲区,字节将从中取出
StringBufferInputStream 字符串,底层实现实际使用StringBuffer作为一种数据源,已弃用
FileInputStream 字符串,表示文件名,文件或FileDescriptor对象
PipedInputStream 多线程中的数据源
SquenceInputStream 两个InputStream或一个容纳InputStream对象的容器Enumeration
FilterInputStream(装饰器的提供类) DataInputStream 包含用于读取基本类型数据的全部接口
BufferedInputStream 可以指定缓冲区大小(可选的)
LineNumberInputStream 仅增加了行号
pushbackInputStream 通常作为编译器的扫描器
数据源 字节数组
String对象
文件
“管道”
一个由其他种类的流组成的序列
OutputStream 结构 ByteArrayOutputStream 缓冲区初始化尺寸(可选),用于指定数据的目的地
FileOutputStream 字符串表示文件名或FileDescriptor对象
PipedOutStream 指定用于多线程的数据的目的地
FilterOutputStream DataOutputStream 包含用于基本数据类型写入的全部接口
PrintStream 可以用boolean表示是否在每次打印时清空缓冲区(可选)
区别 DataOutputStream与PrintStream的区别:DataOutputStream是将数据读取到流种,然后写到指定位置,PrintStream带有打印功能,目的是为了可视化输出
BufferedOutputStream 可指定缓冲区大小(可选)
输入、输出流(基于字符的流) 设计目的 处理字符集(国际化)
Reader FileReader -> FileInputStream
StringReader -> StringBufferInputStream(已弃用)
CharArrayReader -> ByteArrayInputStream
PipedReader -> PipedInputStream
FilterReader -> FilterInputStream BufferedReader BufferedInputStream
LineNumberReader LineNumberInpStream(已弃用)
StreamTokenizer 使用接受Reader的构造器
PushbackReader -> PushbackInputStream
如果不需要使用readLine()方法,那么首选应该使用DataInputStream,用作读取基本数据类型的接口适配器,否则应该使用BufferedReader
Writer FileWriter -> FileOutputStream
StringWriter -> 无对应类
CharArrayWriter -> ByteArrayOutputStream
PipedWriter -> PipedOutputStream
FilterWriter -> FilterOutputStream BufferedWriter -> BufferedOutputStream
PrintWriter -> PrintOutputStream 为了容易过渡到PrintWriter,提供了既能接受Writer的构造器,又提供了能接受OutputStream的构造器,并且,两个类的格式化接口相同
基于字节流与基于字符流结合使用 适配器 InputStreamReader 将InputStream转成Reader
OutputStreamWriter 将OutputStream转成Writer
自我独立的类:RandomAccessFile 特征 适用于由大小已知的记录构成的文件,所以可以使用seek()方法,移动位置,然后进行读取或写入
只实现了DataInput和DataOutput接口,因此是自我独立的,直接从Object类派生而来
工作方式类似于将DataInputStream和DataOutputStream类的方法结合起来,并添加了一些其他方法
方法列表 seek(),从文件某处移动到另一处
getFilePointer()获取当前所在文件的位置
length()获取文件最大长度
构造器接受 r、w、rw等,控制文件读写权限
普通I/O的使用 常用的组合方式 输入 缓冲方式读取字节 FileReader
CharArrayReader
StringReader
读取到内容后生成Reader,将文件流传递给BufferedReader,通过readLine()方法 !=null 来判断文件是否读取完毕。
内存输入 通过其它方式将内容生成Reader加载到内存中,通过StringReader等类,使用read()方法,通过read() != -1,判断内容是否读取完
格式化内存输入 通过DataInputStream进行读取,在DataInputStream中可以通过构造方法插入其他类型的InputStream,并且应该使用available()方法来判定文件是否读取完毕,readByte()方法,因为是一个字节一个字节的读取字符,因此输出的结果都有实际意义,无法判定是否读取完毕
available()是在没有阻塞的情况下所能读取的字节数,对于文件可能意味着整个文件,但是对于不同类型的流,实际可能并非如此,使用需谨慎
输出 基本的文件输出 通常实用FileWriter与文件建立联系,生成Writer,然后使用BufferedWriter进行包装(缓冲输出,主要提高性能)通过不同的包装器进行包装后输出内容到文件
文本文件输出的快捷方式 可以利用PrintWriter中的构造方法简化文件输出建立连接的方式,直接通过new PrintWriter(String filename)方式,得到该Writer。
存储和恢复数据 一般使用DataOutputStream输出数据,生成可用于恢复的文件,用DataInputStream进行读取恢复文件,但是需要注意的是,要么文件的格式固定,要么不通数据类型之前有标记可以识别,否则,可能无法用准确的类型读取方法进行数据的读取。字符串类型,应该首选使用UTF-8格式进行存储和读取
读写随机访问文件
文件读写实用工具 简化文件的读写,简化二进制文件读写
标准I/O System.in 重定向in,setIn(InputStream)
System.out 通过PrintWriter构造器,可以接收System.out流,将其转换为Writer。并且使用自动刷新控制是否允许自动刷新
重定向out,setOut(OutputStream)
System.err 重定向Err,setErr(OutputStream)
进程控制 ProcessBuilder接收命令字符串数组,通过start(),启用,执行各指令,执行结果通过process对象接收。
Process对象可以通过getInputStream()方法获取结果流
Process对象可以通过geteErrorStream()获取执行失败的流
NIO 结构 通道 FileChannel 从缓冲器获得数据,向缓冲器发送数据 in.transferTo(0,in.size(),out)
out.transferFrom(in,0,in.size)
将输入与输出的FileChannel进行连接
缓冲器 ByteBuffer wrap()将已存在的字节数组包装到ByteBuffer中,称之为数组支持的ByteBuffer
allocate()只读访问,显示地使用该静态方法分配ByteBuffer
allocateDirect()产生一个与操作系统有更高耦合性的直接缓冲器,但是这种分配开支会很大,并且具体性能也会随着操作系统的不通而不通
如果我们执行了fileChannel的read()方法,必须调用ByteBuffer的flip()方法,让它做好让别人取数据的准备
如果想要进一步执行read()操作,ByteBuffer必须调用clear()方法,来为每个read()作准备。
旧的I/O系统 面向字节 FileInputStream
FileOutputStream
RandomAccessFile
都有一个getChannel()方法来获取FileChannel
面向字符 无法通过Reader或者 Writer得到FileChannel
可以通过java.nio.channels.Channels类,生成Reader或Writer
转换数据
获取基本类型
视图缓冲器
用缓冲器操作数据
性能
文件加锁
对映射文件的部分加锁
文件压缩 压缩类
压缩格式
Java档案文件
对象序列化 对象序列化与反序列化
XML
Preferences
并发
异常
字符串
注解
设计模式 策略模式
适配器模式
工厂方法设计模式
迭代器模式
模板方法
命令模式
装饰器模式
享元模式
JVM 类加载机制
垃圾回收
Java内存模型
基础语法 对象 对象:我们将问题空间中的元素及其在解空间中的表示称为对象
创建与存储
8种基本数据类型 byte(1字节)-> Byte
short(2字节)-> Short
int(4字节)-> Integer
long(8字节)-> Long
double(8字节) -> Double
float(4字节) ->Float
boolean -> Boolean
char(2字节) -> Character
作用域
方法、参数、返回值
import
static关键字
注释与嵌入式文档
操作符
控制执行流程
初始化与清理
访问控制权限 private 私有的,仅对象内部可访问
protected 子类可访问父类中的protected属性和方法
public 公开的,任何人可以访问
default 默认的访问权限(包访问权限,仅在同一个package下可访问
新特性
final 数据 使用场景 永不改变的编译时常量
运行时被初始化,但不希望被改变的值
特征 若final关键字修饰的是基本数据类型,代表该变量的值不可改变,若final关键词修饰的是对象,代表初始化以后,该引用只能指向该对象地址,不能指向其他对象,但是对象本身是可以被改变的
可以声明final变量,但不给定其初始的域,但使用该引用(变量)之前必须先对其初始化
使用声明的方式,将参数列表指定为final,表示当前方法无法改变变量的值或对象的引用
方法 使用场景 方法锁定,以防任何继承类修改它的含义
早期,用于对执行效率的优化(在栈中执行代码,取得返回值,消除调用的开销),现在基本上是通过虚拟机来实现这类性能的优化,而且使用final不一定可以带来性能上的优化
private与final关键字:private访问权限的变量或方法,都是隐含final关键字修饰作用的
final关键字修饰的类,不允许被继承,因此,类中的属性无法被覆盖,所以类中的属性与方法也相应的带有final的属性
接口 接口中定义的域不能是空final,但可以被

非常量化表达式初始化,这些域不属于接
口的一部分,它们的值存储在该接口的静
态存储区域 | | | | | | | |

你可能感兴趣的:(Java基础知识)