Java提升2

[toc]

一. Java集合类详解

  1. Connection接口
  2. 集合可以理解为一个动态的对象数组,不同的是集合中的对象内容可以任意扩充
  3. 集合的特点:
    性能高
    容易扩展和修改
  4. Collection的常用子类
    List
    Set
    Queue
  5. List接口

    1. List接口可以存放任意的数据,而且在List接口中内容是可以重复的
    2. List接口常用子类:
      ArrayList
      Vector
    3. 常用操作:
      判断集合是否为空:boolean isEmpty()
      查找指定的对象是否存在:int indexOf(Object o)
      |比较|ArrayList|Vector|
      |-|-|-|
      |推出时间|JDK1.2之后推出|JDK1.0推出|
      |性能|采用异步处理方式,性能高|采用同步处理方式,性能低|
      |线程安全|属于非线程安全|属于线程安全|
  6. Set接口

    1. Set接口中不能加入重复元素,但是可以排序
    2. Set接口常用子类
      散列存放:HashSet
      有序存放:TreeSet
  7. Iterator接口
    1. 集合输出的标准操作:
      标准做法,使用Iterator接口
    2. 操作原理:
      Iterator是专门的迭代输出接口,迭代输出就是将元素一个个进行判断,判断其是否有内容,如果有内容则把内容取出。
  8. Map接口
    1. 保存形式:
      Key—>value的方式保存
    2. 常用子类:
      HashMap:无序存放,key不允许重复(非线程安全的)
      Hashtable:无序存放,key不允许重复(线程安全的)

二. Java中的IO操作

  1. 作用:
    IO也写作“I/O”,可理解为In和Out,即输入与输出。所以,IO体系的基本功能就是:读和写。

  2. IO流

    • 作用:读写设备上的数据,硬盘文件、内存、键盘、网络…
    • 根据数据的走向,可分为:输入流、输出流
    • 根据处理的数据类型,可分为:字节流、字符流
  3. 字节流和字符流

    • 字节流可以处理所有类型的数据,如MP3,图片、文字、视频等。在读取时,读到一个字节就返回一个字节。
    • 在java中对应的类都以“Stream”结尾。

    • 字符流仅能处理纯文本数据,如txt文本等。在读取时,读到一个或者多个字节,先查找指定的编码表,然后将查到的字符返回。

    • 在Java中对应的类都以“Reader”或“Writer” 结尾

  4. 字符、字节和编码

字节(Byte)

  • 字节是通过网络传输信息或再硬盘或内存中存储信息的单位,是计算机信息技术用于计量存储容量和传输容量的一种计量单位。
  • 1个字节等于8位二进制,即一个8位二进制数,是一个狠具体的存储空间。
    如0x01,0x45,0xFA,…

字符(Char)

  • 字符是人们使用的几号,抽象意义上的一个符号。
    如’1’,’中’,’a’,’¥’,’$’,…

字符集(Charset)

“字符集”也称为“编码”。

三者的区别,请看下表:
javaByteCharDif

  1. 使用字节流读写数据
  • 使用fileInputStream和fileOutputStream来进行文件的拷贝
public static void main(String[] args) {
    try {
        FileInputStream fileInputStream = new FileInputStream("Java01/text.txt");
        FileOutputStream fileOutputStream = new FileOutputStream("Java01/newText.txt");

        byte input[] = new byte[50];

        while (fileInputStream.read(input) != -1) {
            fileOutputStream.write(input);
        }

        fileInputStream.close();
        fileOutputStream.close();

    } catch (FileNotFoundException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    }
}


  1. 使用带缓冲的字节流读写数据
public static void main(String[] args){
    try {
        FileInputStream fileInputStream = new FileInputStream("Java01/text.txt");
        BufferedInputStream bufferedInputStream = new BufferedInputStream(fileInputStream,1000000);//设置缓冲区的大小

        //大型文件对应的数组可以大一些,小文件对应的数组小一些
        byte input[]  = new byte[100000];
        int count = 0;
        long before = System.currentTimeMillis();               //读取之前的时间
        while (bufferedInputStream.read(input)!=-1){
            count++;
        }
        bufferedInputStream.close();
        fileInputStream.close();
        System.out.println(System.currentTimeMillis()-before+"ms"); //读取之后和之前的差值
        System.out.println("都去了"+ count +"次");


    } catch (FileNotFoundException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    }
}

说明:通过多次调试缓冲区和字节数组的大小,来寻找文件读取效率最高的数据。

  1. 使用字符流读写数据
    同样是,进行文件拷贝,现在使用字符流来读写数据,实例如下:
public static void main(String[] args) {
        try {
            FileInputStream fileInputStream = new FileInputStream("Java01/text.txt");
            FileOutputStream fileOutputStream = new FileOutputStream("Java01/newText.txt");
            InputStreamReader inputStreamReader = new InputStreamReader(fileInputStream, "UTF-8");//InputStreamReader使用指定的 charset 读取字节并将其解码为字符。
            OutputStreamWriter outputStreamWriter = new OutputStreamWriter(fileOutputStream, "UTF-8");

            char input[] = new char[100];
            int l = 0;
            while ((l = inputStreamReader.read(input)) != -1) {
                outputStreamWriter.write(input, 0, l);          //将字符读入数组中的某一部分。
            }
//            while (inputStreamReader.read(input) != -1) {     //读入数组的的字符会存在偏移,即多读出字符
//                outputStreamWriter.write(input);
//            }

            outputStreamWriter.close();
            inputStreamReader.close();
            fileOutputStream.close();
            fileInputStream.close();


        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }


  1. 使用带有缓冲的字符流读写数据

即添加BufferedReader和BufferedWriter,会出现一个问题,就是写入文件的时候会丢弃换行符,可使用PrintWriter
PrintWriter实例化:

PrintWriter pw = new PrintWriter(outputStreamWriter,true);//实例化并强制自动刷新缓冲区数据


  1. FileReader与FileWriter
  • 使用FileReader和FileWriter来读写一些纯文本文件,读写以字符为基准的文件。用法同上述几种文件读出方式类似,不做赘述。


  1. RandomAccessFile随机文件读写

实例代码:
MultiwriterFile.java

package com.william.RandomAccessFileTest;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.RandomAccessFile;

/**
 * Created by william on 2016/11/25.
 */
public class MultiwriterFile {
    static File file = new File("Java01/text.txt");

    public static void main(String[] args) {
//        if (file.exists()) {
//            file.delete();
//        }
//        new WriteFile(file,1).start();
//        new WriteFile(file,2).start();
//        new WriteFile(file,3).start();
//        new WriteFile(file,4).start();
//        new WriteFile(file,5).start();

        try {
            RandomAccessFile randomAccessFile = new RandomAccessFile(file, "r");
            randomAccessFile.seek(300);
            byte input[] = new byte[20];
            randomAccessFile.read(input);
            String str = new String(input);
            System.out.print(str);
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }

    }

}

WriteFile.java

package com.william.RandomAccessFileTest;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.RandomAccessFile;

/**
 * Created by william on 2016/11/25.
 */
public class WriteFile extends Thread {
    File file;
    int block;
    int L = 100;

    public WriteFile(File file, int block) {
        this.file = file;
        this.block = block;
    }

    /**
     * 文件随机读取示意图:
     * 1                 2(100)            3                 4(300)            5
     * |-----------------|-----------------|-----------------|-----------------|--------
     * 0xL<-----100----->1xL
     */
    public void run() {
        try {
            RandomAccessFile randomAccessFile = new RandomAccessFile(file, "rw");
            randomAccessFile.seek((block - 1) * L);
            randomAccessFile.writeBytes("This is block" + block);
            for (int i=0;i<20;i++) {
                randomAccessFile.writeBytes("-");
            }
            randomAccessFile.writeBytes("\n");

        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

执行写操作,输出结果:

This is block1——————–
This is block2——————–
This is block3——————–
This is block4——————–
This is block5——————–

执行读操作输出结果:
输出:输出20个字节长度

This is block4——


  1. 使用Apache IO库操作IO与文件

对原始java对文件的操作做了封装,使用起来更加的方便,详细请看Apache的官方API文档。


三. Java多线程编程

  1. 线程与进程

线程:

  • 程序中的单独顺序的控制流
  • 新城本身依靠程序进行运行
  • 线程是程序中的顺序控制流,只能使用分配给程序的资源和环境

进程:

  • 执行中的程序
  • 一个进程可以包含一个或多个线程
  • 一个进程至少要包含一个线程

单线程:

  • 程序中只存在一个线程,实际上主方法就是一个主线程

多线程:

  • 多线程是在一个程序中运行多个任务
  • 多线程的目的是更好的利用cpu资源


  1. 线程的实现
  • 在java中,线程的实现有两种:
    ①. 继承Thread类
    ②. 实现Runnable接口
  • Thread类:
    Thread类是在java.lang包中定义的,继承Thread类必须重写run()方法
    定义格式:
class className extends Thread{
    run(){};
}

实例:

public class MyThread extends Thread {
    private String name;

    public MyThread(String name) {
        this.name = name;
    }

    @Override
    public void run() {
        for (int i = 0; i < 1000; i++) {
            System.out.println(name + ":" + i);
        }
        super.run();
    }
}

说明:当在主方法中使用Start启动线程时,我们可以看到两个线程时并行执行的,即谁先拿到cpu的资源,谁就执行,并不是顺序执行的。

看部分输出结果:


B:25
B:26
B:27
B:28
B:29
A:0
B:30
A:1
A:2
A:3

  • Runnable接口

实现Runnable接口中的run方法,与Thread的run方法一样,在主方法中调用时,如下调用:

MyRunnable r = new MyRunnable("A");
Thread t = new Thread(r);
t.start();


  1. 线程的状态

线程也有固定的操作状态:

  • 创建状态:准备好了一个多线程的对象
  • 就绪状态:调用了start()方法,等待cpu进行调度
  • 运行状态:执行run()方法
  • 阻塞状态:暂时停止执行,可能将资源交给其他线程使用
  • 终止状态(死亡状态):线程销毁


  1. 线程的常用方法
  • 取得线程名称
    getName()
  • 取得当前线程对象
    currentThread()
  • 判断线程是否启动
    isAlive()
  • 线程的强行运行
    join()
  • 线程的休眠
    sleep()
  • 礼让
    yield()


  1. 线程的优先级

优先级顺序设置:

  • 1-MIN_PRIORITY
  • 10-MAX_PRIORITY
  • 5-NORM_PRIORITY
    如果什么都不设置默认值是5


  1. 同步与死锁
  • 同步代码块
    在代码块上加上“synchronized”关键字,则此代码块就称为同步代码块
  • 同步代码块格式:
    synachronized(同步对象){
    需要同步的代码块;
    }
  • 同步方法
    除了代码块可以同步,方法也是可以同步的
  • 方法同步格式:
    synchronized void 方法名称(){}
    同步实例:
class MyThreadDemo implements Runnable {

    private int ticket = 5;

    public void run() {
        for (int i = 0; i < 10; i++) {
            tell();
        }
    }

    public synchronized void tell() {
        if (ticket > 0) {
            try {
                Thread.sleep(500);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("车票:" + ticket--);
        }
    }
}

public class synchronizedtest {
    public static void main(String[] args) {
        MyThreadDemo m = new MyThreadDemo();
        Thread t1 = new Thread(m);
        Thread t2 = new Thread(m);
        Thread t3 = new Thread(m);
        t1.start();
        t2.start();
        t3.start();
    }
}

而死锁,就相当与两个人耍赖皮,比如说:张三有十块钱,李四有一本书,张三说,你先把书给我,我就给你钱,李四说你先给我钱,我就给你书,两个人互不想让,就会陷入等待,就会出现死锁的状况。

  1. 线程的生命周期
    不解释,上图:
    threadLife

四. Java中的HTTP通信

  1. 使用Http的Get方法读取网络数据

看下面博客吧,视频上讲的挺散,但是要感谢视频的老师,同时感谢博客的博主。:)
http://blog.csdn.net/luckyzhoustar/article/details/50259209

  1. 使用Http的Post方式与网络交互通信

啥都不说了,还是博客文章:
http://blog.csdn.net/thl331860203/article/details/51783434

  1. 使用HttpClient进行Get方式通信

使用Apache的HttpClient的jar包,具体的操作,自己网上查去吧,不像写了。

  1. 使用HttpClient进行Post方式通信

使用Apache的HttpClient的jar包,具体的操作,自己网上查去吧,不像写了。
做参考吧:
https://www.oschina.net/code/snippet_1591393_46723


五. Java中内部类,匿名内部类理解

http://blog.csdn.net/zzjjiandan/article/details/9189943

一般来说,有4种内部类:常规内部类、静态内部类、局部内部类、匿名内部类。

  1. 在局部内部类前不能用修饰符public和private,protected.
  2. 可以定义与外部类同名的变量
    如果内部类没有与外部类同名的变量,在内部类中可以直接访问外部类的实例变量

    如果内部类中有与外部类同名的变量,直接用变量名访问的是内部类的变量,用this.变量名访问的也是内部类变量.

    用外部类名.this.内部类变量名访问的是外部类变量

  3. 不可以定义静态变量和方法
  4. 可以访问外部类的局部变量(即方法内的变量),但是变量必须是final的
  5. 可以访问外部类的所有成员

实例:
http://blog.csdn.net/l294265421/article/details/46583475

小插曲:关于类的实例化顺序

1.在实例化一个类的对象时,先要实例化该类的成员变量,再执行该类的构造函数。

  1. 在实例化一个类的成员变量时,先要实例化静态成员变量,再实例化非静态成员变量。
  2. 一个类的静态成员变量只实例化一次,即只有一个拷贝,在该类的所有对象中共享。
  3. 执行一个类的静态成员函数时,该类的对象并没有生成,因此,只会实例化该类的静态成员变量,而不会实例化非静态成员变量,也不会执行构造函数。

最好自己写一个小的实例,然后自己debugger一下,这样更容易理解上述的总结,可以用下面的小实例:

class A{
    private int a = 10;
    private static int AA = 100;

    public A(int a) {
        this.a = a;
    }

    public void printA(){
        System.out.println("this is A");
    }

    public static void printText(){
        System.out.println("come here!");
    }

}

public class newclasstest {

    public static void main(String[] args){
        A.printText();
        A a = new A(22);
        a.printA();
    }

}

   转载规则


《Java提升2》 Will 采用 知识共享署名 4.0 国际许可协议 进行许可。
 上一篇
Java之自动拆装箱及享元模式应用 Java之自动拆装箱及享元模式应用
首先,来说一下关于编译器蜜糖(compiler suger)的问题,它给我们带来便利的同时,也埋下了一些陷阱,像foreach的增强,自动拆装箱等,本节一起来学习一下蜜糖之一的自动拆装箱机制。 [toc] 一. 静态导入 静态导入 i
2016-12-29
下一篇 
Java提升1 Java提升1
[toc] 一.WebService入门 Java中的xml操作 XML和HTML区别 XML被设计为传输和存储数据,其焦点是数据的内容 HTML被设计用来显示数据,起焦点是数据的外观 HTML旨在显示信息,而XML旨在传输信息
2016-11-24
  目录