Read Sean

          Read me, read Sean.
          posts - 508, comments - 655, trackbacks - 9, articles - 4

           

          好了,來看我在Common Lang中最后要講的一個包:org.apache.commons.lang.time。這個包里面包含了如下5個類:

           

          DateFormatUtils – 提供格式化日期和時間的功能及相關常量;

          DateUtils – CalendarDate的基礎上提供更方便的訪問;

          DurationFormatUtils – 提供格式化時間跨度的功能及相關常量;

          FastDateFormat – java.text.SimpleDateFormat提供一個的線程安全的替代類;

          StopWatch – 是一個方便的計時器。

           

          我們還是在一個例子中來看上述各個類的用法吧:

           

          package sean.study.jakarta.commons.lang;

           

          import java.util.Calendar;

          import java.util.Date;

           

          import org.apache.commons.lang.StringUtils;

          import org.apache.commons.lang.time.DateFormatUtils;

          import org.apache.commons.lang.time.DateUtils;

          import org.apache.commons.lang.time.FastDateFormat;

          import org.apache.commons.lang.time.StopWatch;

           

          public class DateTimeUsage {

           

              public static void main(String[] args) {

                  demoDateUtils();

                  demoStopWatch();

              }

             

              public static void demoDateUtils() {

                  System.out.println(StringUtils.center(" demoDateUtils ", 30, "="));

                  Date date = new Date();

                  String isoDateTime = DateFormatUtils.ISO_DATETIME_FORMAT.format(date);

                  String isoTime = DateFormatUtils.ISO_TIME_NO_T_FORMAT.format(date);

                  FastDateFormat fdf = FastDateFormat.getInstance("yyyy-MM");

                  String customDateTime = fdf.format(date);

                  System.out.println("ISO_DATETIME_FORMAT: " + isoDateTime);

                  System.out.println("ISO_TIME_NO_T_FORMAT: " + isoTime);

                  System.out.println("Custom FastDateFormat: " + customDateTime);

                  System.out.println("Default format: " + date);

                  System.out.println("Round HOUR: " + DateUtils.round(date, Calendar.HOUR));

                  System.out.println("Truncate HOUR: " + DateUtils.truncate(date, Calendar.HOUR));

                  System.out.println();

              }

             

              public static void demoStopWatch() {

                  System.out.println(StringUtils.center(" demoStopWatch ", 30, "="));

                  StopWatch sw = new StopWatch();

                  sw.start();

                  operationA();

                  sw.stop();

                  System.out.println("operationA used " + sw.getTime() + " milliseconds.");

                  System.out.println();

              }

             

              public static void operationA() {

                  try {

                      Thread.sleep(999);

                  }

                  catch (InterruptedException e) {

                      // do nothing

                  }

              }

           

          }

           

          以下是運行結果:

           

          ======= demoDateUtils ========

          ISO_DATETIME_FORMAT: 2005-08-01T12:41:51

          ISO_TIME_NO_T_FORMAT: 12:41:51

          Custom FastDateFormat: 2005-08

          Default format: Mon Aug 01 12:41:51 CST 2005

          Round HOUR: Mon Aug 01 13:00:00 CST 2005

          Truncate HOUR: Mon Aug 01 12:00:00 CST 2005

           

          ======= demoStopWatch ========

          operationA used 1000 milliseconds.

           

          具體的調用細節和完整的API請參閱Commons LangJavadoc。

           

           

          posted @ 2005-08-01 13:19 laogao 閱讀(7369) | 評論 (11)編輯 收藏

           

          Jakarta Commons中,專門處理數學計算的類分別可以在兩個地方找到:一是Commons Langorg.apache.commons.lang.math包中,二是在Commons Math這個單獨的子項目中。由于后者主要是處理復數、矩陣等,相對使用比較少,在我的筆記中就只簡單講講Commons Lang中的math包。對后者感興趣的可以看看

          http://jakarta.apache.org/commons/math/

           

          org.apache.commons.lang.math包中共有10個類,這些類可以歸納成四組:

          1- 處理分數的Fraction類;

          2- 處理數值的NumberUtils類;

          3- 處理數值范圍的Range、NumberRange、IntRangeLongRange、FloatRange、DoubleRange類;

          4- 處理隨機數的JVMRandomRandomUtils類。

           

          下面我舉個例子分別說明上述四組的使用方法:

           

          package sean.study.jakarta.commons.lang;

           

          import org.apache.commons.lang.ArrayUtils;

          import org.apache.commons.lang.BooleanUtils;

          import org.apache.commons.lang.StringUtils;

          import org.apache.commons.lang.math.DoubleRange;

          import org.apache.commons.lang.math.Fraction;

          import org.apache.commons.lang.math.NumberUtils;

          import org.apache.commons.lang.math.RandomUtils;

          import org.apache.commons.lang.math.Range;

           

          public class LangMathUsage {

           

              public static void main(String[] args) {

                  demoFraction();

                  demoNumberUtils();

                  demoNumberRange();

                  demoRandomUtils();

              }

           

              public static void demoFraction() {

                  System.out.println(StringUtils.center(" demoFraction ", 30, "="));

                  Fraction myFraction = Fraction.getFraction(144, 90);

                  // Fraction myFraction = Fraction.getFraction("1 54/90");

                  System.out.println("144/90 as fraction: " + myFraction);

                  System.out.println("144/90 to proper: " + myFraction.toProperString());

                  System.out.println("144/90 as double: " + myFraction.doubleValue());

                  System.out.println("144/90 reduced: " + myFraction.reduce());

                  System.out.println("144/90 reduced proper: "

                          + myFraction.reduce().toProperString());

                  System.out.println();

              }

           

              public static void demoNumberUtils() {

                  System.out.println(StringUtils.center(" demoNumberUtils ", 30, "="));

                  System.out.println("Is 0x3F a number? "

                          + StringUtils.capitalize(BooleanUtils.toStringYesNo(NumberUtils

                                  .isNumber("0x3F"))) + ".");

                  double[] array = { 1.0, 3.4, 0.8, 7.1, 4.6 };

                  double max = NumberUtils.max(array);

                  double min = NumberUtils.min(array);

                  String arrayStr = ArrayUtils.toString(array);

                  System.out.println("Max of " + arrayStr + " is: " + max);

                  System.out.println("Min of " + arrayStr + " is: " + min);

                  System.out.println();

              }

           

              public static void demoNumberRange() {

                  System.out.println(StringUtils.center(" demoNumberRange ", 30, "="));

                  Range normalScoreRange = new DoubleRange(90, 120);

                  double score1 = 102.5;

                  double score2 = 79.9;

                  System.out.println("Normal score range is: " + normalScoreRange);

                  System.out.println("Is "

                          + score1

                          + " a normal score? "

                          + StringUtils

                                  .capitalize(BooleanUtils.toStringYesNo(normalScoreRange

                                          .containsDouble(score1))) + ".");

                  System.out.println("Is "

                          + score2

                          + " a normal score? "

                          + StringUtils

                                  .capitalize(BooleanUtils.toStringYesNo(normalScoreRange

                                          .containsDouble(score2))) + ".");

                  System.out.println();

              }

           

              public static void demoRandomUtils() {

                  System.out.println(StringUtils.center(" demoRandomUtils ", 30, "="));

                  for (int i = 0; i < 5; i++) {

                      System.out.println(RandomUtils.nextInt(100));

                  }

                  System.out.println();

              }

           

          }

           

          以下是運行結果:

           

          ======== demoFraction ========

          144/90 as fraction: 144/90

          144/90 to proper: 1 54/90

          144/90 as double: 1.6

          144/90 reduced: 8/5

          144/90 reduced proper: 1 3/5

           

          ====== demoNumberUtils =======

          Is 0x3F a number? Yes.

          Max of {1.0,3.4,0.8,7.1,4.6} is: 7.1

          Min of {1.0,3.4,0.8,7.1,4.6} is: 0.8

           

          ====== demoNumberRange =======

          Normal score range is: Range[90.0,120.0]

          Is 102.5 a normal score? Yes.

          Is 79.9 a normal score? No.

           

          ====== demoRandomUtils =======

          75

          63

          40

          21

          92

           

          以上就是Commons Langmath包通常的用法。提一下NumberUtils.inNumber(String)方法,它會正確判斷出給定的字符串是否是合法的數值,而我在前面的筆記中提到的StringUtils.isNumeric(String)只能判斷一個字符串是否是由純數字字符組成。Commons Langmath包的各個類都還有很多實用的方法,遠不止我在例子中用到的這些,如果你感興趣,參照一下Commons LangJavadoc吧。

           

           

          posted @ 2005-08-01 13:18 laogao 閱讀(3984) | 評論 (3)編輯 收藏

           

          在前面的專題文章中,我們一起過了一遍org.apache.commons.lang包,接下來我們繼續看org.apache.commons.lang.builder這個包。在這里面我們可以找到7個類,用于幫助我們實現Java對象的一些基礎的共有方法。這7個類分別是:

           

          CompareToBuilder – 用于輔助實現Comparable.compareTo(Object)方法;

          EqualsBuilder – 用于輔助實現Object.equals()方法;

          HashCodeBuilder – 用于輔助實現Object.hashCode()方法;

          ToStringBuilder – 用于輔助實現Object.toString()方法;

          ReflectionToStringBuilder – 使用反射機制輔助實現Object.toString()方法;

          ToStringStyle – 輔助ToStringBuilder控制輸出格式;

          StandardToStringStyle – 輔助ToStringBuilder控制標準格式。

           

          我們知道,在實際應用中,其實經常需要在運行過程中判定對象的知否相等、比較、取hash、和獲取對象基本信息(一般是產生log日志)。然而實現這些compareToequalshashCode、toString其實并非那么直截了當,甚至稍有不注意就可能造成難以追蹤的bug,而且這些方法手工維護的話,比較繁瑣,也容易出錯。于是Commons Langbuilder這個包中提供了上述輔助類,為我們簡化這些方法的實現和維護。

           

          來看一個例子:

           

          package sean.study.jakarta.commons.lang;

           

          import java.util.Date;

           

          import org.apache.commons.lang.builder.CompareToBuilder;

          import org.apache.commons.lang.builder.EqualsBuilder;

          import org.apache.commons.lang.builder.HashCodeBuilder;

          import org.apache.commons.lang.builder.ToStringBuilder;

          import org.apache.commons.lang.builder.ToStringStyle;

           

          public class BuilderUsage {

           

              public static void main(String[] args) {

                 

                  Staff staff1 = new Staff(123, "John Smith", new Date());

                  Staff staff2 = new Staff(456, "Jane Smith", new Date());

                 

                  System.out.println("staff1's info: " + staff1);

                  System.out.println("staff2's info: " + staff2);

                  System.out.println("staff1's hash code: " + staff1.hashCode());

                  System.out.println("staff2's hash code: " + staff2.hashCode());

                  System.out.println("staff1 equals staff2? " + staff1.equals(staff2));

           

              }

           

          }

           

          class Staff implements Comparable {

           

              private long staffId;

              private String staffName;

              private Date dateJoined;

           

              public Staff() {

              }

           

              public Staff(long staffId, String staffName, Date dateJoined) {

                  this.staffId = staffId;

                  this.staffName = staffName;

                  this.dateJoined = dateJoined;

              }

           

              public int compareTo(Object o) {

                  int res = -1;

                  if (o != null && Staff.class.isAssignableFrom(o.getClass())) {

                      Staff s = (Staff) o;

                      res = new CompareToBuilder()

                              .append(dateJoined, s.getDateJoined())

                              .append(staffName, s.getStaffName()).toComparison();

                  }

                  return res;

              }

           

              public boolean equals(Object o) {

                  boolean res = false;

                  if (o != null && Staff.class.isAssignableFrom(o.getClass())) {

                      Staff s = (Staff) o;

                      res = new EqualsBuilder()

                              .append(staffId, s.getStaffId())

                              .isEquals();

                  }

                  return res;

              }

           

              public int hashCode() {

                  return new HashCodeBuilder(11, 23).append(staffId).toHashCode();

              }

           

              public String toString() {

                  return new ToStringBuilder(this, ToStringStyle.MULTI_LINE_STYLE)

                          .append("staffId", staffId)

                          .append("staffName", staffName)

                          .append("dateJoined", dateJoined)

                          .toString();

              }

           

              public Date getDateJoined() {

                  return dateJoined;

              }

           

              public void setDateJoined(Date dateJoined) {

                  this.dateJoined = dateJoined;

              }

           

              public long getStaffId() {

                  return staffId;

              }

           

              public void setStaffId(long staffId) {

                  this.staffId = staffId;

              }

           

              public String getStaffName() {

                  return staffName;

              }

           

              public void setStaffName(String staffName) {

                  this.staffName = staffName;

              }

          }

           

          以下是運行結果:

           

          staff1's info: sean.study.jakarta.commons.lang.Staff@190d11[

            staffId=123

            staffName=John Smith

            dateJoined=Sat Jul 30 13:18:45 CST 2005

          ]

          staff2's info: sean.study.jakarta.commons.lang.Staff@1fb8ee3[

            staffId=456

            staffName=Jane Smith

            dateJoined=Sat Jul 30 13:18:45 CST 2005

          ]

          staff1's hash code: 376

          staff2's hash code: 709

          staff1 equals staff2? false

           

          這些builder使用起來都很簡單,new一個實例,append需要參與的信息,最后加上toComparisonisEqualstoHashCode、toString這樣的結尾即可。相應的,如果你不需要這樣級別的控制,也可以使用利用反射機制的版本自動化實現需要的功能,如:

           

              public int compareTo(Object o) {

                  return CompareToBuilder.reflectionCompare(this, o);

              }

           

              public boolean equals(Object o) {

                  return EqualsBuilder.reflectionEquals(this, o);

              }

           

              public int hashCode() {

                  return HashCodeBuilder.reflectionHashCode(this);

              }

           

              public String toString() {

                  return ReflectionToStringBuilder.toString(this);

              }

           

          尤其當我們在項目中不希望過多的參與到對這些對象方法的維護時,采用Commons提供的利用反射的這些API就成了方便而相對安全的一個方案。

           

           

          posted @ 2005-07-30 15:38 laogao 閱讀(6092) | 評論 (0)編輯 收藏

           

          處理文本對Java應用來說應該算是家常便飯了,在1.4出現之前,Java自身提供的API非常有限,如String、StringTokenizer、StringBuffer,操作也比較單一。無非就是查找substring、分解、合并等等。到1.4的出現可以說Java的文字處理上了一個臺階,因為它支持regular expression了。這可是個重量級而方便的東東啊,缺點是太復雜,學習起來有一定難度。相較而言,Jakarta Commons提供的StringUtilsWordUtils至今還維持著那種簡潔而強大的美,使用起來也很順手。來看一個例子:

           

          package sean.study.jakarta.commons.lang;

           

          import org.apache.commons.lang.StringUtils;

           

          public class StringUtilsAndWordUtilsUsage {

           

              public static void main(String[] args) {

                 

                  // data setup

                  String str1 = "";

                  String str2 = " ";

                  String str3 = "\t";

                  String str4 = null;

                  String str5 = "123";

                  String str6 = "ABCDEFG";

                  String str7 = "It feels good to use Jakarta Commons.\r\n";

                 

                  // check for empty strings

                  System.out.println("==============================");

                  System.out.println("Is str1 blank? " + StringUtils.isBlank(str1));

                  System.out.println("Is str2 blank? " + StringUtils.isBlank(str2));

                  System.out.println("Is str3 blank? " + StringUtils.isBlank(str3));

                  System.out.println("Is str4 blank? " + StringUtils.isBlank(str4));

                 

                  // check for numerics

                  System.out.println("==============================");

                  System.out.println("Is str5 numeric? " + StringUtils.isNumeric(str5));

                  System.out.println("Is str6 numeric? " + StringUtils.isNumeric(str6));

                 

                  // reverse strings / whole words

                  System.out.println("==============================");

                  System.out.println("str6: " + str6);

                  System.out.println("str6 reversed: " + StringUtils.reverse(str6));

                  System.out.println("str7: " + str7);

                  String str8 = StringUtils.chomp(str7);

                  str8 = StringUtils.reverseDelimited(str8, ' ');

                  System.out.println("str7 reversed whole words : \r\n" + str8);

                 

                  // build header (useful to print log messages that are easy to locate)

                  System.out.println("==============================");

                  System.out.println("print header:");

                  String padding = StringUtils.repeat("=", 50);

                  String msg = StringUtils.center(" Customised Header ", 50, "%");

                  Object[] raw = new Object[]{padding, msg, padding};

                  String header = StringUtils.join(raw, "\r\n");

                  System.out.println(header);

           

              }

          }

           

          輸出的結果如下:

           

          ==============================

          Is str1 blank? true

          Is str2 blank? true

          Is str3 blank? true

          Is str4 blank? true

          ==============================

          Is str5 numeric? true

          Is str6 numeric? false

          ==============================

          str6: ABCDEFG

          str6 reversed: GFEDCBA

          str7: It feels good to use Jakarta Commons.

           

          str7 reversed whole words :

          Commons. Jakarta use to good feels It

          ==============================

          print header:

          ==================================================

          %%%%%%%%%%%%%%% Customised Header %%%%%%%%%%%%%%%%

          ==================================================

           

          從代碼中我們可以大致了解到這個StringUtils類簡單而強大的處理能力,從檢查空串(對null的情況處理很得體),到分割子串,到生成格式化的字符串,使用都很簡潔,也很直截了當。

           

           

          posted @ 2005-07-30 11:37 laogao 閱讀(5032) | 評論 (0)編輯 收藏

           

          數組是我們經常需要使用到的一種數據結構,但是由于Java本身并沒有提供很好的API支持,使得很多操作實際上做起來相當繁瑣,以至于我們實際編碼中甚至會不惜犧牲性能去使用Collections API,用Collection當然能夠很方便的解決我們的問題,但是我們一定要以性能為代價嗎?ArrayUtils幫我們解決了處理類似情況的大部分問題。來看一個例子:

           

          package sean.study.jakarta.commons.lang;

           

          import java.util.Map;

          import org.apache.commons.lang.ArrayUtils;

           

          public class ArrayUtilsUsage {

           

              public static void main(String[] args) {

           

                  // data setup

                  int[] intArray1 = { 2, 4, 8, 16 };

                  int[][] intArray2 = { { 1, 2 }, { 2, 4 }, { 3, 8 }, { 4, 16 } };

                  Object[][] notAMap = {

                          { "A", new Double(100) },

                          { "B", new Double(80) },

                          { "C", new Double(60) },

                          { "D", new Double(40) },

                          { "E", new Double(20) }

                  };

           

                  // printing arrays

                  System.out.println("intArray1: " + ArrayUtils.toString(intArray1));

                  System.out.println("intArray2: " + ArrayUtils.toString(intArray2));

                  System.out.println("notAMap: " + ArrayUtils.toString(notAMap));

           

                  // finding items

                  System.out.println("intArray1 contains '8'? "

                          + ArrayUtils.contains(intArray1, 8));

                  System.out.println("intArray1 index of '8'? "

                          + ArrayUtils.indexOf(intArray1, 8));

                  System.out.println("intArray1 last index of '8'? "

                          + ArrayUtils.lastIndexOf(intArray1, 8));

           

                  // cloning and resversing

                  int[] intArray3 = ArrayUtils.clone(intArray1);

                  System.out.println("intArray3: " + ArrayUtils.toString(intArray3));

                  ArrayUtils.reverse(intArray3);

                  System.out.println("intArray3 reversed: "

                          + ArrayUtils.toString(intArray3));

           

                  // primitive to Object array

                  Integer[] integerArray1 = ArrayUtils.toObject(intArray1);

                  System.out.println("integerArray1: "

                          + ArrayUtils.toString(integerArray1));

           

                  // build Map from two dimensional array

                  Map map = ArrayUtils.toMap(notAMap);

                  Double res = (Double) map.get("C");

                  System.out.println("get 'C' from map: " + res);

           

              }

           

          }

           

          以下是運行結果:

           

          intArray1: {2,4,8,16}

          intArray2: {{1,2},{2,4},{3,8},{4,16}}

          notAMap: {{A,100.0},{B,80.0},{C,60.0},{D,40.0},{E,20.0}}

          intArray1 contains '8'? true

          intArray1 index of '8'? 2

          intArray1 last index of '8'? 2

          intArray3: {2,4,8,16}

          intArray3 reversed: {16,8,4,2}

          integerArray1: {2,4,8,16}

          get 'C' from map: 60.0

           

          這段代碼說明了我們可以如何方便的利用ArrayUtils類幫我們完成數組的打印、查找、克隆、倒序、以及值型/對象數組之間的轉換等操作。如果想了解更多,請參考Javadoc。

           

           

          posted @ 2005-07-30 11:36 laogao 閱讀(3599) | 評論 (0)編輯 收藏

           

          我們首先來看org.apache.commons.lang包,這個包提供了一些有用的包含static方法的Util類。除了6Exception類和2個已經deprecated的數字類之外,commons.lang包共包含了17個實用的類:

           

          ArrayUtils – 用于對數組的操作,如添加、查找、刪除、子數組、倒序、元素類型轉換等;

          BitField – 用于操作位元,提供了一些方便而安全的方法;

          BooleanUtils – 用于操作和轉換boolean或者Boolean及相應的數組;

          CharEncoding – 包含了Java環境支持的字符編碼,提供是否支持某種編碼的判斷;

          CharRange – 用于設定字符范圍并做相應檢查;

          CharSet – 用于設定一組字符作為范圍并做相應檢查;

          CharSetUtils – 用于操作CharSet;

          CharUtils – 用于操作char值和Character對象;

          ClassUtils – 用于對Java類的操作,不使用反射;

          ObjectUtils – 用于操作Java對象,提供null安全的訪問和其他一些功能;

          RandomStringUtils – 用于生成隨機的字符串;

          SerializationUtils – 用于處理對象序列化,提供比一般Java序列化更高級的處理能力;

          StringEscapeUtils – 用于正確處理轉義字符,產生正確的Java、JavaScript、HTML、XMLSQL代碼;

          StringUtils – 處理String的核心類,提供了相當多的功能;

          SystemUtils – java.lang.System基礎上提供更方便的訪問,如用戶路徑、Java版本、時區、操作系統等判斷;

          Validate – 提供驗證的操作,有點類似assert斷言;

          WordUtils – 用于處理單詞大小寫、換行等。

           

          接下來我準備用兩個例子來分別說明ArrayUtilsStringUtils的常見用法。

           

           

          posted @ 2005-07-30 11:35 laogao 閱讀(3760) | 評論 (0)編輯 收藏

           

          java.lang這個包的作用類似,Commons Lang這一組API也是提供一些基礎的、通用的操作和處理,如自動生成toString()的結果、自動實現hashCode()equals()方法、數組操作、枚舉、日期和時間的處理等等。目前這組API的版本是2.1,下載地址如下:

           

          http://apache.justdn.org/jakarta/commons/lang/binaries/commons-lang-2.1.zip

          http://apache.justdn.org/jakarta/commons/lang/source/commons-lang-2.1-src.zip

           

          其中后一個是源代碼。

           

          這一組API的所有包名都以org.apache.commons.lang開頭,共有如下8個包:

           

          org.apache.commons.lang

          org.apache.commons.lang.builder

          org.apache.commons.lang.enum

          org.apache.commons.lang.enums

          org.apache.commons.lang.exception

          org.apache.commons.lang.math

          org.apache.commons.lang.mutable

          org.apache.commons.lang.time

           

          其中的lang.enum已不建議使用,替代它的是緊隨其后的lang.enums包。 lang包主要是一些可以高度重用的Util類;lang.builder包包含了一組用于產生每個Java類中都常使用到的toString()hashCode()equals()、compareTo()等等方法的構造器;lang.enums包顧名思義用于處理枚舉;lang.exception包用于處理Java標準API中的exception,為1.4之前版本提供Nested Exception功能;lang.math包用于處理數字;lang.mutable用于包裝值型變量;lang.time包提供處理日期和時間的功能。

           

          由于Commons的包和類實在很多,不可能一個一個講了,在接下來的專題文章中我就只分別過一下lang、lang.builder、lang.mathlang.time這幾個包和常見的用法,其他的我們可以在用到時臨時參考一下Javadoc。位置就在安裝路徑的

          …\commons-lang-2.1\docs\api\index.html

           

           

          posted @ 2005-07-29 18:10 laogao 閱讀(5023) | 評論 (0)編輯 收藏

           

          Java的世界,有很多(成千上萬)開源的框架,有成功的,也有不那么成功的,有聲名顯赫的,也有默默無聞的。在我看來,成功而默默無聞的那些框架值得我們格外的尊敬和關注,Jakarta Commons就是這樣的一個框架。如果你至少參與了一個中型規模的Java項目,那么我想有超過一大半的機會你都接觸和使用到了Jakarta Commons,不管你自己有沒有察覺。就我所知,除了Apache Jakarta其他許多開源框架之外,不少所謂的商業框架其實內部有些模塊是借用Commons的,甚至有一些完全就是對Commons的類進行了簡單的封裝。如果真的沒有接觸過也不要緊,當你看到它時,你自然會被它的簡單而強大所吸引。

           

          要提高Java編程水平,一條可以走的路就是學習優秀的開源框架。這又要分兩個層面:應用層面和源碼層面。從應用來說,開源的框架大都可以給你帶來生產力和/或代碼質量的大幅提升;從源碼來說,Java開源框架,尤其是那些大型的優秀的框架,其源碼對廣大Java愛好者來說都是一筆巨大的財富,你可以從中學到許多課本上學不到的東西:編碼習慣、代碼組織、注釋、文檔、如何用Java解決實際問題、特定問題的算法,等等。而這些對于我們的作為軟件開發者的實際工作而言,相當有意義。

           

          熟悉Jakarta Commons的朋友可能會覺得現在是不是有點過時,因為有很多功能在J2SE 5.0中已經包含了。其實這個問題看你怎么去看,一方面,J2SE 5.0畢竟是剛出現不久的Java版本,實際應用中,很多時候我們需要把代碼兼容等級維持在1.3或者1.4,所以很多5.0的功能我們暫時還不能放開手腳去使用;另一方面,鑒于Jakarta在一定程度上反映了一線Java開發人員的實際需求,而目前5.0已經采納了其中許多特性,我們當然也有理由相信未來的Java版本還會繼續參照Jakarta Commons的內容。有這么一套開發源碼、免費使用、商業友好的優秀API作為Java自帶API的補充,何樂而不為呢?

           

          我打算在近期陸續做一些Jakarta Commons的學習筆記放上來,供大家參考。

           

          有關Jakarta的最新動態和詳細信息,可以參考:

          http://jakarta.apache.org/commons/index.html

           

           

          posted @ 2005-07-29 12:59 laogao 閱讀(4467) | 評論 (0)編輯 收藏


          在Artima Developer上看到一則關于Jonathan Schwartz提到的Sun計劃將其所有軟件免費提供以促進使用Sun技術的社區發展的消息,有興趣的看看原文吧:

          http://www.artima.com/forums/flat.jsp?forum=270&thread=120325

          posted @ 2005-07-27 17:48 laogao 閱讀(461) | 評論 (1)編輯 收藏


          昨天看了Brad Pitt和Angelina Jolie合演的新片:Mr. & Mrs. Smith。說實在的,我原本對這部片子的期待并不高,一方面我猜想這是just another Hollywood movie而已,另一方面女主演Jolie的風格好像并不是我欣賞的風格,尤其是看了電影公司如何用她糟踏了我曾經一度是我的偶像的Lara Croft之后。然而,事實并非我想象的那樣糟,甚至完全相反,大大超出我的預期不說,還相當讓我喜歡。

          說到這里我插一點題外話:國內的進口電影片名翻譯總是那么不能忠實原著,如果你想不出一個"信、達、雅"的中文名稱,索性就直譯一個"信"的就好,總比一個完全不沾邊的名字強上百倍。在電影院和路邊的宣傳海報上出現的中文片名是:"史密斯行動",而在網上我們看到大陸之外的中文國家、地區通常都采用了"史密斯夫婦"這個忠于原文的中文片名。在中國大陸,最典型的一個例子就是"Enemy At the Gates",我們翻譯成"決戰中的較量",而其它地區都是"兵臨城下",一相比較,孰優孰劣立見分曉。

          話說回來,這部片子雖然也充滿了Hollywood和商業的味道,但是并不讓人反感,至少我不覺得排斥。這部片子演員夠級別,劇本寫得也好,美工和動作特效的處理也很到位,畢竟是2005年的新片大片。總的來說,這部片子夠性感、夠幽默、夠夸張、夠暴力美學。

          貼一張海報和一張很多地方都引用到的劇照:
          mrandmrssmith3.jpg

          mrandmrssmith02.jpg

          posted @ 2005-07-26 09:37 laogao 閱讀(437) | 評論 (0)編輯 收藏


          這個是上個月照的了,由于一直沒時間整理,就擱在一邊。今天心血來潮又翻出來,發現這一張雖然很隨意,但是感覺還不錯:

          Perfume.jpg

          全部的光源就是一盞40W的臺燈,器材為Canon EOS 5、SIGMA 28-70 EX 2.8,Fujifilm 200負片,2.8光圈,1/30秒,手持拍攝。后期底掃后調整過色階,分別按黑、白、灰三處取樣。

          posted @ 2005-07-25 13:20 laogao 閱讀(389) | 評論 (0)編輯 收藏

            

          J2EE應用中有一些常見的毛病和錯誤的觀念,按照時下流行的說法,叫反模式。稍不注意,我們自己也會犯,所以大概整理一下,一個是備忘,也是供需要的朋友參考:

           

          1- EJB不叫J2EE

          EJB一直發展到今天的2.1仍然被廣為詬病,它提供了很多時候我們并不需要的東西,而且我們在很多情況下一旦選用EJB就沒有其他的方式不去使用那些笨重的功能。但是很多所謂范例讓我們有一種錯覺,好像不用EJB就不是J2EE應用。有一些折中的方案是使用Session Fa?ade模式,Entity Bean采用BMP + 本地接口,然后提供一層無狀態的Session Bean,采用遠程和本地接口,這樣的設計模式,我想,多半是出于無奈。如今,甚至我們經常都能看到不使用EJB的言論,炒得很火的Spring則為這種完全不用EJB開發J2EE項目提供了實際的、強有力的佐證。

           

          2- 過度分層

          J2EE這個規范膚淺的來看,就是為我們定義了很多“層”,然后還有很多分工明確的“角色”,加上J2EE的藍本應用程序就分了很多“層”,以至于大家都覺得J2EE的應用就應該是很多層的,其實不然,需要具體情況具體分析。

           

          3- 頻繁的往返調用

          EJB的看似簡單造成我們經常忽略可能在使用過程中出現的遠程調用,比如有時候為了更新一條記錄,每個字段都是遠程的去set,大大增加了不必要的開銷,于是我們意識到在調用中使用DTO是一個建議遵循的方案。

           

          4- 過度使用有狀態的Session Bean

          一般來講,一個Session Bean實例,如果它是有狀態的,那么它只對某個固定的用戶服務,如果是無狀態的,則可以滿足不同用戶的調用。這有點類似(只是有點類似)一個類的靜態方法和非靜態方法的區別。我們在實際應用中,應該盡量避免使用有狀態的Session Bean,除非特別必要。我們可以把狀態保留在Session Bean之外,如Web容器的session對象或者我們自定義的類中,而不是完全依賴有狀態的Session Bean去幫我們做。

           

          5- 過度會話

          Web容器的session對象是個好東西,用起來也很方便和直截了當,這造成了我們很多人對它的濫用,什么東西都往里面放。這有兩個突出的問題,一個是資源浪費;另一個,萬一Web服務器崩潰,那些本來需要持久化的數據就丟失了。我們需要考慮好,哪些數據本可以用request的,哪些數據又是需要持久化到數據庫的,等等,不能一味依賴session。

           

          6- 萬能Servlet或者萬能JSP

          J2EE為我們提供了Web層豐富的技術選擇,Servlet或者JSP都只是其中一種,雖然它很強大,但是也不應該由它一個來承擔所有MVC三個部分的功能?,F實中我們的Struts很好的規范了這個問題:Servlet負責調度,專門的Action負責處理邏輯,而JSP用于用戶界面顯示。JSPServlet本質上是同一個東西,只是從不同的角度來處理問題,它們各有所長,互為補充。

           

           

          posted @ 2005-07-23 17:01 laogao 閱讀(3288) | 評論 (0)編輯 收藏


          眼看做了一年多的項目總算要上線了,自己也該計劃一下項目結束以后要系統學習的東東,粗略地想了一下,應該包括下面這些:

          Eclipse (SWT/JFace/PDE/RCP)
          Hibernate
          JDO
          EJB 3.0 (以及Java EE 5 的其他部分)
          Spring Framework
          JSF
          Tapestry
          XML
          MySQL
          PHP
          Linux

          希望我還不算太貪心。

          posted @ 2005-07-23 15:22 laogao 閱讀(704) | 評論 (4)編輯 收藏


          今天在JDJ上面看到一篇文章,說起一個在Java社區還算是比較新鮮的話題:XML Rich-Client,用XML替代傳統的HTML作為服務器端返回給客戶端的數據載體,它的基本思想有點類似微軟的XAML,在Longhorn (Vista)中將要采用的一種界面配置技術,通過XML文檔構建用戶界面。

          相信大家多少有這種感覺,在服務器端,Java是老大,而客戶端則被MS牢牢控制著。.NET出來以后MS更是利用客戶端(桌面)的優勢向服務器端發起了猛攻,開發.NET應用越來越簡單,功能也越來越強大。現在提的這個XML Rich-Client并不需要很深的Java以及OO的知識,只需修改XML即可改變UI,甚至可以是獨立于特定語言和平臺的(雖然文中沒提,但是筆者認為這就像是Web Services一樣,理論上是平臺中立的),不需要在客戶端下載安裝。也許這就是未來Java在客戶端同MS競爭的一個重要方向?

          原文見:http://java.sys-con.com/read/111208_1.htm
          關于XAML,可以參考:http://www.ondotnet.com/pub/a/dotnet/2004/01/19/longhorn.html

          posted @ 2005-07-23 14:59 laogao 閱讀(1191) | 評論 (0)編輯 收藏


          經過一段時間試用TM,效果并不理想:

          1- 可能是網絡原因,TM的斷線率同樣很高,經常可以看見它在嘗試重新登錄,或者消息發送失??;
          2- 不知道是Windows還是TM處理窗口的方式有問題,經常在你處理其他事務的時候,從你的當前窗口跳轉到TM的窗口,導致你所在的窗口失去焦點,這在你用中文輸入法時尤其讓人不爽;
          3- 偶爾TM會與我的金山詞霸沖突導致系統死機。

          看來要做一款好用而又大眾接受的IM即時通訊軟件想必不是那么容易的一件事吧。

          posted @ 2005-07-13 15:49 laogao 閱讀(508) | 評論 (2)編輯 收藏

          僅列出標題
          共34頁: First 上一頁 25 26 27 28 29 30 31 32 33 下一頁 Last 
          主站蜘蛛池模板: 兴山县| 昭觉县| 白山市| 苍梧县| 武威市| 习水县| 临颍县| 饶平县| 丰台区| 安阳县| 广灵县| 台江县| 宁阳县| 濉溪县| 乌兰县| 威远县| 合作市| 盐山县| 巴东县| 连平县| 衡南县| 宁远县| 措美县| 青田县| 扎鲁特旗| 饶河县| 花垣县| 化州市| 齐河县| 大足县| 西林县| 廊坊市| 兴文县| 溧阳市| 准格尔旗| 如皋市| 习水县| 南华县| 建宁县| 景洪市| 图木舒克市|