目錄
I/O編程
I/O
- 簡單介紹一下Java中的輸入 / 輸出系統
- 輸入輸出是對於磁盤和內存來說的,程序的運行是在內存中,所以要將數據輸入到內存。處理完畢的數據需要保存,便輸出到磁盤。
- Java 中將數據的輸入輸出抽象爲流,流是一組有順序的,單向的,有起點和終點的數據集合
- 按照數據單元分爲字節流和字符流
- 字節流:以 8 位(即 1 byte,8 bit)作爲一個數據單元,數據流中最小的數據單元是字節;
使用InputStream/OutputStream
類實現 - 字符流:以 16 位(即 1 char,2 byte,16 bit)作爲一個數據單元,數據流中最小的數據單元是字符, Java 中的字符是 Unicode 編碼,一個字符佔用兩個字節
使用Reader/Writer
類實現
- Reader/Writer本質上是一個能自動編解碼的InputStream/OutputStream
- JDK提供的
java.io
是同步IO,java.nio
是異步IO
- 我們較常使用的IO類
- 如果有興趣可以讀一下源碼
- 先從目錄/文件說起
File
- java.io.File表示文件系統的一個文件或者目錄
// 構造方法
File f = new File("C:\\Windows\\notepad.exe") // windows下使用 \\
import java.io.File;
import java.io.IOException;
public static void main(String[] args) throws IOException {
File win = new File("C:\\Windows");
System.out.println(win.isDirectory()); // true
File notepad = new File("C:\\Windows\\notepad.exe");
System.out.println(notepad.isFile()); // true
File dir = new File("C:\\abc\\xyz");
System.out.println(dir.mkdir()); // -> mkdirs
File readme = new File("./src/readme.txt");
System.out.println(readme.isFile()); // false
System.out.println(readme.getAbsolutePath());
System.out.println(readme.getCanonicalPath());
}
InputStream
- java.io.InputStream是所有輸入流的超類
public static void main(String[] args) throws IOException {
// 推薦寫法,try(resource)保證流被正確關閉
try (InputStream input = new FileInputStream("readme.txt")) {// FileInputStream文件流
int n;
byte[] buffer = new byte[1000]; // 建立buffer緩衝區
// 一次儘可能多的將字節讀入緩衝區,但不會超過;需要使用while保證所有字節讀出
while ((n = input.read(buffer)) != -1) {
System.out.println(n); // 返回字節數
// System.out.println(buffer);
}
}
}
OutputStream
- java.io.OutputStream是所有輸出流的超類
public static void main(String[] args) throws IOException {
try (OutputStream output = new FileOutputStream("output.txt")) {// FileOutputStream文件流
byte[] b1 = "Hello".getBytes("UTF-8");
output.write(b1);
byte[] b2 = "你好".getBytes("UTF-8");
output.write(b2);
}
}
ByteArrayOutputStream
/ByteArrayInputStream
在內存中模擬字節流的輸出輸入
Filter模式
- InputStream可以被繼承從而擴展出很多子類。出現子類爆炸的現象
- 爲了避免這種情況我們使用組合功能而非繼承的設計模式,稱爲Filter模式(或Decorator)
- 通過少量的類組合出複雜的功能
- FileStream與FilterStream相互配合,包裝所需的類
- 可以參考如下包裝形式理解:
import java.io.BufferedInputStream;
import java.io.ByteArrayOutputStream;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.zip.GZIPInputStream;
public static void main(String[] args) throws IOException {
try (InputStream input = new GZIPInputStream(new BufferedInputStream(new FileInputStream("test.txt.gz")))) {// 最後向上轉型爲InputStream
ByteArrayOutputStream output = new ByteArrayOutputStream();
byte[] buffer = new byte[1024];
int n;
while ((n = input.read(buffer)) != -1) {
output.write(buffer, 0, n);
}
byte[] data = output.toByteArray();
String text = new String(data, "UTF-8");
System.out.println(text);
}
}
ZipInputStream
是一種FilterInputStream,配合FileInputStream可以直接讀取zip內容- ZipOutputStream同理
- 下面是ZipStream的基本用法,也是FileStream與FilterStream組合的例子
public static void main(String[] args) throws IOException {
try (ZipInputStream zip = new ZipInputStream(new BufferedInputStream(new FileInputStream("test.jar")))) { // 包裝
ZipEntry entry = null;
while ((entry = zip.getNextEntry()) != null) {// zip不能向上轉型爲InputStream
if (entry.isDirectory()) { // 如果是目錄
System.out.println("D " + entry.getName());
} else {
System.out.println("F " + entry.getName() + " " + entry.getSize());
printFileContent(zip);
}
}
}
}
static void printFileContent(ZipInputStream zip) throws IOException { // 打印文件內容
ByteArrayOutputStream output = new ByteArrayOutputStream();// 內存中模擬字節流
byte[] buffer = new byte[1024];
int n;
while ((n = zip.read(buffer)) != -1) {
output.write(buffer, 0, n);
}
byte[] data = output.toByteArray();
System.out.println(" size: " + data.length);
}
classpath資源文件
- Java存放.class的目錄或者jar包可以包含任意類型的其他文件(jar包主要是壓縮的class文件和輔助資源)
- 從classpath讀取文件可以避免不同環境下(Windows/Linux)文件路徑不一致的問題
- Class對象的
getResourceAsStream()
可以從classpath讀取資源
public static void main(String[] args) throws IOException {
// 從classpath讀取配置文件:
try (InputStream input = Main.class.getResourceAsStream("/conf.properties")) {// src根目錄下
if (input != null) { // 需要檢查返回的InputStream是否爲null
System.out.println("Read /conf.properties...");
Properties props = new Properties();// 配置讀取器
props.load(input);
System.out.println("name=" + props.getProperty("name"));
}
}
// 從classpath讀取txt文件:
String data = "/com/hello/sample/data.txt";
try (InputStream input = Main.class.getResourceAsStream(data)) {
if (input != null) { // 要檢查是否爲null
System.out.println("Read " + data + "...");
// Java流讀取
BufferedReader reader = new BufferedReader(new InputStreamReader(input, "UTF-8"));
System.out.println(reader.readLine());
} else {
System.out.println("Resource not found: " + data);
}
}
}
序列化
- 序列化是將一個對象變成二進制文件byte[]
- 可序列化的java對象必須實現java.io.Serializable接口
- 類似Serializable這樣的空接口被稱爲“標記接口”(marker interface)
- 反序列化時JVM不調用構造方法
// Main
public static void main(String[] args) throws IOException, ClassNotFoundException {
String dataFile = "saved.data";
try (ObjectOutputStream output = new ObjectOutputStream(
new BufferedOutputStream(new FileOutputStream(dataFile)))) {
// 依次寫入 int, String, Person:
output.writeInt(999);
output.writeUTF("Hello, world!");
output.writeObject(new Person("Xiao Ming"));
}
System.out.println("Read...");
try (ObjectInputStream input = new ObjectInputStream(new BufferedInputStream(new FileInputStream(dataFile)))) {
// 依次讀入 int, String, Person:
System.out.println(input.readInt());
System.out.println(input.readUTF());
Person p = (Person) input.readObject();
System.out.println(p);
}
}
public class Person implements Serializable {// 必須實現此接口
// 可以藉助IDEA設置serialVersionUID作爲版本號(可選),這樣我們即使刪除了寫入數據的步驟,可以記住UID讀取序列化文件!
private final String name;
public Person(String name) {
System.out.println(name);// 反序列化時不調用構造方法
this.name = name;
}
public String getName() {
return name;
}
@Override
public String toString() {
return "(Person: " + name + ")";
}
}
- Java的序列化機制適用於Java,如果要與其他語言交互,必須 使用通用的序列化方法例如 json
Reader
- Reader是所有字符輸入流的超類,它與InputStream的區別:
- Reader實際上是基於InputStream構造的,FileReader內部持有一個FileInputStream
- 可以通過
InputStreamReader()
將任意的InputStream轉化爲Reader
public static void main(String[] args) throws IOException {
// try (Reader reader = new InputStreamReader(new FileInputStream("readme.txt"), "UTF-8"));// 指定編碼
try (Reader reader = new FileReader("readme.txt")) {// 無法指定編碼
int n;
while ((n = reader.read()) != -1) {
System.out.println((char) n);
}
}
}
CharArrayReader
/CharArrayWriter
在內存中模擬字符流輸入輸出- 和InputStream一樣也是阻塞(blocking)的
Writer
- Writer是所有字符輸入流的超類,它與OutputStream的區別:
- 好了不想多說類比一下吧!
- 都要使用
try(resource)
格式保證正常關閉哦!
時間和日期
- 需要了解時間戳,時區,計時規則和表示形式。比較簡單百度一下
- Java中有新舊兩套操作時間日期的類,因爲目前有的程序還在混合使用
// 舊接口
import java.util.Date;
// Main
public class Main {
public static void main(String[] args) throws Exception {
// 獲取系統當前時間戳:
System.out.println(System.currentTimeMillis());// 獲取當前時間戳
// 獲取當前時間:
Date now = new Date();
System.out.println(now);
// 把Date轉化爲long:
long t = now.getTime();
System.out.println(t);
// 把long轉化爲Date:
System.out.println(new Date(t));
}
}
// Date2String
import java.util.Date;
public class Date2String {
public static void main(String[] args) throws Exception {
// 獲取當前時間:
Date now = new Date();
// 以當前時區打印日期時間:
System.out.println(now.toString());
// 以GMT+00:00時區打印日期時間:
System.out.println(now.toGMTString());
// 以當前時區+當前Locale打印日期時間:
System.out.println(now.toLocaleString()); // 國際化
}
}
// Format
import java.text.SimpleDateFormat;
import java.util.Date;
public class Format { // 格式化輸出
public static void main(String[] args) throws Exception {
// 獲取當前時間:
Date now = new Date();
// 指定格式打印:
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");// "MM-dd-yyyy HH:mm:ss"
System.out.println(sdf.format(now));
}
}
// Parse
import java.text.SimpleDateFormat;
import java.util.Date;
public class Parse { // 字符串解析爲時間
public static void main(String[] args) throws Exception {
// 按系統Locale解析日期時間:
String s1 = "2016-11-20 12:15:59";
Date date1 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse(s1);
System.out.println(date1);
// 解析MMM時默認按照系統Locale:
String s2 = "Nov/20/2016 12:15:59";
Date date2 = new SimpleDateFormat("MMM/dd/yyyy HH:mm:ss").parse(s2);
System.out.println(date2);
// 按ISO 8601標準格式解析:
String iso = "2016-11-20T12:15:59";
Date date3 = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss").parse(iso);
System.out.println(date3);
}
}
// Calendar接口
import java.util.Calendar;
// Main
public class Main {
public static void main(String[] args) throws Exception {
// 獲取當前時間表示的Calendar:
Calendar c = Calendar.getInstance();
// 轉換爲Date打印:
System.out.println(c.getTime());
// 轉換爲long打印:
System.out.println(c.getTimeInMillis());
// 獲取年月日時分秒:
System.out.println(" Year = " + c.get(Calendar.YEAR));
// 注意月份從0開始:1月=0,2月=1,...,12月=11:
System.out.println(" Month = " + c.get(Calendar.MONTH));// 月份從0開始,反人類吧!
System.out.println(" Day = " + c.get(Calendar.DAY_OF_MONTH));
// 注意星期從1開始:星期日=1,星期一=2,...,星期六=7:
System.out.println(" Weekday = " + c.get(Calendar.DAY_OF_WEEK));
System.out.println(" Hour = " + c.get(Calendar.HOUR_OF_DAY));
System.out.println(" Minute = " + c.get(Calendar.MINUTE));
System.out.println(" Second = " + c.get(Calendar.SECOND));
System.out.println(" Millis = " + c.get(Calendar.MILLISECOND));
// 默認時區:
System.out.println("TimeZone = " + c.getTimeZone());// Asia/shanghai
}
}
// setTime
public class SetTime { // 可以設置時間
public static void main(String[] args) throws Exception {
// 獲取當前時間表示的Calendar:
Calendar c = Calendar.getInstance();
// 轉換爲Date打印:
System.out.println(c.getTime());
// 設置爲指定時間:
c.clear();
c.set(Calendar.YEAR, 1999);
c.set(Calendar.MONTH, 10); // 11月
c.set(Calendar.DAY_OF_MONTH, 30);
c.set(Calendar.HOUR_OF_DAY, 21);
System.out.println(c.getTime());
}
}
// Calculate
public class Calculate { // 可以運算日期時間
public static void main(String[] args) throws Exception {
// 獲取當前時間表示的Calendar:
Calendar c = Calendar.getInstance();
// 轉換爲Date打印:
System.out.println(c.getTime());
// + 5 days:
c.add(Calendar.DAY_OF_MONTH, 5);
// - 2 hours:
c.add(Calendar.HOUR_OF_DAY, -2);
// 轉換爲Date打印:
System.out.println(c.getTime());
}
}
//
import java.util.TimeZone;
public class Zone { // 獲取指定時區的時間
public static void main(String[] args) throws Exception {
// 獲取當前時間:
Calendar c = Calendar.getInstance();
System.out.println(c.getTime());
// 獲取紐約時間:
c.setTimeZone(TimeZone.getTimeZone("America/New_York"));
int y = c.get(Calendar.YEAR);
int m = c.get(Calendar.MONTH) + 1;
int d = c.get(Calendar.DAY_OF_MONTH);
int hh = c.get(Calendar.HOUR_OF_DAY);
int mm = c.get(Calendar.MINUTE);
int ss = c.get(Calendar.SECOND);
System.out.println(y + "-" + m + "-" + d + " " + hh + ":" + mm + ":" + ss);
}
}
java.time
// 新接口
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
public class Main {
public static void main(String[] args) throws Exception {
// 獲取當前本地日期:
LocalDate d1 = LocalDate.now();
System.out.println(d1);
System.out.println("Week = " + d1.getDayOfWeek().getValue());
// 注意11月=11:
LocalDate d2 = LocalDate.of(2016, 11, 30);
System.out.println(d2);
// 獲取當前本地時間:
LocalTime t1 = LocalTime.now();
System.out.println(t1);
LocalTime t2 = LocalTime.of(15, 16, 17);
System.out.println(t2);
// 獲取當前本地日期和時間:
LocalDateTime dt1 = LocalDateTime.now();
System.out.println(dt1);
// 用LocalDate和LocalTime組合:
LocalDateTime dt2 = LocalDateTime.of(d2, t2);
System.out.println(dt2);
}
}
// Format
import java.time.format.DateTimeFormatter;
public class Format {
public static void main(String[] args) {
// 格式化:
DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
System.out.println(dtf.format(LocalDateTime.now()));
// 按ISO格式解析:
LocalDateTime dt1 = LocalDateTime.parse("2016-11-30T15:16:17");
System.out.println(dt1);
// 按指定格式解析:
LocalDateTime dt2 = LocalDateTime.parse("2016-11-30 15:16:17", dtf);
System.out.println(dt2);
}
}
// Calculate
mport java.time.DayOfWeek;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.Period;
import java.time.temporal.TemporalAdjusters;
public class Calculate {
public static void main(String[] args) throws Exception {
// 獲取當前日期和時間:
LocalDateTime ldt = LocalDateTime.now();
System.out.println(ldt);
// + 5 days:
LocalDateTime ldt2 = ldt.plusDays(5);
System.out.println(ldt2);
// - 2 hours:
LocalDateTime ldt3 = ldt2.minusHours(2);
System.out.println(ldt3);
// 獲得當月第一天:
LocalDate firstDay = LocalDate.now().withDayOfMonth(1);
LocalDate firstDay2 = LocalDate.now().with(TemporalAdjusters.firstDayOfMonth());
System.out.println(firstDay.equals(firstDay2));
System.out.println(firstDay);
// 獲得當月最後一天:
LocalDate lastDay = LocalDate.now().with(TemporalAdjusters.lastDayOfMonth());
System.out.println(lastDay);
// 獲得當月第一個星期日:
LocalDate firstSunday = LocalDate.now().with(TemporalAdjusters.firstInMonth(DayOfWeek.SUNDAY));
System.out.println(firstSunday);
// 判斷兩個日期哪個在前:
System.out.println(firstSunday.isBefore(LocalDate.now()));
// 兩個日期相差?年?月?天:
Period p = LocalDate.now().until(LocalDate.of(2050, 1, 1));
System.out.println(p);
// 兩個日期一共相差多少天:
System.out.println(LocalDate.of(2050, 1, 1).toEpochDay() - LocalDate.now().toEpochDay());
}
}
- 這裏的LocalDateTime不能裝換爲long
ZonedDateTime
- Instant表示時刻
- long表示時間戳(秒值)
import java.time.Instant;
import java.time.ZoneId;
import java.time.ZonedDateTime;
public class Main {
public static void main(String[] args) throws Exception {
// 獲取當前默認時區的日期和時間:
ZonedDateTime now = ZonedDateTime.now();
System.out.println(now);
// 打印時區:
System.out.println(now.getZone());
// 獲取Instant:
Instant ins = now.toInstant();
System.out.println(ins.getEpochSecond());
// 按指定時區獲取當前日期和時間:
ZonedDateTime london = ZonedDateTime.now(ZoneId.of("Europe/London")); // 倫敦時間
System.out.println(london);
// 把倫敦時間轉換到紐約時間:
ZonedDateTime newyork = london.withZoneSameInstant(ZoneId.of("America/New_York")); // 紐約時間
System.out.println(newyork);
}
}
// Local2Zoned
public class Local2Zoned { // 轉換時區
public static void main(String[] args) throws Exception {
// 把LocalDateTime轉換爲ZonedDateTime:
LocalDateTime ldt = LocalDateTime.of(2016, 11, 30, 8, 15, 59);
// 關聯到當前默認時區:
ZonedDateTime bj = ldt.atZone(ZoneId.systemDefault());
System.out.println(bj);
// 關聯到紐約時區:
ZonedDateTime ny = ldt.atZone(ZoneId.of("America/New_York"));
System.out.println(ny);
}
}
public class ChangeZone { // 更改時區
public static void main(String[] args) {
// 把LocalDateTime轉換爲ZonedDateTime:
LocalDateTime ldt = LocalDateTime.of(2016, 11, 30, 8, 15, 59);
// 關聯到當前默認時區:
ZonedDateTime bj = ldt.atZone(ZoneId.systemDefault());
System.out.println(bj);
// 轉換到紐約時區:
ZonedDateTime ny = bj.withZoneSameInstant(ZoneId.of("America/New_York"));
System.out.println(ny);
}
}
- 新舊接口的轉換
- 設置符合不同用戶習慣的時間格式
- Locale對象會根據國家常量構建不同的語言環境(主要是格式上)
- 時間的確定主要是DateTime/long/Instant
單元測試
- 什麼是單元測試?
一個項目往往包含了大量的方法,可能有成千上萬個。如何去保證這些方法產生的結果是我們想要的呢?最容易想到的一個方式,就是我們通過System.out來輸出我們的結果,看看是不是滿足我們的需求,但是項目中總不能在每一個方法中都去輸出一遍非常繁瑣,所以需要單元測試框架 - 測試驅動開發(TDD)
- 測試框架JUnit
JUnit模塊
- 特點:
- 使用斷言Assert
- 使用JUnit需要注意:
- 測試之前我們一般要初始化一些資源,稱爲
Fixture
- 需要使用如下方法
使用步驟:
- 在需要測試的類中使用
ctrl+shift+T
創建測試類,可能會自動下載一些jar包添加到lib庫 - 在IDEA爲我們創建好的測試方法中填寫邏輯
- 測試方法一般都爲
void
類型,必須使用@Test
註解
package Hello;
import org.junit.Test;
import static org.junit.Assert.*;
public class RecursionTest {
@Test
public void isNumberic() {
Recursion re = new Recursion();
boolean x = re.isNumberic("666");
assertEquals(x,true);
}
}
- 我們要了解測試的生命週期
- 一般情況下,只需將公有的實例化步驟放在
@Before
註解的方法中即可,一般命名爲setUp() - 但如果需要創建數據庫等耗時操作,需要在
@BeforeClass
註解的方法中執行 - 順序是:@BeforeClass–>@Before–>@After–>…[@Before–>@After]…–>@AfterClass
測試異常
- 使用
expected
測試異常
// 在測試類中
@Test(expected=NumberFormatException.class)
public void testCalcWithNull() {
calc.calculate(null); // 如果測試未通過,說明我們傳入null時沒有報此異常,需要修改代碼
}
參數化測試
- 當我們使用一組參數對相同的方法測試時,可以將參數用方法返回,進行一次性測試,而不用不斷重複
- 參數必須由靜態方法
data()
返回,被標記(註解)爲@Parameters
,返回類型爲Collection<> - 此測試類必須被標記爲@RunWith(parameterized.class)
- 構造方法參數必須和測試參數(data中定義的參數)一一對應
- 相當於測試類會使用構造方法進行實例化,將數據賦值給成員變量
- 可以通過@Parameter(index)標記public字段,就不用寫構造方法,JUnit會自動創建實例,並把數據注入!
- 還可以爲測試設置超時
@Test(timeout=1000) // 單位是毫秒
超時測試不能取代性能測試和壓力測試
正則表達式
- 一個正則表達式就是一個描述規則的字符串,編寫正確的規則,就可以通過正則引擎判斷目標字符串是否符合規則
- 可以應用於任何語言,JDK中使用java.util.regex
- 規則可以參考博文
注:Java 的正則表達式字符串轉義有兩層次的意義,那就是 Java 字符串轉義出符合正則表達式語法的字符串,所以匹配“ . ”要使用“ \\. ”,Java轉義後交給正則表達式的就是 “\.”。如果要匹配到“\”,就需要使用“\\\\”,因爲要保證Java 程序裏輸出的是 “\\”纔行,交給正則表達時候,規則我們就比較熟悉了!
- 我們常用分組匹配的方式
import java.util.Objects;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class Time {
/**
* TODO: 提取合法時間字符串的時,分,秒
*
* @param str
* Time字符串
* @return Time對象,包含時,分,秒,或者當字符串不合法時返回null
*/
// 只編譯一次規則,提高效率
static Pattern p = Pattern.compile("^([0-9]|[0-1][0-9]|2[0-3])\\:([0-9]|[0-5][0-9])\\:([0-9]|[0-5][0-9])$");
public static Time parseTime(String str) {
int h = 0;
int m = 0;
int s = 0;
// FIXME:
Matcher mt = p.matcher(str);// 正則匹配
// 可以使用mt.find()實現搜索
if (mt.matches()) {// 匹配成功
// group(0)表示匹配到的所有值
h = Integer.parseInt(mt.group(1));// 第一個分組匹配到的值
m = Integer.parseInt(mt.group(2));
s = Integer.parseInt(mt.group(3));
return new Time(h, m, s);
}
return null;
}
private final int hour;
private final int minute;
private final int second;
public Time(int hour, int minute, int second) {// 構造方法
this.hour = hour;
this.minute = minute;
this.second = second;
}
public int getHour() {
return hour;
}
public int getMinute() {
return minute;
}
public int getSecond() {
return second;
}
@Override
public boolean equals(Object o) {
if (o == this) {
return true;
}
if (o instanceof Time) {
Time t = (Time) o;
return t.hour == this.hour && t.minute == this.minute && t.second == this.second;
}
return false;
}
@Override
public int hashCode() {
return Objects.hash(hour, minute, second);
}
@Override
public String toString() {
return String.format("%02d:%02d:%02d", hour, minute, second);
}
}
- 用測試康康
import org.junit.Test;
import static org.junit.Assert.*;
public class TimeTest {
@Test
public void parseTime() {
assertEquals(new Time(0, 0, 0), Time.parseTime("0:0:0"));
assertEquals(new Time(0, 0, 59), Time.parseTime("0:0:59"));
assertEquals(new Time(0, 59, 0), Time.parseTime("0:59:0"));
assertEquals(new Time(5, 0, 9), Time.parseTime("05:00:9"));
assertEquals(new Time(10, 2, 9), Time.parseTime("10:02:9"));
assertEquals(new Time(10, 2, 9), Time.parseTime("10:2:09"));
assertEquals(new Time(23, 0, 1), Time.parseTime("23:0:01"));
assertEquals(new Time(23, 59, 59), Time.parseTime("23:59:59"));
assertNull(Time.parseTime("000:00:00"));
assertNull(Time.parseTime("23:59:60"));
assertNull(Time.parseTime("23:60:59"));
assertNull(Time.parseTime("24:00:00"));
assertNull(Time.parseTime("0:0:A"));
assertNull(Time.parseTime("11-12-12"));
}
}
- 我們可以使用正則表達式實現搜索、替換等等
import java.util.Objects;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public static void main(String[] s) {
String s = "Roy is a handsome boy";
String r = s.replaceAll("\\s+", " ");
String w = r.replaceAll("\\w+", "<h1>$1<h1>"); // $1表示匹配到的字符
}
小結
這裏總結了Java的IO編程,主要包括字符字節流,Filter模式,通過classpath獲取資源,序列化對象等。然後介紹了Java中操作時間日期的方法,如何進行代碼測試以及正則表達式的基本使用方法。
部分圖片來源於網絡
部分代碼來自廖雪峯老師的教程
如有不當,煩請指出