《Java学习笔记JDK8》学习总结

chapter 6   继承与多态

 6.1何谓继承

1.继承的定义:继承就是避免多个类间重复定义共同行为。javascript

2.总结:教材中经过设计一款RPG游戏的部分代码向咱们展现了“重复”程序代码的弊端,为了改进,咱们引进了继承的概念。在咱们自我学习的过程当中,经过一次次的改进,也曾经获得这样的启示:在不一样的信息类中,有多少的属性就设置多少个变量,给每一个属性分别给予设置和获取的方法,以来能够将属性设为private时仍然能够存取引用数据,二来当多个类拥有一样属性和一样的设置、获取方法时,咱们能够将其利用继承于父类的方式精简代码,提升可读性和简洁性,并未以后对代码的修改提供方便。html

简而言之,就是须要咱们经过理解和提炼,将相同的程序代码提高为父类。java

3.继承的格式:咱们经过关键字“extends”来链接子类和父类,这表示子类会扩充、继承父类的行为。linux

4.引入类图:类图是用于建模帮助咱们理解类中内容、父类子类间关系的工具,在教材161页有提示,另外在毕向东老师Java讲解视频中也有说起,而且更为详细。设计模式

5.is-a:继承中,子类与父类间会有is-a的短息,即“是一种”的关系。简单说就是:子类是父类的一种。教材中经过剑士(子类)是一种角色(父类)的例子来讲明。数组

此处引入了编译与运行的经过判断的讲解,在这当中说起了一个操做:“如何让编译程序闭嘴”。这实际上是一种投机的操做,编译虽然可以无错误地经过,但运行结果要自负。

6.重载:在并行的类中定义同名方法,这就是重载方法的运用。安全

7.多态:引入多态,实际上是对重载的改进。当并行类不少而且他们拥有共同的特色时,咱们能够将其运用继承修改代码,并在此基础上引入多态。多态其实就是使用单一接口操做多种类型的对象。这种写法的好处就是可以具备更高的可维护性。数据结构

8.从新定义:在继承父类以后,定义于父类中相同的方法不熟,但执行内容不一样,这就是从新定义(Override)。jvm

技巧:在某个子类中某个方法前标注@Override,表示要求编译程序检查,该方法是否是真的从新定义了父类中国某个方法,若不是,则编译错误。

9.抽象方法:若是某方法区块中没有任何程序代码操做,可使用abstract表示该方法为抽象方法,该方法不用撰写{}区块,至二级用“;”结束便可。ide

10.抽象类:若一个类中有方法没有操做而且表示为abstract,则这个类就不能用来生成实例,便是抽象类,要在class前面表示abstract。

11.抽象类的继承:若子类继承抽象类,对于抽象方法有两种作法:一是继续标示该方法为abstract,该子类所以也是一个抽象类,必须在class前面表示abstract;另外一种作法就是操做抽象方法。若两种作法都没有实施,就会引起编译错误。

6.2继承语法细节

1.protected:

(1)private定义的属性不能直接在子类中存取,只能经过获取方法来取得。若只想让子类能够直接存取属性变量又不想彻底开放访问权限时,可将他们定义为protected。

(2)被声明为protected的成员,相同包中的类能够直接存取,不一样包中的类须要在继承后的子类中存取。

(3)在写程序时,若一开始对权限未知,通常将成员设定为private。

2.从新定义的细节

(1)super:若子类想取得父类中的方法定义,可在调用方法前,加上super关键字。(例见Game6 Role.java;Game6 SwordsMan.java;Game6 Magician.java)

(2)注意:可使用super关键字调用的父类方法,不能定义为private。而且对于父类中的方法权限,只能扩大但不能缩小。

(3)JDK5的改进:在JDK5以前,从新定义方法时除了能够定义权限较大的关键字外,其余部分必须与父类中方法签署彻底一致,例如返回值类型。在JDK5及以后,只要返回类型是父类中方法返回类型的子类,也是能够经过编译的。

(4)提示:static方法属于类拥有,若是子类中定义了相同签署的static成员,该成员属于子类全部,而非从新定义,static方法也没有多态,由于对象不会个别拥有static成员。

3.构造函数:

(1)继承构造函数定义的前后顺序:建立子类石磊后,会先进行父类定义的初始流程再进行子类中定义的初始流程。即在建立子类实例后,会先执行父类构造函数定义的流程,再执行子类构造函数定义的流程。

(2)构造函数的重载:父类中可重载多个构造函数,若是子类构造函数中没有指定执行父类中哪一个构造函数,会默认调用父类中无参数的构造函数。

(3)this()和super()只能择一调用,并且必定要在构造函数第一行执行。

4.final关键字

(1)final:若是对象数据成员被声明为final,但没有明确使用=指定值,表示延迟对象成员值的指定,在构造函数执行流程中,必定要有对该数据成员指定值得操做,不然编译错误。

(2)继承中的final:若class前使用了final,则这个类是末类,不能被继承。若方法被限定为final,子类也不能从新定义final方法了。

5.java.lang.Object:若是定义类时没有使用extends关键字定义继承任何类,则表明它继承java.lang.Object。即它是全部类的最上层父类。

6.垃圾收集:对于再也不有用的对象,JVM有垃圾收集机制,收集到的垃圾对象所占据的内存空间会被垃圾收集器释放。在执行流程中,没法经过变量参考的对象,就是GC认定的垃圾对象。

7.抽象类:重点经过例子体现继承思想。(代码包中有对应代码)

附加:总结补充

经过我对Java视频的复习,我将继承与多态相关知识点记录以下:


1.继承的优势:

(1)提升了代码的复用性。
(2)让类与类之间产生了关系,提供了另外一个特征多态的前提。

2.父类的由来:实际上是由多个类不断向上抽取共性内容而来的。java中对于继承,java只支持单继承。java虽然不直接支持多继承,可是保留了这种多继承机制,进行改良。

单继承:一个类只能有一个父类。
多继承:一个类能够有多个父类。

3.不支持多继承的缘由:当一个类同时继承两个父类时,两个父类中有相同的功能,那么子类对象调用该功能时,运行哪个呢?由于父类中的方法中存在方法体。可是java支持多重继承。A继承B,B继承C,C继承D。多重继承的出现,就有了继承体系。体系中的顶层父类是经过不断向上抽取而来的。它里面定义的该体系最基本最共性内容的功能。因此,一个体系要想被使用,直接查阅该系统中的父类的功能便可知道该体系的基本用法。那么想要使用一个体系时,须要创建对象。建议创建最子类对象,由于最子类不只可使用父类中的功能。还可使用子类特有的一些功能。

简单说:对于一个继承体系的使用,查阅顶层父类中的内容,建立最底层子类的对象。

4.子父类出现后,类中的成员的特色:

(1)成员变量:子父类中出现同样的属性时,子类类型的对象,调用该属性,值是子类的属性值。若是想要调用父类中的属性值,须要使用一个关键字:super 。

This:表明是本类类型的对象引用。
Super:表明是子类所属的父类中的内存空间引用。

注意:子父类中一般是不会出现同名成员变量的,由于父类中只要定义了,子类就不用在定义了,直接继承过来用就能够了。

(2)成员函数:当子父类中出现了如出一辙的方法时,创建子类对象会运行子类中的方法。好像父类中的方法被覆盖掉同样。因此这种状况,是函数的另外一个特性:覆盖(复写,重写)。当一个类的功能内容须要修改时,能够经过覆盖来实现。

(3)构造函数:发现子类构造函数运行时,先运行了父类的构造函数。缘由是子类的全部构造函数中的第一行,其实都有一条隐身的语句super();

注意:子类中全部的构造函数都会默认访问父类中的空参数的构造函数,由于每个子类构造内第一行都有默认的语句super(); 若是父类中没有空参数的构造函数,那么子类的构造函数内,必须经过super语句指定要访问的父类中的构造函数。若是子类构造函数中用this来指定调用子类本身的构造函数,那么被调用的构造函数也同样会访问父类中的构造函数。

5.继承的细节:

在方法覆盖时,注意两点:

子类覆盖父类时,必需要保证,子类方法的权限必须大于等于父类方法权限能够实现继承。不然,编译失败。
覆盖时,要么都静态,要么都不静态。 (静态只能覆盖静态,或者被静态覆盖)

6.继承的弊端:打破了封装性。对于一些类,或者类中功能,是须要被继承,或者复写的。此时则须要引进final来解决。

7.final特色:

这个关键字是一个修饰符,能够修饰类,方法,变量。
被final修饰的类是一个最终类,不能够被继承。
被final修饰的方法是一个最终方法,不能够被覆盖。
被final修饰的变量是一个常量,只能赋值一次。

其实这样的缘由的就是给一些固定的数据起个阅读性较强的名称。
不加final修饰不是也可使用吗?那么这个值是一个变量,是能够更改的。加了final,程序更为严谨。常量名称定义时,有规范,全部字母都大写,若是由多个单词组成,中间用 _ 链接。

8.抽象类 abstract:
抽象:不具体,看不明白。抽象类表象体现。
在不断抽取过程当中,将共性内容中的方法声明抽取,可是方法不同,没有抽取,这时抽取到的方法,并不具体,须要被指定关键字abstract所标示,声明为抽象方法。
抽象方法所在类必定要标示为抽象类,也就是说该类须要被abstract关键字所修饰。

9.抽象类的特色:

抽象方法只能定义在抽象类中,抽象类和抽象方法必须由abstract关键字修饰(能够描述类和方法,不能够描述变量)。
抽象方法只定义方法声明,并不定义方法实现。
抽象类不能够被建立对象(实例化)。
只有经过子类继承抽象类并覆盖了抽象类中的全部抽象方法后,该子类才能够实例化。不然,该子类仍是一个抽象类。

10.抽象类的细节:

(1)抽象类中是否有构造函数?有,用于给子类对象进行初始化。
(2)抽象类中是否能够定义非抽象方法?
能够。其实,抽象类和通常类没有太大的区别,都是在描述事物,只不过抽象类在描述事物时,有些功能不具体。因此抽象类和通常类在定义上,都是须要定义属性和行为的。只不过,比通常类多了一个抽象函数。并且比通常类少了一个建立对象的部分。
(3)抽象关键字abstract和哪些不能够共存?final ,	private , static 
(4)抽象类中可不能够不定义抽象方法?能够。抽象方法目的仅仅为了避免让该类建立对象。

chapter7 接口与多态

1.定义:关键字interface。接口中包含的成员,最多见的有全局常量、抽象方法。

注意:接口中的成员都有固定的修饰符。
成员变量:public static final
成员方法:public abstract
interface Inter{
   public static final int x = 3;
   public abstract void show();
}

3:接口中有抽象方法,说明接口不能够实例化接口的子类必须实现了接口中全部的抽象方法后,该子类才能够实例化。不然,该子类仍是一个抽象类。

4:类与类之间存在着继承关系,类与接口中间存在的是实现关系。继承用extends  ;实现用implements ;

5:接口和类不同的地方,就是,接口能够被多实现,这就是多继承改良后的结果。java将多继承机制经过多现实来体现。

6:一个类在继承另外一个类的同时,还能够实现多个接口。因此接口的出现避免了单继承的局限性。还能够将类进行功能的扩展。

7:其实java中是有多继承的。接口与接口之间存在着继承关系,接口能够多继承接口

接口都用于设计上,设计上的特色:(能够理解主板上提供的接口)

1:接口是对外提供的规则。
2:接口是功能的扩展。
3:接口的出现下降了耦合性。

抽象类与接口:

抽象类:通常用于描述一个体系单元,将一组共性内容进行抽取,特色:能够在类中定义抽象内容让子类实现,能够定义非抽象内容让子类直接使用。它里面定义的都是一些体系中的基本内容。

接口:通常用于定义对象的扩展功能,是在继承以外还需这个对象具有的一些功能。

抽象类和接口的共性:都是不断向上抽取的结果。

抽象类和接口的区别:

1:抽象类只能被继承,并且只能单继承。
接口须要被实现,并且能够多实现。
2:抽象类中能够定义非抽象方法,子类能够直接继承使用。
接口中都有抽象方法,须要子类去实现。
3:抽象类使用的是  is a 关系。
接口使用的 like a 关系。
4:抽象类的成员修饰符能够自定义。
接口中的成员修饰符是固定的。全都是public的。

在开发以前,先定义规则,A和B分别开发,A负责实现这个规则,B负责使用这个规则。至于A是如何对规则具体实现的,B是不须要知道的。这样这个接口的出现就下降了A和B直接耦合性。 

chapter8 异常

1.异常:就是不正常。程序在运行时出现的不正常状况。其实就是程序中出现的问题。这个问题按照面向对象思想进行描述,并封装成了对象。由于问题的产生有产生的缘由、有问题的名称、有问题的描述等多个属性信息存在。当出现多属性信息最方便的方式就是将这些信息进行封装。异常就是java按照面向对象的思想将问题进行对象封装。这样就方便于操做问题以及处理问题。

2.出现的问题有不少种,好比角标越界,空指针等都是。就对这些问题进行分类。并且这些问题都有共性内容好比:每个问题都有名称,同时还有问题描述的信息,问题出现的位置,因此能够不断的向上抽取。造成了异常体系

--------java.lang.Throwable

Throwable可抛出的。

       |--Error错误,通常状况下,不编写针对性的代码进行处理,一般是jvm发生的,须要对程序进行修正。

       |--Exception异常,能够有针对性的处理方式

不管是错误仍是异常,它们都有具体的子类体现每个问题,它们的子类都有一个共性,就是都以父类名才做为子类的后缀名

这个体系中的全部类和对象都具有一个独有的特色;就是可抛性。

可抛性的体现:就是这个体系中的类和对象均可以被throws和throw两个关键字所操做。

class  ExceptionDemo{
       public static void main(String[] args) {
//            byte[] buf = new byte[1024*1024*700];//java.lang.OutOfMemoryError内存溢出错误
       }
}

在开发时,若是定义功能时,发现该功能会出现一些问题,应该将问题在定义功能时标示出来,这样调用者就能够在使用这个功能的时候,预先给出处理方式。

3.标示方法:经过throws关键字完成,格式:throws 异常类名,异常类名...标示后,调用者在使用该功能时,就必需要处理,不然编译失败。

4.处理方式:一、捕捉;二、抛出。

对于捕捉:java有针对性的语句块进行处理。

try {
   须要被检测的代码;
}
catch(异常类 变量名){
   异常处理代码;
}
fianlly{
   必定会执行的代码;
}

--------------------------------------------------------

catch (Exception e) { //e用于接收try检测到的异常对象。
       System.out.println("message:"+e.getMessage());//获取的是异常的信息。
       System.out.println("toString:"+e.toString());//获取的是异常的名字+异常的信息。
       e.printStackTrace();//打印异常在堆栈中信息;异常名称+异常信息+异常的位置。
}

异常处理原则:功能抛出几个异常,功能调用若是进行try处理,须要与之对应的catch处理代码块,这样的处理有针对性,抛几个就处理几个。

特殊状况:try对应多个catch时,若是有父类的catch语句块,必定要放在下面。

throw 和throws关键字的区别:

throw用于抛出异常对象,后面跟的是异常对象;throw用在函数内。
throws用于抛出异常类,后面跟的异常类名,能够跟多个,用逗号隔开。throws用在函数上。

一般状况:函数内容若是有throw,抛出异常对象,并无进行处理,那么函数上必定要声明,不然编译失败。可是也有特殊状况。

异常分两种:

1:编译时被检查的异常,只要是Exception及其子类都是编译时被检测的异常。
2:运行时异常,其中Exception有一个特殊的子类RuntimeException,以及RuntimeException的子类是运行异常,也就说这个异常是编译时不被检查的异常。

编译时被检查的异常和运行时异常的区别:

编译被检查的异常在函数内被抛出,函数必需要声明,否编译失败。
声明的缘由:是须要调用者对该异常进行处理。
运行时异常若是在函数内被抛出,在函数上不须要声明。
不声明的缘由:不须要调用者处理,运行时异常发生,已经没法再让程序继续运行,因此,不让调用处理的,直接让程序中止,由调用者对代码进行修正。

定义异常处理时,功能内部若是出现异常,若是内部能够处理,就用try;若是功能内部处理不了,就必须声明出来,让调用者处理。

自定义异常:当开发时,项目中出现了java中没有定义过的问题时,这时就须要咱们按照java异常创建思想,将项目的中的特有问题也进行对象的封装。这个异常,称为自定义异常。

对于除法运算,0做为除数是不能够的。java中对这种问题用ArithmeticException类进行描述。对于这个功能,在咱们项目中,除数除了不能够为0外,还不能够为负数。但是负数的部分java并无针对描述。因此咱们就须要自定义这个异常。

自定义异常的步骤:

1:定义一个子类继承Exception或RuntimeException,让该类具有可抛性。

2:经过throw 或者throws进行操做。

异常的转换思想:当出现的异常是调用者处理不了的,就须要将此异常转换为一个调用者能够处理的异常抛出。

当异常出现后,在子父类进行覆盖时,有了一些新的特色:

1:当子类覆盖父类的方法时,若是父类的方法抛出了异常,那么子类的方法要么不抛出异常要么抛出父类异常或者该异常的子类,不能抛出其余异常。
2:若是父类抛出了多个异常,那么子类在覆盖时只能抛出父类的异常的子集。

注意:

若是父类或者接口中的方法没有抛出过异常,那么子类是不能够抛出异常的,若是子类的覆盖的方法中出现了异常,只能try不能throws。
若是这个异常子类没法处理,已经影响了子类方法的具体运算,这时能够在子类方法中,经过throw抛出RuntimeException异常或者其子类,这样,子类的方法上是不须要throws声明的。

常见异常:

一、脚标越界异常(IndexOutOfBoundsException)包括数组、字符串;

空指针异常(NullPointerException)

二、类型转换异常:ClassCastException

三、没有这个元素异常:NullPointerException

四、不支持操做异常;

异常要尽可能避免,若是避免不了,须要预先给出处理方式。好比家庭备药,好比灭火器。

chapter9 collection和maps

1.Map集合:

|--Hashtable底层是哈希表数据结构,是线程同步的。不能够存储null键,null值。

|--HashMap底层是哈希表数据结构,是线程不一样步的。能够存储null键,null值。替代了Hashtable.

|--TreeMap底层是二叉树结构,能够对map集合中的键进行指定顺序的排序。

Map集合存储和Collection有着很大不一样:

Collection一次存一个元素;Map一次存一对元素。

Collection是单列集合;Map是双列集合。

Map中的存储的一对元素:一个是键,一个是值,键与值之间有对应(映射)关系。

特色:要保证map集合中键的惟一性。

1,添加。

put(key,value):当存储的键相同时,新的值会替换老的值,并将老值返回。若是键没有重复,返回null。
void putAll(Map);

2,删除。

void clear():清空
value remove(key) :删除指定键。

3,判断。

boolean isEmpty():
boolean containsKey(key):是否包含key
boolean containsValue(value) :是否包含value

4,取出。

int size():返回长度
value get(key) :经过指定键获取对应的值。若是返回null,能够判断该键不存在。固然有特殊状况,就是在hashmap集合中,是能够存储null键null值的。
Collection values():获取map集合中的全部的值。

5,想要获取map中的全部元素:

原理:map中是没有迭代器的,collection具有迭代器,只要将map集合转成Set集合,可使用迭代器了。之因此转成set,是由于map集合具有着键的惟一性,其实set集合就来自于map,set集合底层其实用的就是map的方法。

把map集合转成set的方法:

Set keySet();
Set entrySet();//取的是键和值的映射关系。

Entry就是Map接口中的内部接口;

为何要定义在map内部呢?entry是访问键值关系的入口,是map的入口,访问的是map中的键值对。

1.取出map集合中全部元素的方式一:keySet()方法。

能够将map集合中的键都取出存放到set集合中。对set集合进行迭代。迭代完成,再经过get方法对获取到的键进行值的获取。

Set keySet = map.keySet();
Iterator it = keySet.iterator();
      while(it.hasNext()) {
            Object key = it.next();
            Object value = map.get(key);
            System.out.println(key+":"+value);
       }        

--------------------------------------------------------

2.取出map集合中全部元素的方式二:entrySet()方法。

Set entrySet = map.entrySet();
Iterator it = entrySet.iterator();
              while(it.hasNext()) {
                     Map.Entry  me = (Map.Entry)it.next();
                     System.out.println(me.getKey()+"::::"+me.getValue());
              }

--------------------------------------------------------

使用集合的技巧:

看到Array就是数组结构,有角标,查询速度很快。
看到link就是链表结构:增删速度快,并且有特有方法。addFirst; addLast; removeFirst(); removeLast(); getFirst();getLast();
看到hash就是哈希表,就要想要哈希值,就要想到惟一性,就要想到存入到该结构的中的元素必须覆盖hashCode,equals方法。
看到tree就是二叉树,就要想到排序,就想要用到比较。

比较的两种方式:

一个是Comparable:覆盖compareTo方法;

一个是Comparator:覆盖compare方法。

LinkedHashSet,LinkedHashMap:这两个集合能够保证哈希表有存入顺序和取出顺序一致,保证哈希表有序。

集合:当存储的是一个元素时,就用Collection。当存储对象之间存在着映射关系时,就使用Map集合。保证惟一,就用Set。不保证惟一,就用List。

------------------------------------------------------------------------------------------------

Collections它的出现给集合操做提供了更多的功能。这个类不须要建立对象,内部提供的都是静态方法。

静态方法:

Collections.sort(list);//list集合进行元素的天然顺序排序。
Collections.sort(list,new ComparatorByLen());//按指定的比较器方法排序。
class ComparatorByLen implements Comparator<String>{
     public int compare(String s1,String s2){
            int temp = s1.length()-s2.length();
            return temp==0?s1.compareTo(s2):temp;
     }
}
Collections.max(list); //返回list中字典顺序最大的元素。
int index = Collections.binarySearch(list,"zz");//二分查找,返回角标。
Collections.reverseOrder();//逆向反转排序。
Collections.shuffle(list);//随机对list中的元素进行位置的置换。

将非同步集合转成同步集合的方法:Collections中的  XXX synchronizedXXX(XXX);

List synchronizedList(list);

Map synchronizedMap(map);

原理:定义一个类,将集合全部的方法加同一把锁后返回。

Collection 和 Collections的区别:

Collections是个java.util下的类,是针对集合类的一个工具类,提供一系列静态方法,实现对集合的查找、排序、替换、线程安全化(将非同步的集合转换成同步的)等操做。
Collection是个java.util下的接口,它是各类集合结构的父接口,继承于它的接口主要有Set和List,提供了关于集合的一些操做,如插入、删除、判断一个元素是否其成员、遍历等。

chapter10 输入输出

IO流:用于处理设备上数据。

流:能够理解数据的流动,就是一个数据流。IO流最终要以对象来体现,对象都存在IO包中。

流也进行分类:

1:输入流(读)和输出流(写)。

2:由于处理的数据不一样,分为字节流和字符流。

①字节流:处理字节数据的流对象。设备上的数据不管是图片或者dvd,文字,它们都以二进制存储的。二进制的最终都是以一个8位为数据单元进行体现,因此计算机中的最小数据单元就是字节。意味着,字节流能够处理设备上的全部数据,因此字节流同样能够处理字符数据。

②字符流:由于字符每一个国家都不同,因此涉及到了字符编码问题,那么GBK编码的中文用unicode编码解析是有问题的,因此须要获取中文字节数据的同时+ 指定的编码表才能够解析正确数据。为了方便于文字的解析,因此将字节流和编码表封装成对象,这个对象就是字符流。只要操做字符数据,优先考虑使用字符流体系。

注意:流的操做只有两种:读和写。

流的体系由于功能不一样,可是有共性内容,不断抽取,造成继承体系。该体系一共有四个基类,并且都是抽象类。

字节流:InputStream  OutputStream

字符流:Reader  Writer

在这四个系统中,它们的子类,都有一个共性特色:子类名后缀都是父类名,前缀名都是这个子类的功能名称。

public static void main(String[] args) throws IOException { //读、写都会发生IO异常
            /*
            1:建立一个字符输出流对象,用于操做文件。该对象一创建,就必须明确数据存储位置,是一个文件。
            2:对象产生后,会在堆内存中有一个实体,同时也调用了系统底层资源,在指定的位置建立了一个存储数据的文件。
            3:若是指定位置,出现了同名文件,文件会被覆盖。
            */
            FileWriter fw = new FileWriter("demo.txt"); // FileNotFoundException
            /*
            调用Writer类中的write方法写入字符串。字符串并未直接写入到目的地中,而是写入到了流中,(实际上是写入到内存缓冲区中)。怎么把数据弄到文件中?
            */
            fw.write("abcde");
            fw.flush(); // 刷新缓冲区,将缓冲区中的数据刷到目的地文件中。
            fw.close(); // 关闭流,其实关闭的就是java调用的系统底层资源。在关闭前,会先刷新该流。
}

 

close()和flush()的区别:

flush():将缓冲区的数据刷到目的地中后,流可使用。

close():将缓冲区的数据刷到目的地中后,流就关闭了,该方法主要用于结束调用的底层资源。这个动做必定作。

--------------------------------------------------------------------------------------------------------------------

io异常的处理方式:io必定要写finally

FileWriter写入数据的细节:

1:window中的换行符:\r\n两个符号组成。 linux:\n。

2:续写数据,只要在构造函数中传入新的参数true。

3:目录分割符:window \\  /

 

public static void main(String[] args) {
                        FileWriter fw = null;
                        try {
                                    fw = new FileWriter("demo.txt",true);
                                    fw.write("abcde");
                        }
                        catch (IOException e ){
                                    System.out.println(e.toString()+"....");
                        }
                        finally{
                                    if(fw!=null)
                                                try{
                                                            fw.close();
                                                }
                                                catch (IOException e){                                                           
                                System.out.println("close:"+e.toString()); } } }

FileReader使用Reader体系,读取一个文本文件中的数据。返回 -1 ,标志读到结尾。

import java.io.*;
class  FileReaderDemo {
            public static void main(String[] args) throws IOException {
                        /*
                        建立能够读取文本文件的流对象,FileReader让建立好的流对象和指定的文件相关联。
                        */
                        FileReader fr = new FileReader("demo.txt");
                        int ch = 0;
                        while((ch = fr.read())!= -1) { //条件是没有读到结尾
                                    System.out.println((char)ch); //调用读取流的read方法,读取一个字符。
                        }
                        fr.close();
            }
}

读取数据的第二种方式:第二种方式较为高效,自定义缓冲区。

import java.io.*;
class FileReaderDemo2 {
            public static void main(String[] args) throws IOException {
                       FileReader fr = new FileReader("demo.txt"); //建立读取流对象和指定文件关联。
                        //由于要使用read(char[])方法,将读取到字符存入数组。因此要建立一个字符数组,通常数组的长度都是1024的整数倍。
                        char[] buf = new char[1024];
                        int len = 0;
                        while(( len=fr.read(buf)) != -1) {
                                    System.out.println(new String(buf,0,len));
                        }
                        fr.close();
            }
}

IO中的使用到了一个设计模式:装饰设计模式。

装饰设计模式解决:对一组类进行功能的加强。

包装:写一个类(包装类)对被包装对象进行包装;

包装类和被包装对象要实现一样的接口;
包装类要持有一个被包装对象;
包装类在实现接口时,大部分方法是靠调用被包装对象来实现的,对于须要修改的方法咱们本身实现;

字符流:

Reader用于读取字符流的抽象类。子类必须实现的方法只有 read(char[], int, int) 和 close()。

     |---BufferedReader从字符输入流中读取文本,缓冲各个字符,从而实现字符、数组和行的高效读取。 能够指定缓冲区的大小,或者可以使用默认的大小。大多数状况下,默认值就足够大了。

     |---LineNumberReader跟踪行号的缓冲字符输入流。此类定义了方法 setLineNumber(int)getLineNumber(),它们可分别用于设置和获取当前行号。

     |---InputStreamReader是字节流通向字符流的桥梁:它使用指定的 charset 读取字节并将其解码为字符。它使用的字符集能够由名称指定或显式给定,或者能够接受平台默认的字符集。

     |---FileReader用来读取字符文件的便捷类。此类的构造方法假定默认字符编码和默认字节缓冲区大小都是适当的。要本身指定这些值,能够先在 FileInputStream 上构造一个 InputStreamReader。

     |---CharArrayReader

     |---StringReader

Writer写入字符流的抽象类。子类必须实现的方法仅有 write(char[], int, int)、flush() 和 close()。

     |---BufferedWriter将文本写入字符输出流,缓冲各个字符,从而提供单个字符、数组和字符串的高效写入。

     |---OutputStreamWriter是字符流通向字节流的桥梁:可以使用指定的 charset 将要写入流中的字符编码成字节。它使用的字符集能够由名称指定或显式给定,不然将接受平台默认的字符集。

     |---FileWriter用来写入字符文件的便捷类。此类的构造方法假定默认字符编码和默认字节缓冲区大小都是可接受的。要本身指定这些值,能够先在 FileOutputStream 上构造一个 OutputStreamWriter。

     |---PrintWriter

     |---CharArrayWriter

     |---StringWriter

字节流:

InputStream是表示字节输入流的全部类的超类。

     |--- FileInputStream从文件系统中的某个文件中得到输入字节。哪些文件可用取决于主机环境。FileInputStream 用于读取诸如图像数据之类的原始字节流。要读取字符流,请考虑使用 FileReader。

     |--- FilterInputStream包含其余一些输入流,它将这些流用做其基本数据源,它能够直接传输数据或提供一些额外的功能。

     |--- BufferedInputStream该类实现缓冲的输入流。

     |--- Stream

     |--- ObjectInputStream

     |--- PipedInputStream

OutputStream此抽象类是表示输出字节流的全部类的超类。

     |--- FileOutputStream文件输出流是用于将数据写入 FileFileDescriptor 的输出流。

     |--- FilterOutputStream此类是过滤输出流的全部类的超类。

     |--- BufferedOutputStream该类实现缓冲的输出流。

     |--- PrintStream

     |--- DataOutputStream

     |--- ObjectOutputStream

     |--- PipedOutputStream

缓冲区是提升效率用的:

BufferedWriter是给字符输出流提升效率用的,那就意味着,缓冲区对象创建时,必需要先有流对象。明确要提升具体的流对象的效率。

       FileWriter fw = new FileWriter("bufdemo.txt");
       BufferedWriter bufw = new BufferedWriter(fw);//让缓冲区和指定流相关联。
       for(int x=0; x<4; x++){
              bufw.write(x+"abc");
              bufw.newLine(); //写入一个换行符,这个换行符能够依据平台的不一样写入不一样的换行符。
              bufw.flush();//对缓冲区进行刷新,可让数据到目的地中。
       }
       bufw.close();//关闭缓冲区,其实就是在关闭具体的流。

BufferedReader

       FileReader fr = new FileReader("bufdemo.txt");
       BufferedReader bufr  = new BufferedReader(fr);
       String line = null;
       while((line=bufr.readLine())!=null){  //readLine方法返回的时候是不带换行符的。
              System.out.println(line);
       }
       bufr.close();

流对象:其实很简单,就是读取和写入。可是由于功能的不一样,流的体系中提供N多的对象。那么开始时,到底该用哪一个对象更为合适呢?这就须要明确流的操做规律。

流的操做规律:

1,明确源和目的。

数据源:就是须要读取,可使用两个体系:InputStream、Reader;
数据汇:就是须要写入,可使用两个体系:OutputStream、Writer;

2,操做的数据是不是纯文本数据?

            若是是:数据源:Reader

                       数据汇:Writer

            若是不是:数据源:InputStream

                          数据汇:OutputStream

3,虽然肯定了一个体系,可是该体系中有太多的对象,到底用哪一个呢?

明确操做的数据设备。

数据源对应的设备:硬盘(File),内存(数组),键盘(System.in)

数据汇对应的设备:硬盘(File),内存(数组),控制台(System.out)。

4,须要在基本操做上附加其余功能吗?好比缓冲。若是须要就进行装饰。

转换流特有功能:转换流能够将字节转成字符,缘由在于,将获取到的字节经过查编码表获取到指定对应字符。

转换流的最强功能就是基于 字节流 + 编码表 。没有转换,没有字符流。

发现转换流有一个子类就是操做文件的字符流对象:

InputStreamReader

            |--FileReader

OutputStreamWriter

            |--FileWrier

想要操做文本文件,必需要进行编码转换,而编码转换动做转换流都完成了。因此操做文件的流对象只要继承自转换流就能够读取一个字符了。

可是子类有一个局限性,就是子类中使用的编码是固定的,是本机默认的编码表,对于简体中文版的系统默认码表是GBK

FileReader fr = new FileReader("a.txt");
InputStreamReader isr = new InputStreamReader(new FileInputStream("a.txt"),"gbk");

以上两句代码功能一致,

若是仅仅使用平台默认码表,就使用FileReader fr = new FileReader("a.txt"); //由于简化。

若是须要制定码表,必须用转换流。

转换流 = 字节流+编码表。

转换流的子类File = 字节流 + 默认编码表。

凡是操做设备上的文本数据,涉及编码转换,必须使用转换流。

chapter 12 Lambda

这部份内容书上讲的很详细不少代码能够用来参照,知识点就不列举了。另外因为这个是JDK 8的新特性,我在网上找了其余一些探究讲解,能够用来参考。

连接以下:

http://developer.51cto.com/art/201404/435591.htm

chapter 14 NIO和NIO2

这部份内容我至今看的不是很懂,只是看了书上内容反复看了代码,可是实际上并不能理解多少。网上也能看到一些资料,可是对本身启发也不是很大= =。还得继续研读。

 

总结

这六个章节是我负责来敲代码和作记录的部分。因为自身的基础和对一些模块的学习欠缺致使我看起来也很吃力。在寒假扣除掉不少没法避免的时间后,我只能算是勉勉强强看了下来。可是后面部分对我来讲是真正陌生的,看起来理解慢,内容新,难度又大。实在是没法对本身寒假的学习感到满意。我以为这真的须要认真检讨。有的部分看起来反反复复看,也没有什么真正学到的,真正记在脑子里的。我想这对于没有Java基础的同窗们来讲学起来可能要更加困难。所以还须要花更多的时间来精读这本教材。经过对之前学过部分的Java资料对比,我发现这本教材讲的很详细,也很简明易懂。有不少代码能够借助理解。这正是我对读这本书的动力所在。我总感受这本书的讲解风格很适合我来学习新的知识。所以,我会在和新同窗们一块儿学习的过程当中再去巩固本身的知识。

相关文章
相关标签/搜索