实现compareTo()

class Person implements Comparable<Person> {
  String firstName;
  String lastName;
  int birthdate;

  // Compare by firstName, break ties by lastName, finally break ties by birthdate
  public int compareTo(Person other) {
    if (firstName.compareTo(other.firstName) != 0)
      return firstName.compareTo(other.firstName);
    else if (lastName.compareTo(other.lastName) != 0)
      return lastName.compareTo(other.lastName);
    else if (birthdate < other.birthdate)
      return -1;
    else if (birthdate > other.birthdate)
      return 1;
    else
      return 0;
  }
}
  • 连天完结泛型版本 Comparable 并非完毕原始类型 Comparable
    。因为那样能够节约代码量和压缩不供给的分神。
  • 只关怀重临结果的正负号(负/零/正),它们的轻重不主要。
  • Comparator.compare(卡塔尔国的兑现与这一个相通。
  • 参考:java.lang.Comparable。

返转字符串

String reverse(String s) {
  return new StringBuilder(s).reverse().toString();
}
  • 其风度翩翩法子或许应该出席Java标准库。
  • 参考:java.lang.StringBuilder.reverse()。

从输入流里读取字节数据

InputStream in = (...);
try {
  while (true) {
    int b = in.read();
    if (b == -1)
      break;
    (... process b ...)
  }
} finally {
  in.close();
}
  • read(State of Qatar方法大概重返下一次从流里读取的字节数(0到255,满含0和255),要么在到达流的末端时回来-1。
  • 参考:java.io.InputStream.read()。

实现clone()

class Values implements Cloneable {
  String abc;
  double foo;
  int[] bars;
  Date hired;

  public Values clone() {
    try {
      Values result = (Values)super.clone();
      result.bars = result.bars.clone();
      result.hired = result.hired.clone();
      return result;
    } catch (CloneNotSupportedException e) {  // Impossible
      throw new AssertionError(e);
    }
  }
}
  • 行使 super.clone(卡塔尔(قطر‎ 让Object类担任创制新的靶子。
  • 基本类型域都早已被科学地复制了。同样,大家不需求去克隆String和BigInteger等不得变类型。
  • 手动对富有的非基本类型域(对象和数组)实行深度复制(deep copy)。
  • 兑现了Cloneable的类,clone(卡塔尔方法长久不要抛CloneNotSupportedException。因而,要求捕获这几个可怜并忽视它,可能使用不受检特别(unchecked
    exception)包装它。
  • 不行使Object.clone(卡塔尔(قطر‎方法而是手动地促成clone(State of Qatar方法是能够的也是合法的。
  • 参考:java.lang.Object.clone()、java.lang.Cloneable()。

把4个字节包装(packing)成三个int

int packBigEndian(byte[] b) {
  return (b[0] & 0xFF) << 24
       | (b[1] & 0xFF) << 16
       | (b[2] & 0xFF) <<  8
       | (b[3] & 0xFF) <<  0;
}

int packLittleEndian(byte[] b) {
  return (b[0] & 0xFF) <<  0
       | (b[1] & 0xFF) <<  8
       | (b[2] & 0xFF) << 16
       | (b[3] & 0xFF) << 24;
}

从文件里读取文本

BufferedReader in = new BufferedReader(
    new InputStreamReader(new FileInputStream(...), "UTF-8"));
try {
  while (true) {
    String line = in.readLine();
    if (line == null)
      break;
    (... process line ...)
  }
} finally {
  in.close();
}
  • BufferedReader对象的创制显得很冗长。那是因为Java把字节和字符当成五个不等的概念来对待(那与C语言分化)。
  • 您能够采用别的类型的InputStream来顶替FileInputStream,譬喻socket。
  • 当达到流的末端时,BufferedReader.readLine()会返回null。
  • 要三回读取三个字符,使用Reader.read()方法。
  • 您能够动用其它的字符编码而不接收UTF-8,但可是不要那样做。
  • 参考:java.io.BufferedReader、java.io.InputStreamReader。

使用Iterator.remove()

void filter(List<String> list) {
  for (Iterator<String> iter = list.iterator(); iter.hasNext(); ) {
    String item = iter.next();
    if (...)
      iter.remove();
  }
}
  • remove(卡塔尔(قطر‎方法效果在next(卡塔尔方法前段时间回到的条约上。每种条约只能选拔一回remove(卡塔尔国方法。
  • 参考:java.util.Iterator.remove()。

防御性检验数组区间

void frob(byte[] b, int off, int len) {
  if (b == null)
    throw new NullPointerException();
  if (off < 0 || off > b.length
    || len < 0 || b.length - off < len)
    throw new IndexOutOfBoundsException();
  ...
}
  • 毫无认为所给的数组区间(比如,从off起头,读取len个因素)是不会越界。要显式地检查实验它。

填充数组成分

运用循环:

// Fill each element of array 'a' with 123
byte[] a = (...);
for (int i = 0; i < a.length; i++)
  a[i] = 123;

(优先)使用规范库的点子:

Arrays.fill(a, (byte)123);
  • 参考:java.util.Arrays.fill(T[], T)。
  • 参考:java.util.Arrays.fill(T[], int,
    int, T)。

堤防性检查实验对象

int findIndex(List<String> list, String target) {
  if (list == null || target == null)
    throw new NullPointerException();
  ...
}
  • 永不感觉对象参数不会为空(null)。要显式地检验这一个规范。

使用StringBuilder或StringBuffer

// join(["a", "b", "c"]) -> "a and b and c"
String join(List<String> strs) {
  StringBuilder sb = new StringBuilder();
  boolean first = true;
  for (String s : strs) {
    if (first) first = false;
    else sb.append(" and ");
    sb.append(s);
  }
  return sb.toString();
}
  • 决不像这样使用重复的字符串连接:s += item
    ,因为它的年月作用是O(n^2卡塔尔(قطر‎。
  • 动用StringBuilder也许StringBuffer时,能够接收append(卡塔尔方法添Gavin本和使用toString(卡塔尔(قطر‎方法去获得连接起来的全体文件。
  • 先行利用StringBuilder,因为它更加快。StringBuffer的有着办法都以手拉手的,而你平凡不须求一块的秘籍。
  • 参考java.lang.StringBuilder、java.lang.StringBuffer。

在Java编制程序中,有个别知识
并不可能仅经过语言专门的事业只怕专门的学业API文书档案就能够学到的。在本文中,作者会尽量搜罗一些最常用的习于旧贯用法,极度是很难猜到的用法。(Joshua
Bloch的《Effective
Java》对这些话题给出了更详尽的论述,能够从那本书里读书更加多的用法。)

复制二个限量内的数组元素

应用循环:

// Copy 8 elements from array 'a' starting at offset 3
// to array 'b' starting at offset 6,
// assuming 'a' and 'b' are distinct arrays
byte[] a = (...);
byte[] b = (...);
for (int i = 0; i < 8; i++)
  b[6 + i] = a[3 + i];

(优先)使用标准库的章程:

System.arraycopy(a, 3, b, 6, 8);
  • 参考:java.lang.System.arraycopy(Object, int, Object, int,
    int)。

实现hashCode()

class Person {
  String a;
  Object b;
  byte c;
  int[] d;

  public int hashCode() {
    return a.hashCode() + b.hashCode() + c + Arrays.hashCode(d);
  }

  public boolean equals(Object o) { ... }
}
  • 当x和y七个对象具备x.equals(y卡塔尔国 == true ,你不得不要作保x.hashCode(卡塔尔国 ==
    y.hashCode(卡塔尔国。
  • 依照逆反命题,如若x.hashCode(卡塔尔国 != y.hashCode(State of Qatar,那么x.equals(y卡塔尔(قطر‎ ==
    false 必定创造。
  • 你没有须要确定保证,当x.equals(y卡塔尔(قطر‎ == false时,x.hashCode(卡塔尔 !=
    y.hashCode(卡塔尔(قطر‎。可是,若是你能够尽量地使它确立的话,这会增加哈希表的性情。
  • hashCode(State of Qatar最轻便易行的合法完结正是简约地return
    0;即便这一个完成是科学的,然而那会产生HashMap那几个数据构造运营得非常慢。
  • 参考:java.lang.Object.hashCode()。

目录

  • 实现:
    • equals()
    • hashCode()
    • compareTo()
    • clone()
  • 应用:
    • StringBuilder/StringBuffer
    • Random.nextInt(int)
    • Iterator.remove()
    • StringBuilder.reverse()
    • Thread/Runnable
    • try-finally
  • 输入/输出:
    • 从输入流里读取字节数据
    • 从输入流里读取块数据
    • 从文件里读取文本
    • 向文件里写文本
  • 防范性检测:
    • 数值
    • 对象
    • 数组索引
    • 数组区间
  • 新澳门31999,数组:
    • 填充元素
    • 复制二个范围内的数组成分
    • 调动数组大小
  • 包装
    • 个字节包装成三个int
    • 分解成4个字节

实现equals()

class Person {
  String name;
  int birthYear;
  byte[] raw;

  public boolean equals(Object obj) {
    if (!obj instanceof Person)
      return false;

    Person other = (Person)obj;
    return name.equals(other.name)
        && birthYear == other.birthYear
        && Arrays.equals(raw, other.raw);
  }

  public int hashCode() { ... }
}
  • 参数必得是Object类型,无法是外围类。
  • foo.equals(null)必得再次来到false,不可能抛NullPointerException。(注意,null instanceof
    任性类 总是回到false,因而地点的代码能够运作。)
  • 基本类型域(比如,int)的相比使用 ==
    ,基本项目数组域的相比较使用Arrays.equals(卡塔尔国。
  • 覆盖equals(State of Qatar时,记得要相应地隐蔽 hashCode(卡塔尔(قطر‎,与 equals(卡塔尔国 保持黄金年代致。
  • 参考:java.lang.Object.equals(Object)。

转移三个约束内的放肆整数

Random rand = new Random();

// Between 1 and 6, inclusive
int diceRoll() {
  return rand.nextInt(6) + 1;
}
  • 连天利用Java API方法去生成二个大背头节制内的随机数。
  • 永不试图去行使 Math.abs(rand.nextInt(卡塔尔(قطر‎卡塔尔(قطر‎ % n
    这个不鲜明的用法,因为它的结果是有过错的。其它,它的结果值有十分大可能率是负数,举例当rand.nextInt(State of Qatar== Integer.MIN_VALUE时就能够那样。
  • 参考:java.util.Random.nextInt(int)。

堤防性检查评定数组索引

void frob(byte[] b, int index) {
  if (b == null)
    throw new NullPointerException();
  if (index < 0 || index >= b.length)
    throw new IndexOutOfBoundsException();
  ...
}
  • 永不认为所以给的数组索引不会越界。要显式地检查测量检验它。

自身把本文的持有代码都位居大庭广众里。你可以依赖自个儿的喜好去复制和纠正放肆的代码片段,没有必要别的的证据。

从输入流里读取块数据

InputStream in = (...);
try {
  byte[] buf = new byte[100];
  while (true) {
    int n = in.read(buf);
    if (n == -1)
      break;
    (... process buf with offset=0 and length=n ...)
  }
} finally {
  in.close();
}
  • 要记住的是,read(State of Qatar方法不必然会填满整个buf,所以你必须在拍卖逻辑中思考回到的尺寸。
  • 参考:java.io.InputStream.read(byte[])、java.io.InputStream.read(byte[],
    int,
    int)。

向文件里写文本

PrintWriter out = new PrintWriter(
    new OutputStreamWriter(new FileOutputStream(...), "UTF-8"));
try {
  out.print("Hello ");
  out.print(42);
  out.println(" world!");
} finally {
  out.close();
}
  • Printwriter对象的创设显得很冗长。那是因为Java把字节和字符当成多个例外的概念来对待(那与C语言不一样)。
  • 就疑似System.out,你能够使用print(State of Qatar和println(卡塔尔打字与印刷五类别型的值。
  • 您能够采用任何的字符编码而不利用UTF-8,但十二万分不要这么做。
  • 参考:java.io.PrintWriter、java.io.OutputStreamWriter。

防范性检查测验(Defensive checking)数值

int factorial(int n) {
  if (n < 0)
    throw new IllegalArgumentException("Undefined");
  else if (n >= 13)
    throw new ArithmeticException("Result overflow");
  else if (n == 0)
    return 1;
  else
    return n * factorial(n - 1);
}
  • 毫无以为输入的数值都以正数、丰裕小的数等等。要显式地检查测验那几个准绳。
  • 贰个设计精美的函数应该对负有望的输入值都能够科学地实施。要担保全部的意况都思忖到了同临时间不会生出错误的输出(举例溢出)。

把int分解(Unpacking)成4个字节

byte[] unpackBigEndian(int x) {
  return new byte[] {
    (byte)(x >>> 24),
    (byte)(x >>> 16),
    (byte)(x >>>  8),
    (byte)(x >>>  0)
  };
}

byte[] unpackLittleEndian(int x) {
  return new byte[] {
    (byte)(x >>>  0),
    (byte)(x >>>  8),
    (byte)(x >>> 16),
    (byte)(x >>> 24)
  };
}
  • 接连接受无符号右移操作符(>>>)对位实行打包(packing),不要选拔算术右移操作符(>>)。

使用try-finally

I/O流例子:

void writeStuff() throws IOException {
  OutputStream out = new FileOutputStream(...);
  try {
    out.write(...);
  } finally {
    out.close();
  }
}

锁例子:

void doWithLock(Lock lock) {
  lock.acquire();
  try {
    ...
  } finally {
    lock.release();
  }
}
  • 假如try从前的口舌运维失利何况抛出至极,那么finally语句块就不会试行。但无论如何,在此个例子里不用担忧能源的释放。
  • 纵然try语句块里面包车型客车语句抛出卓殊,那么程序的运作就能够跳到finally语句块里施行尽恐怕多的言语,然后跳出那么些主意(除非那么些措施还大概有另八个外部的finally语句块)。

起步一条线程

上边包车型客车八个例证使用了差异的艺术成就了同生龙活虎的业务。

实现Runnnable的方式:

void startAThread0() {
  new Thread(new MyRunnable()).start();
}

class MyRunnable implements Runnable {
  public void run() {
    ...
  }
}

继承Thread的方式:

void startAThread1() {
  new MyThread().start();
}

class MyThread extends Thread {
  public void run() {
    ...
  }
}

无名氏世襲Thread的办法:

void startAThread2() {
  new Thread() {
    public void run() {
      ...
    }
  }.start();
}
  • 决不一贯调用run(卡塔尔国方法。总是调用Thread.start(卡塔尔方法,这些方法会创造一条新的线程并使新建的线程调用run(卡塔尔国。
  • 参考:java.lang.Thread,
    java.lang.Runnable。

调动数组大小

应用循环(扩大范围):

// Make array 'a' larger to newLen
byte[] a = (...);
byte[] b = new byte[newLen];
for (int i = 0; i < a.length; i++)  // Goes up to length of A
  b[i] = a[i];
a = b;

行使循环(减小圈圈):

// Make array 'a' smaller to newLen
byte[] a = (...);
byte[] b = new byte[newLen];
for (int i = 0; i < b.length; i++)  // Goes up to length of B
  b[i] = a[i];
a = b;

(优先)使用规范库的措施:

a = Arrays.copyOf(a, newLen);
  • 参考:java.util.Arrays.copyOf(T[],
    int)。
  • 参考:java.util.Arrays.copyOfRange(T[], int,
    int)。

发表评论

电子邮件地址不会被公开。 必填项已用*标注