第十五章 泛型、第十六章数组、第十八章 JAVA I/O 系统

一般的类和方法,只能使用具体的类型:要么是基本类型,要么是自定义的类。如果要编写可以应用于多种类型的代码,这种刻板的限制对代码的束缚就会很大。


1. 简单泛型

  • 泛型的意思就是 : 适用于许多的类型。
  • 元组(数据传送对象,信使):将一组对象直接打包存储于其中的一个单一对象,这个容器允许读取其中元素,但是不允许向其中存放新的对象。通常,元组可以具有任意长度,同时元组中的对象还可以是不同类型。

    public class TwoTuple<A,B> {
    public final A first ;
    public final B second ;
    public TwoTuple(A a , B b){
      first = a;
      second = b ;
    }
    public String toString(){
      return "(" + first + "," + second + ")" ;
    }
    }
    
    public class TupleTest{
    static TwoTuple<String,Integer> f(){
      return new TwoTuple<String,Integer>("hi",47);
    }
    public static void main(){
      TwoTuple<String,Integer> ttsi = f();
      System.out.println(ttsi) ;
    }
    }
  • 有了泛型,可以很容易的创建元组,令其返回一组任意类型的对象。final 声明可以保护 public 元素,在对象被创建出来之后,声明为 final 的元素便不能被再赋予其他值了。

2. 泛型接口

  • 泛型可以应用于接口,例如生成器( gennerator ) ,这是一种专门负责创建对象的类。实际上,这是工厂方法设计模式的一种,不过当使用生成器创建新的对象的时候,他不需要任何参数,但是工厂方法一般需要参数,也就是说,生成器无需额外的信息,就知道如何创建新对象。
  • 一般而言,一个生成器只定义一个方法,用以产生新的对象。

3. 泛型方法

  • 是否拥有泛型方法,与其所在的类是否是泛型没有任何关系。泛型方法使得该方法可以独立于类而产生变化。
  • 要使用泛型方法,需要将泛型参数列表置于返回值之前。
  • Class.getTypeParameters() 将返回一个 “ TypeVariable ” 对象数组,表示有泛型声明所声明的类型参数。
  • 在泛型代码内部, 你无法获得任何有关泛型参数类型的信息。
  • List 、 List 在运行时事实上都是相同的类型。这两种形式都被擦出成他们的 “ 原生 ” 类型 , List 。
  • 因为擦除在与方法体中移除了类型信息,所以在运行时的问题就是边界:即对象进入和离开方法的地点。
  • 擦除丢失了在泛型代码中执行某些操作的能力,任何在运行时,需要知道确切类型的操作都将无法工作。

4. 通配符

  • <? extends xx>
  • 超类通配符 <? super extends MyClass> <? super T>

5. 问题

  • 任何基本类型都不能作为类型参数。但是自动包装可以解决。自动包装不能用于数组。

6. 混型

  • 混型最基本的概念是混合多个类的能力,以产生一个可以表示混型中的所有类型的类。

第十六章 数组

你可以创建并组装他们,通过使用整型索引值访问他们的元素。


1. 数组为什么特殊

  • 数组和其他种类的容器的区别有三方面:效率、类型、保存基本类型的能力。
  • 在 java 中,数组是一种效率最高的存储和随机访问对象引用序列的方式。数组就是一个简单的线性序列,这使得元素访问非常快速。但是为这种速度所付出的代价就是数组对象的大小被固定,并且在其生命周期中不可更改。
  • 数组可以持有基本包装类型,泛型之前的·容器则不能。

2. 数组是第一级对象

  • 无论使用哪种类型的数组,数组标识符其实只是一个引用,指向在堆中创建的一个真是的对象。这个数组对象用以保存指向其它对象的引用。
  • “ [] ” 是访问数组对象的唯一方式。 “ length ” 只表示数组可以容纳多少个元素。

3. Arrays实用功能

  • Arrays.fill() :只能用同一个值填充各个位置。针对对象就是复制同一个引用进行填充。
  • Arrays.equals() 用于比较两个数组是否相等
  • Arrays.deepEquals() 用于比较多维数组
  • Arrays.sort() 用于对数组排序
  • Arrays.binarySearch() 用于在已经排序的数组中查找元素
  • Arrays.toString() 产生数组的 Sring 表示
  • Arrays.hashCode() 产生数组的散列码
  • Arrays.asList() 接受任意的序列或数组作为其参数,并将其转变为 List 容器。
  • System.arraycopy() 复制数组
  • 浅复制 ( shallow copy ) 只是复制了对象的引用
  • 实现 java.lang.Comparable 接口,使类具有比较能力,这个接口只有一个 compareTo() 方法,接受另一个 Object 作为参数,如果当前对象小于参数返回负值,相等返回零,当前对象大于参数返回正值。

第十八章 Java I/O 系统

对程序设计者来说,创建一个好的输入、输出(I/O)系统是一项艰难的任务


1. File 类

它既能代表一个特定文件的名称,又能代表一个目录下的一组文件的名称。


1.1 目录列表器

  • 查看一个目录列表的方法:

    • 调用不带参数的 list() 方法,可以获得此 File 对象包含的全部列表
    • 使用目录过滤器,获取有限制的文件。
  • 使用 java.utils.Arrays.sort() 和 String.CASE_INSENSITIVE.ORDERComparator 对查出的结果进行排序。

1.2 目录实用工具

  • 在文件集上执行操作.

2. 输入和输出

  • 编程语言的 I/O 类库中常使用 流 这个抽象概念,它代表具有任何有能立产生数据源对象或者是有能力接收数据的接收端对象。“ 流 ” 屏蔽了实际的 I/O 设备处理数据的细节。
  • 任何自 InputStream 或者 Reader 派生而来的类都含有 read() 基本方法。
  • 任何自 OutputStream 或者 Writer 派生而来的类都含有 write() 方法。

3. 添加属性和有用的接口

  • FilterInputStream 和 FileOutputStream 是用来提供装饰器类接口以控制特定输入流和输出流的两个类。

4. 输入文件

  • 如果想要打开一个文件用于字符输入,可以使用 String 或者 File 对象作为文件名的 FileInputReader 。为了提高速度,希望对文件进行缓冲,可以使用 BufferedReader 构造器 ,提供了 readLine() 方法,当期返回 null 的时候 ,就说明到达了文件的末尾。
  • BufferedInputaFile.read() 读入的 String 结果被用来创建一个 StringReader,然后调用 read() 读取每一个字符。

    //xxx
    StringReader in = new StringReader(BufferedInputFile.read("xxx.java")) ;
    int c ;
    while((c = in.read()) != -1){
    System.out.println((char)c);
    }
    //xx
    //read()  是以 int 形式返回下一字节,因此必须类型转换为 char 才能正确打印。
    
  • FileWriter 对象可以向文件写入数据。
    java
    ///xxx
    BufferReader in = new BufferReader(new StringReader(BufferedInputFile.read("xxx.java"))) ;
    PrintWriter out = new PrintWriter(new BufferedWriter(new FileWriter(file))) ;
    int linrCount = 1 ;
    String s ;
    while((s = in.readLine()) !=null ){
    System.out.println(lineCount++ +":"+ s) ;
    }
    out.close() ;System.out.println(BufferedInputFile.read(file)) ;


5. 标准I/O

  • 将 System.in 包装成 BufferedReader 来使用这要求我们必须用 InputStreamReader 把 System.in 转换成 Reader 。

    //xxx
    BufferedReader stdin = new BufferReader(new InputStreamReader(System.in)) ;
    String s ;
    while((s == stdin.readLine()) != null && s.length()!=0){
    System.out.println(s);
    }
    //xxx
  • System.out 是一个 PrintStream ,PrintStream 是一个 OutPutStream 。

    java
    PrintWriter out = new PrintWriter(System.out,true) ;
    System.out.println("Hello,Word") ;


由于时间原因,后面几章做的比你很少,其实也没怎么认真看,以后有机会再补充吧,这本书第二遍告以段落。


由本人从 Thinking in java ( java 编程思想 ) 整理而来

最后修改:2018 年 07 月 15 日
哇卡哇卡