和風細雨

          世上本無難事,心以為難,斯乃真難。茍不存一難之見于心,則運用之術自出。

          #

          JTabbedPane選項窗格的使用

          選項窗格JTabbedPane

          JTabbedPane在Swing中實現(xiàn)選項窗格,它可以把多個組件放在多個選項卡中,從而使頁面不致?lián)頂D,其選項卡的形式也能為程序增色不少。
          選項窗格和分隔窗格類似,創(chuàng)建出來需要添加到設置好布局的面板中,通常我們可以設置布局為1*1的網(wǎng)格布局或是邊界布局。
          選項窗格內部可以放置多個選項頁,每個選項頁都可以容納一個JPanel作為子組件,我們只要設計好需要添加到選項頁的面板即可。

          JTabbedPane效果

          創(chuàng)建JTabbedPane

          // 創(chuàng)建選項窗格
          JTabbedPane tabPane = new JTabbedPane();

          // 設置面板布局為網(wǎng)格布局
          this.setLayout(new GridLayout(1,1));
          tabPane.setTabPlacement(JTabbedPane.TOP);// 設定選項卡放在上部
          this.add(tabPane);// 將選項窗格放置在面板中 

          // 創(chuàng)建一個StockPanel面板并添加到選項窗格,這是指定圖標的方法
          StockPanel stockPanel=new StockPanel();
          tabPane.addTab("庫存頁面", new ImageIcon(TabbedPanel.class
            .getResource("/stock.gif")), stockPanel);

          ImportPanel importPanel=new ImportPanel();
          tabPane.addTab("進貨頁面", new ImageIcon(TabbedPanel.class
            .getResource("/import.gif")), importPanel);

          // 創(chuàng)建一個SaledPanel面板并添加到選項窗格,這是不指定圖標的方法
          SaledPanel saledPanel=new SaledPanel();
          tabPane.addTab("已售頁面",  saledPanel);

          // 選擇第一個選項頁為當前選擇的選項頁
          tabPane.setSelectedIndex(0);

          posted @ 2008-03-03 22:57 和風細雨 閱讀(14913) | 評論 (23)編輯 收藏

          泛型類(Generic Class)

          C++模版(Template)類在Java中的體現(xiàn)-泛型類

          泛型類是C++模版(Template)類思想在java新版本(1.5)中的應用體現(xiàn).當對類型相同的對象操作時泛型是很有用的,但其中對象的具體類型直到對類實例化時才能知道.這種方式非常適合于包含關聯(lián)項目的集合或設計查找的類.

          泛型類的使用示例一

          /**
           * 泛型類示例一,成員變量為鏈表,T可以指代任意類類型.
           * @author sitinspring
           *
           * @date 2007-12-28
           */
          public class Service<T>{
            // 元素為T的鏈表
            private List<T> elements;
           
            /**
             * 構造函數(shù),這里無須指定類型
             *
             */
            public Service(){
              elements=new ArrayList<T>();
            }
           
            /**
             * 向鏈表中添加類型為T的元素
             * @param element
             */
            public void add(T element){
              elements.add(element);
            }
          /**
             * 打印鏈表中元素
             *
             */
            public void printElements(){
              for(T t:elements){
                System.out.println(t);
              }
            }
           
          /**
             * 使用示例
             * @param args
             */
            public static void main(String[] args){
              // 創(chuàng)建Service類的示例memberService
              Service<Member> memberService=new Service<Member>();
             
              // 向memberService中添加元素
              memberService.add(new Member("Andy",25));
              memberService.add(new Member("Bill",24));
              memberService.add(new Member("Cindy",55));
              memberService.add(new Member("Felex",35));
             
              // 打印memberService中諸元素
              memberService.printElements();
            }
          }

          泛型類的使用示例二

          /**
           * 泛型類示例二,成員變量為哈希表,k,v可以指代任意類類型.
           * @author sitinspring
           *
           * @date 2007-12-28
           */
          public class ServiceHt<K,V>{
            private Map<K,V> elements;
           
            /**
             * 向elements中添加元素
             * @param k
             * @param v
             */
            public void add(K k,V v){
              // 如果elements為空則創(chuàng)建元素
              if(elements==null){
                elements=new Hashtable<K,V>();
              }
             
              // 向elements中添加鍵值對
              elements.put(k, v);
            }
           /**
             * 打印哈希表中的元素
             *
             */
            public void printElements(){
              Iterator it=elements.keySet().iterator();
             
              while(it.hasNext()){
                K k=(K)it.next();
                V v=elements.get(k);
               
                System.out.println("鍵="+k+" 值="+v);
              }
            }

            /**
             * 使用示例
             * @param args
             */
            public static void main(String[] args){
              // 創(chuàng)建Service類的示例memberService
              ServiceHt<String,Member> memberService=new ServiceHt<String,Member>();
             
              // 向memberService中添加元素
              memberService.add("Andy",new Member("Andy",25));
              memberService.add("Bill",new Member("Bill",24));
              memberService.add("Cindy",new Member("Cindy",55));
              memberService.add("Felex",new Member("Felex",35));
             
              // 打印memberService中諸元素
              memberService.printElements();
            }
          }

          posted @ 2008-03-03 22:55 和風細雨 閱讀(633) | 評論 (0)編輯 收藏

          分隔窗格JSplitPane

          JSplitPane可以顯示兩個組件,可以并排或上下顯示,通過拖動出現(xiàn)在兩個組件之間的分隔器,用戶可以指定分隔窗格為每一個組件分配多少空間.通過在分隔窗格內設置分隔窗格,可以將屏幕空間分隔成三個或更多的組件.
          除了直接將組件添加到分隔窗格外,通常會將每個組件放置在一個滾動窗格中,這使用戶能拖動滾動條查看組件的任何部分.



          創(chuàng)建分隔窗格示例

          // 創(chuàng)建分隔窗口,第一個參數(shù)指定了分隔的方向,JSplitPane.HORIZONTAL_SPLIT表示水平分隔,另外一個選項是JSplitPane.VERTICAL_SPLIT,表示垂直分隔;另外兩個參數(shù)是放置在該分隔窗格的組件.
          JSplitPane splitPanel = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, tablePanel, textPanel);

          // 設置分隔器的位置,可以用整數(shù)(像素)或百分比來指定.
          splitPanel.setDividerLocation(200);

          // 設置分隔器是否顯示用來展開/折疊分隔器的控件
          splitPanel.setOneTouchExpandable(true);

          // 設置分隔器的大小,單位為像素
          splitPanel.setDividerSize(5);

          // 將分隔窗口添加到容器中
          setLayout(new BorderLayout());
          add(splitPanel, BorderLayout.CENTER);

           

          posted @ 2008-03-03 22:52 和風細雨 閱讀(2172) | 評論 (0)編輯 收藏

          Swing中添加事件響應的三種處理方式說明

          舉例說明事件響應

          在Swing中,事件響應是通過監(jiān)聽器對象來處理事件的方式實行的,這種方式被稱為事件委托模型.

          以JButton舉例,它內部有一個名為listenerList的鏈表,在點擊按鈕時,會產(chǎn)生一個ActionEvent事件,此后內部會依次調用位于listenerList中的每一個actionListener子類實例的actionPerformed方法,這就是事件響應的過程.

          當調用JButton的addActionListener方法時, 外界actionListener子類實例的指針就被放入了listenerList中,當按鈕點擊事件產(chǎn)生時,這個實例的actionPerformed方法就會被調用,從而按鈕的點擊事件處理就被委托到了actionListener子類實例中進行處理.

          實現(xiàn)ActionListener的三種方式

          1.實現(xiàn)一個ActionListener子類,再把按鈕的事件響應委托給這個子類的實例處理.這種方式并不常用,我在這里列出是為了教學.

          2.讓界面類實現(xiàn)ActionListener接口,再把事件響應委托給界面類.這種方式適合于處理一些短小簡單或要求內聚的事件響應.

          3.用匿名類實現(xiàn)ActionListener接口,再把事件委托給這個匿名類的實例.這種方式是Swing事件處理的主流.


          方式一:實現(xiàn)一個ActionListener子類

          // 實現(xiàn)了ActionListener接口的類
          public class Button3ActionListener implements ActionListener{
            public void actionPerformed(ActionEvent e) {
              String buttonText=((JButton)e.getSource()).getText();
             
              System.out.println("你按下了" + buttonText);
            }
          }

          // 給按鈕三添加事件處理
          button3.addActionListener(new Button3ActionListener());

          方式二:讓界面類實現(xiàn)ActionListener接口

          public class MyFrame extends JFrame implements ActionListener{
            public MyFrame() {
              ....
              button2.addActionListener(this);
            }
           
            /**
             * 按鈕二的事件響應在此
             */
            public void actionPerformed(ActionEvent e) {
              if(e.getSource()==button2){
                showMsg("你按下了" + button2.getText());
              }  
            }
          }

          方式三:用匿名類的方式添加事件響應

          button1 = new JButton("按鈕一");

          button1.addActionListener(new ActionListener() {
                public void actionPerformed(ActionEvent e) {
                  showMsg("你按下了" + button1.getText());
                }
          });

           

          posted @ 2008-03-03 22:49 和風細雨 閱讀(3700) | 評論 (0)編輯 收藏

          使用JFrame創(chuàng)建窗口

          Java.swing包中的JFrame類對于創(chuàng)建窗口很有效,它繼承Container類,能夠包含其它的組件.

          右邊顯示了創(chuàng)建窗口的代碼和JFrame的幾個常用函數(shù).

          public class MyFrame extends JFrame {
            private static final long serialVersionUID = 1379963724699883220L;

            /**
             * 構造函數(shù)
             *
             */
            public MyFrame() {
              // 設置窗口標題
              this.setTitle("程序標題");

              // 定位窗口
              this.setLocation(20, 20);
             
              // 設置窗口大小
              this.setSize(480, 320);
             
              // 顯示窗口
              setVisible(true);
            }
           
            public static void main(String[] args){
              new MyFrame();
            }
          }

          將窗口定位在屏幕正中

          使用Toolkit.getDefaultToolkit().getScreenSize()方法可以取得屏幕的大小,再調用setLocation函數(shù)可以將程序定位在屏幕正中.

          public class MyFrame extends JFrame {
            private static final long serialVersionUID = 1379963724699883220L;

            /**
             * 構造函數(shù)
             *
             */
            public MyFrame() {
              // 設置窗口標題
              this.setTitle("程序標題");

              // 設置程序大小并定位程序在屏幕正中
              setSizeAndCentralizeMe(480, 320);
             
              // 顯示窗口
              setVisible(true);
            }
           
            // 設置程序大小并定位程序在屏幕正中
            private void setSizeAndCentralizeMe(int width, int height) {
              Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
              this.setSize(width, height);
              this.setLocation(screenSize.width / 2 - width / 2, screenSize.height
                  / 2 - height / 2);
            }
           
            public static void main(String[] args){
              new MyFrame();
            }
          }

          點擊窗口右上角的關閉按鈕關閉窗口,退出程序

          setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE)可以達到此功能,否則按關閉按鈕窗口關閉但不退出程序.

          public class MyFrame extends JFrame {
            private static final long serialVersionUID = 1379963724699883220L;

            /**
             * 構造函數(shù)
             *
             */
            public MyFrame() {
              // 設置窗口標題
              this.setTitle("程序標題");

              // 設置程序大小并定位程序在屏幕正中
              setSizeAndCentralizeMe(480, 320);
             
              // 顯示窗口
              setVisible(true);
             
              // 點擊窗口右上角的關閉按鈕關閉窗口,退出程序
              this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            }
           
            // 設置程序大小并定位程序在屏幕正中
            private void setSizeAndCentralizeMe(int width, int height) {
              Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
              this.setSize(width, height);
              this.setLocation(screenSize.width / 2 - width / 2, screenSize.height
                  / 2 - height / 2);
            }
           
            public static void main(String[] args){
              new MyFrame();
            }
          }

          添加窗口關閉事件處理

          // 點擊窗口右上角的關閉按鈕關閉窗口,退出程序
              this.addWindowListener(new WindowAdapter() {
                public void windowClosing(WindowEvent e) {
                  System.out.println("程序退出.");
                  System.exit(0);
                }
              });

          上面的代碼實現(xiàn)了一個WindowAdapter的匿名類,并將它注冊為窗口事件的監(jiān)聽器.

          public class MyFrame extends JFrame {
            private static final long serialVersionUID = 1379963724699883220L;

            /**
             * 構造函數(shù)
             *
             */
            public MyFrame() {
              // 設置窗口標題
              this.setTitle("程序標題");

              // 設置程序大小并定位程序在屏幕正中
              setSizeAndCentralizeMe(480, 320);

              // 顯示窗口
              setVisible(true);

              // 點擊窗口右上角的關閉按鈕關閉窗口,退出程序
              this.addWindowListener(new WindowAdapter() {
                public void windowClosing(WindowEvent e) {
                  System.out.println("程序退出.");
                  System.exit(0);
                }
              });
            }

            // 設置程序大小并定位程序在屏幕正中
            private void setSizeAndCentralizeMe(int width, int height) {
              Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
              this.setSize(width, height);
              this.setLocation(screenSize.width / 2 - width / 2, screenSize.height
                  / 2 - height / 2);
            }

            public static void main(String[] args) {
              new MyFrame();
            }
          }

          設置程序感觀

          UIManager.getInstalledLookAndFeels()可得到可用的感觀數(shù)組,然后取數(shù)組中元素的getClassName()方法可得到感觀類名,再調用
          UIManager.setLookAndFeel(strLookFeel);      SwingUtilities.updateComponentTreeUI(this);
          方法可設置窗口感觀.

          public class MyFrame extends JFrame {
            /**
             * 構造函數(shù)
             *
             */
            public MyFrame() {
              // 設置窗口標題
              this.setTitle("程序標題");

              // 設置程序大小并定位程序在屏幕正中
              setSizeAndCentralizeMe(480, 320);

              // 顯示窗口
              setVisible(true);

              // 設置程序感觀
              setupLookAndFeel();

              ....;
            }
          ...

            // 設置程序感觀
            private void setupLookAndFeel() {
              // 取得系統(tǒng)當前可用感觀數(shù)組
              UIManager.LookAndFeelInfo[] arr = UIManager.getInstalledLookAndFeels();
             
              Random random = new Random();
              String strLookFeel=arr[random.nextInt(arr.length)].getClassName();

              try {
                UIManager.setLookAndFeel(strLookFeel);
                SwingUtilities.updateComponentTreeUI(this);
              } catch (Exception e) {
                System.out.println("Can't Set Lookandfeel Style to " + strLookFeel);
              }
            }
          ....
          }

          設置程序感觀為跨平臺的感觀

          UIManager.getCrossPlatformLookAndFeelClassName()可得到跨平臺的感觀.

          public class MyFrame extends JFrame {
            public MyFrame() {
              // 設置窗口標題
              this.setTitle("程序標題");

              // 設置程序大小并定位程序在屏幕正中
              setSizeAndCentralizeMe(480, 320);

              // 顯示窗口
              setVisible(true);

              // 設置程序感觀
              setupLookAndFeel();
            }

            // 設置程序感觀
            private void setupLookAndFeel() {
              String strLookFeel = UIManager.getCrossPlatformLookAndFeelClassName();

              try {
                UIManager.setLookAndFeel(strLookFeel);
              } catch (Exception e) {
                System.out.println("Can't Set Lookandfeel Style to " + strLookFeel);
              }
            }
          }

          posted @ 2008-03-03 22:46 和風細雨 閱讀(6770) | 評論 (0)編輯 收藏

          Swing常用組件

          面板類JPanel

          JPanel類常用來作為一批組件如JButton,JTextBox等的容器,一般來說對它的常見操作有設置其邊框,設置其布局等.

          設置邊框代碼:
          setBorder(BorderFactory.createTitledBorder(title));

          設置布局代碼示例:
          setLayout(new GridLayout(4, 1));
          add(nameInputPanel);
          add(ageInputPanel);
          add(titleInputPanel);
          add(ButtonsPanel);

          按鈕類JButton

          當我們需要向界面添加按鈕時需要用到JButton類.以下是它的一些常用方法

          1.創(chuàng)建Button類實例
          JButton csvButton=new JButton("csv下載");

          2.設置按鈕的最大尺寸,最小尺寸,首選尺寸.
          Dimension dimension = new Dimension(80, 20);
          csvButton.setMaximumSize(dimension);
          csvButton.setMinimumSize(dimension);
          csvButton.setPreferredSize(dimension);

          單選框JRadioButton

          我們需要單選按鈕時需要用到JRadioButton,它的常用方法如下:
          1.創(chuàng)建
          JRadioButton xmlRadio=new JRadioButton("Xml",true);
          JRadioButton db4oRadio=new JRadioButton("Db4o",false);

          2.分組
          ButtonGroup group = new ButtonGroup();
          group.add(xmlRadio);
          group.add(db4oRadio);
          group.add(sqlRadio);
          group.add(hibenateRadio);

          3.取得單個JRadioButton是否被選擇
          boolean isSelected=db4oRadio.isSelected()

          4.取得一組JRadioButton中被選擇的單元的文字
                  for (Enumeration e=group.getElements(); e.hasMoreElements(); ) {
                      JRadioButton b = (JRadioButton)e.nextElement();
                      if (b.getModel() == group.getSelection()) {
                          return b.getText();
                      }
                  }

          標簽組件JLabel

          JLabel是標簽控件,也是Swing組件中最簡單常用的一個.

          創(chuàng)建JLabel:
          JLabel label=new JLabel(“ABC");

          修改標簽文字
          label.setText("DEF");

          單行文本框JTextField

          需要輸入單行文字時我們可以用到JTextField,它的使用也很簡單.
          創(chuàng)建:
          JTextField textBox=new JTextField();

          設置文本框文字:
          textBox.setText("ABC");

          取得文本框文字:
          String text=textBox.getText();

          復合框JComboBox

          JComboBox是既能提供輸入又能提供選擇一項的選擇控件.

          1) 創(chuàng)建JComboBox
          String[] items = {"item1", "item2"};
          JComboBox editableCB = new JComboBox(items); editableCB.setEditable(true);

          表格控件JTable

          表格控件是相對復雜的Swing控件之一,使用也相對復雜.

          1) 創(chuàng)建表格控件
          JTable table = new JTable();

          2) 設置表格行高
          table.setRowHeight(20);

          3) 設置表格的行數(shù)和列數(shù)
          DefaultTableModel tableModel = (DefaultTableModel) table
          .getModel();
          tableModel.setColumnCount(0);
          tableModel.setRowCount(0);

          4) 給表格添加表頭
          String[] headers = {"姓名","年齡", "職務"};

          for (int i = 0; i < headers.length; i++) {
                tableModel.addColumn(headers[i]);
          }

          5) 向表格添加內容
           public void fillTable(List<Member> members){
              DefaultTableModel tableModel = (DefaultTableModel) table
              .getModel();
              tableModel.setRowCount(0);
             
              for(Member member:members){
                String[] arr=new String[5];
                arr[0]=member.getName();
                arr[1]=member.getAge();
                arr[2]=member.getTitle();
               
                tableModel.addRow(arr);
              }
             
              table.invalidate();
            }

          6) 取得表格內的內容
          public List<Member> getShowMembers(){
              List<Member> members=new ArrayList<Member>();
             
              DefaultTableModel tableModel = (DefaultTableModel) table
              .getModel();
             
              int rowCount=tableModel.getRowCount();
             
              for(int i=0;i<rowCount;i++){
                Member member=new Member();
                member.setName((String)tableModel.getValueAt(i, 0));
                member.setAge((String)tableModel.getValueAt(i, 1));
                member.setTitle((String)tableModel.getValueAt(i, 2));
               
                members.add(member);
              }
             
              return members;
            }


           

          posted @ 2008-03-03 22:42 和風細雨 閱讀(1187) | 評論 (0)編輯 收藏

          字符串比較 ==與equals辨析

          字符串比較

          字符串比較是java程序常遇到的問題,新手常用==進行兩個字符串比較,實際上這時進行的地址比較,不一定會返回正確結果.在java中,正確的進行字符串比較的函數(shù)String類的equals()函數(shù),這才是真正的值比較.

          ==的真正意義

          Java中,==用來比較兩個引用是否指向同一個內存對象.對于String的實例,運行時JVM會盡可能的確保任何兩個具有相同字符串信息的String實例指向同一個內部對象,此過程稱為”駐留”(interning),但它不助于每個String實例的比較.一個原因是垃圾收集器刪除了駐留值,另一個原因是String所在的位置可能被別的String實例所取代.這樣的話,==將不會返回預想的結果.
          下頁的示例說明了這個問題:

          ==和equals比較的示例


          String str1,str2,str3;

          str1
          ="Andy";

          str2
          =str1;

          if(str1==str2){
          System.out.println(
          "str1,str2地址相等");
          }

          if(str1.equals(str2)){
          System.out.println(
          "str1,str2值相等");
          }


          str2
          =“Andy”;
          if(str1==str2){
          System.out.println(
          "str1,str2通常地址相等");
          }

          if(str1.equals(str2)){
          System.out.println(
          "str1,str2值一定相等");
          }


          str3
          =new String("Andy");
          if(str1==str3){
          System.out.println(
          "str1,str3地址相等");
          }

          else{
          System.out.println(
          "str1,str3地址不相等");
          }


          if(str1.equals(str3)){
          System.out.println(
          "str1,str3值一定相等");
          }




          結論

          從上面的例子可以看出,==比較的是地址,在駐留機制的作用下,也許返回正確的結果,但并不可靠,這種不確定性會隱藏在陰暗的角落里,在你以為萬事大吉時給你致命一擊.
          而equal始終進行值比較,它一定會返回正確的結果,無論在什么情況下.

          我們應該記住:為了保證程序的正確,進行字符串比較時一定要使用equals,而一定不能使用==.

          posted @ 2008-03-03 22:38 和風細雨 閱讀(780) | 評論 (0)編輯 收藏

          異常機制綜述

          在運行過程中,應用程序可能遭遇各種嚴重程度不同的問題.異常提供了一種在不弄亂程序的情況下檢查錯誤的巧妙方式.它也提供了一種直接報告錯誤的機制,而不必檢查標志或者具有此作用的域.異常把方法能夠報告的錯誤作為方法約定的一個顯式部分.
          異常能夠被程序員看到,由編譯器檢查,并且由重載方法的子類保留.
          如果遇到意外的錯誤將拋出異常,然后異常被方法調用棧上的子句捕獲.如果異常未被捕獲,將導致執(zhí)行線程的終止.

          異常的體系結構

          毫無疑問,在java中異常是對象,它必定繼承Throwable及其子類.Throwable中含有一個用于描述異常的字符串.Exception是Throwable的一個最常用子類,另一個子類是Error.而RuntimeException繼承自Exception.



          異常的種類

          非檢查型異常(Unchecked Exception):
          非檢查型異常反映了程序中的邏輯錯誤,不能從運行中合理恢復.
          標準的運行時異常和錯誤構成非檢查型異常,它們繼承自RuntimeException和Error.
          非檢查型異常不用顯示進行捕獲.

          檢查型異常(Checked Exception):
          這種異常描述了這種情況,雖然是異常的,但被認為是可以合理發(fā)生的,如果這種異常真的發(fā)生了,必須調用某種方法處理.
          Java異常大多是檢查型異常,繼承自Exception類,你自己定義的異常必須是繼承Exception的檢查型異常.
          檢查型異常必須進行顯示捕獲.

          自定義異常

          繼承Exception即可定義自己的異常,以下是一種常見寫法
          public class DBXmlFileReadException extends Exception{
            public DBXmlFileReadException(String   msg){
              super(msg);
            }
          }


          拋出異常

          在Java語句中,可以用throw語句拋出異常,如throw new NoSuchElementException();
          拋出的對象必須是Throwable類的子類型.

          拋出異常的策略:
          1) 如果拋出后不可能得到處理,可以拋出Error.
          2) 如果你想讓其它類自由選擇是否處理這個異常,就可以拋出RuntimeException.
          3) 如果你要求類的用戶必須處理這個異常,則可以拋出Exception.

          異常拋出后的控制權轉移

          一旦發(fā)生異常,異常發(fā)生點后的動作將不會發(fā)生.此后將要發(fā)生的操作不是在catch塊和finally塊.

          當異常拋出時,導致異常發(fā)生的語句和表達式就被稱為突然完成.語句的突然完成將導致調用鏈逐漸展開,直到該異常被捕獲.

          如果該異常沒有捕獲,執(zhí)行線程將中止.

          Try,catch和finally

          異常由包含在try塊中的語句捕獲:
              try{
                正常執(zhí)行語句
              }
              catch(XException e){
                異常執(zhí)行語句一
              }
              catch(XXException e){
                異常執(zhí)行語句二
              }
              catch(XXXException e){
                異常執(zhí)行語句三
              }
              finally{
                中止語句
              }

          Try中的語句體要么順利完成,要么執(zhí)行到拋出異常.
          如果拋出異常,就要找出對應于異常類或其父類的catch子句,如果未能找到合適的catch子句,異常就從try語句中擴散出來,進入到外層可能對它進行處理的try語句.
          Catch子句可以有多個,只要這些子句捕獲的異常類型不同.
          如果在try中有finally子句,其代碼在try把所有其它處理完成之后執(zhí)行.
          無論是正常完成或是出現(xiàn)異常,甚至是通過return或者break這樣的控制語句結束,finally子句總是被執(zhí)行.
          Catch子句和finally子句在try語句之后至少有一個,不要求全部出現(xiàn).

          More…

          在catch語句中捕獲通用的異常Exception通常不是最佳策略,因為它會將所有異常進行等同處理.
          不能把基類異常的catch語句放到子類異常的catch語句之前,編譯器會在運行之前就檢查出這樣的錯誤.
          Try…catch對每個catch語句都從頭到尾檢查,如果找到處理同類異常的catch子句,此catch塊中的語句將得以執(zhí)行,而不再處理同層次的其它catch塊.
          如果catch或finally拋出另一個異常,程序將不會再去檢查try的catch子句.
          Try...catch語句可以嵌套,內層拋出的異常可被外層處理.

          Throws子句

          函數(shù)能拋出的檢查型異常用throws聲明,它后面可以是帶用逗號隔開的一系列異常類型.僅僅那些在方法中不被捕獲的異常必須列出.

          private void readObject(java.io.ObjectInputStream s)
                  throws java.io.IOException, ClassNotFoundException {
                  // Read in any hidden serialization magic
                  s.defaultReadObject();

                  // Read in size
                  int size = s.readInt();

                  // Initialize header
                  header = new Entry<E>(null, null, null);
                  header.next = header.previous = header;

                  // Read in all elements in the proper order.
                  for (int i=0; i<size; i++)
                       addBefore((E)s.readObject(), header);
                  }
          }

          More…

          Throws子句的約定是嚴格強制性的,只能拋出throws子句中聲明的異常類型,拋出其它類型的異常是非法的,不管是直接利用throw,還是調用別的方法間接的拋出.
          RuntimeException和Error是僅有的不必由throws子句列出的異常.
          調用函數(shù)的函數(shù)要么處理對聲明的異常進行處理,要么也聲明同樣的異常,將收到的異常拋向上層.

          對檢查型異常通常進行的幾種處理

          1) 用e.printStackTrace()輸出異常信息.
          2) 將異常記錄到日志中以備查,如logger.error(e.getMessage()).
          3) 試圖進行異常恢復.
          4) 告知維護者和用戶發(fā)生的情況.

          posted @ 2008-03-03 22:34 和風細雨 閱讀(313) | 評論 (0)編輯 收藏

          嵌套類和匿名類

          嵌套類和匿名類

          內部類的出現(xiàn)
          當進行Java開發(fā)時,有時需要實現(xiàn)一個僅包含1-2個方法的接口.在AWT和Swing開發(fā)中經(jīng)常出現(xiàn)這種情況,例如當一個display組件需要一個事件回調方法如一個按鈕的ActionListener時. 如果使用普通的類來實現(xiàn)此操作,最終會得到很多僅在單個位置上使用的小型類.
          內部類用于處理這種情況,java允許定義內部類,而且可在Gui外使用內部類.

          內部類的定義和實現(xiàn)

          內部類是指在另一個類內部定義的一個類.可以將內部類定義為一個類的成員.
          public class Linker{
            public class LinkedNode{
              private LinkedNode prev;
              private LinkedNode next;
              private String content;
             
              public LinkedNode(String content){
                this.content=content;
              }
            }
           
            public Linker(){
              LinkedNode first=new LinkedNode("First");
              LinkedNode second=new LinkedNode("Second");
             
              first.next=second;
              second.prev=first;
            }
          }

          定義在一個類方法中的內部類

          public class Hapiness{
            interface Smiler{
              public void smile();
            }
           
            public static void main(String[] args){
              class Happy implements Smiler{
                public void smile(){
                  System.out.println(":-}");
                }
              }
             
              Happy happy=new Happy();
              happy.smile();
            }
          }

          匿名類

          對很多情況而言,定義在方法內部的類名意義不大,它可以保持為匿名的,程序員關心的只是它的實例名.
          如:
          Runnable runner=new Runnable(){
               public void  run(){
                    // Run statememnt
               }
          }

          理解匿名類

          匿名類并不難理解,它只是把類的定義過程和實例的創(chuàng)建過程混合而已,上頁的語句實際上相當于如下語句:
          // 定義類
          Public class Runner implements Runnable{
               public void run(){
                   // do sth
                }
          }

          // 創(chuàng)建實例
          Runner runner=new Runner();

          使用匿名類的篩選解耦過程

          需求:從公司的職員列表中,找出男性且年齡大于22的成員.

          傳統(tǒng)寫法:

             List allmembers=company.getMembers();// 取得所有成員
              List results=new ArrayList();// 結果列表
             
              for(Iterator it=allmembers.iterator();it.hasNext();){
               Member member=(Member)it.next();
              
               if(member.getAge()>22 && member.isMale()){  // 篩選,這里是把查詢條件和遴選過程融合在一起,條件一變立即就得加個分支.
                results.add(member);
               }
             }

          傳統(tǒng)方法的缺陷

          這種寫法沒有錯,但是不是面向對象的寫法,它有以下缺陷:
          1.查詢條件和篩選過程沒有分離.
          2.這樣寫的后果使Company變成了一個失血模型而不是領域模型.
          3.換查詢條件的話,上面除了"篩選"一句有變化外其它都是模板代碼,重復性很高.

          使用匿名類實現(xiàn)的OO化查詢

          真正符合OO的查詢應該是這樣:

             MemberFilter filter1=new MemberFilter(){
              public boolean accept(Member member) {
                   return member.isMale() && member.getAge()>22;
              }
             };
            
             List ls=company.listMembers(filter1);
           

          這段代碼成功的把查詢條件作為一個接口分離了出去,接口代碼如下:

          public interface MemberFilter{
            public boolean accept(Member member);
          }

          查詢函數(shù)的變化

          而類Company增加了這樣一個函數(shù):

          public List searchMembers(MemberFilter memberFilter){
             List retval=new ArrayList();
             
              for(Iterator it=members.iterator();it.hasNext();){
               Member member=(Member)it.next();
              
               if(memberFilter.accept(member)){
                retval.add(member);
              }
             } 
            
             return retval;
          }
          這就把模板代碼歸結到了類內部,外面不會重復書寫了.Company也同時擁有了數(shù)據(jù)和行為,而不是原來的數(shù)據(jù)容器了.


          匿名類的例子二

          用匿名類處理分類匯總的方法 分類匯總是統(tǒng)計中常用,舉例來說如統(tǒng)計學生成績,及格不及格的歸類,分優(yōu)良中差等級歸類等,每個單項代碼很好寫,但是如果分類匯總的項目多了,能一種匯總寫一個函數(shù)嗎? 比如說有些科目60分才算及格,有些科目50分就算;有些老師喜歡分優(yōu)良中差四等,有些老師卻喜歡分ABCD;不一而足,如果每個都寫一個函數(shù)無疑是個編寫和維護惡夢. 如果我們用匿名類把分類匯總的規(guī)則和分類匯總的過程分別抽象出來,代碼就清晰靈活多了,以下代碼講述了這個過程.

          基本類Student

          public class Student{
              private String name;
              private int score;
             
              public Student(String name,int score){
                  this.name=name;
                  this.score=score;
              }
             
              public String getName() {
                  return name;
              }
              public void setName(String name) {
                  this.name = name;
              }
              public int getScore() {
                  return score;
              }
              public void setScore(int score) {
                  this.score = score;
              }   
          }


          用于分類匯總的類

          它強制子類實現(xiàn)getKey和getvalue兩個方法:
          public abstract class ClassifyRule {
              public Student student;
             
              public ClassifyRule(){       
              }   

              public void setStudent(Student student) {
                  this.student = student;
              }
             
              abstract public String getKey();
              abstract public int getValue();
          }

          對Student進行統(tǒng)計處理的StudentService類

          注意getSum方法,它保留了篩選過程,篩選規(guī)則則不在其中:
          import java.util.ArrayList;
          import java.util.Hashtable;
          import java.util.List;

          public class StudentService {
              private List<Student> students;

              public StudentService() {
                  students = new ArrayList<Student>();
              }

              public void add(Student student) {
                  students.add(student);
              }

              public Hashtable<String, Integer> getSum(ClassifyRule rule) {
                  Hashtable<String, Integer> ht = new Hashtable<String, Integer>();

                  for (Student student : students) {
                      rule.setStudent(student);
                      String key = rule.getKey();
                      int value = rule.getValue();

                      if (ht.containsKey(key)) {
                          Integer oldValue = ht.remove(key);
                          oldValue += value;
                          ht.put(key, oldValue);
                      } else {
                          ht.put(key, value);
                      }
                  }

                  return ht;
              }
          }

          測試代碼,注意其中篩選規(guī)則的創(chuàng)建

          public class Test {
              public static void main(String[] args) {
                  // 初始化
                  StudentService service = new StudentService();
                  service.add(new Student("Andy", 90));
                  service.add(new Student("Bill", 95));
                  service.add(new Student("Cindy", 70));
                  service.add(new Student("Dural", 85));
                  service.add(new Student("Edin", 60));
                  service.add(new Student("Felix", 55));
                  service.add(new Student("Green", 15));

                  // 60分及格篩選
                  ClassifyRule rule60 = new ClassifyRule() {
                      public String getKey() {
                          return student.getScore() >= 60 ? "及格" : "不及格";
                      }

                      public int getValue() {
                          return 1;
                      }
                  };

                  System.out.println("60分及格篩選");
                  printHt(service.getSum(rule60));

                  // 50分及格篩選
                  ClassifyRule rule50 = new ClassifyRule() {
                      public String getKey() {
                          return student.getScore() >= 50 ? "及格" : "不及格";
                      }

                      public int getValue() {
                          return 1;
                      }
                  };
                  System.out.println("\n50分及格篩選");
                  printHt(service.getSum(rule50));

                  // 分"優(yōu)良中差"等級
                  ClassifyRule ruleCn = new ClassifyRule() {
                      public String getKey() {
                          String retval = "";

                          int score = student.getScore();
                          if (score >= 90) {
                              retval = "優(yōu)";
                          } else if (score >= 80) {
                              retval = "良";
                          } else if (score >= 60) {
                              retval = "中";
                          } else if (score > 0) {
                              retval = "差";
                          }

                          return retval;
                      }

                      public int getValue() {
                          return 1;
                      }
                  };

          測試代碼

          System.out.println("\n分優(yōu)良中差等級篩選");
                  printHt(service.getSum(ruleCn));

                  // 分"ABCD"等級
                  ClassifyRule ruleWest = new ClassifyRule() {
                      public String getKey() {
                          String retval = "";

                          int score = student.getScore();
                          if (score >= 90) {
                              retval = "A";
                          } else if (score >= 80) {
                              retval = "B";
                          } else if (score >= 60) {
                              retval = "C";
                          } else if (score > 0) {
                              retval = "D";
                          }

                          return retval;
                      }

                      public int getValue() {
                          return 1;
                      }
                  };

                  System.out.println("\n分ABCD等級篩選");
                  printHt(service.getSum(ruleWest));
              }

              private static void printHt(Hashtable ht) {
                  for (Iterator it = ht.keySet().iterator(); it.hasNext();) {
                      String key = (String) it.next();
                      Integer value = (Integer) ht.get(key);
                      System.out.println("Key=" + key + " Value=" + value);
                  }
              }
          }


          測試結果如下:

           

          60分及格篩選
          Key=及格 Value=5
          Key=不及格 Value=2

          50分及格篩選
          Key=及格 Value=6
          Key=不及格 Value=1

          分優(yōu)良中差等級篩選
          Key=優(yōu) Value=2
          Key=良 Value=1
          Key=中 Value=2
          Key=差 Value=2

          分ABCD等級篩選
          Key=A Value=2
          Key=D Value=2
          Key=C Value=2
          Key=B Value=1

          后記

          內部類也叫嵌套類,一般不提倡書寫,但它在java核心類中都存在,如接口Map中的Entry,我們應該了解并能解讀這種方法.

          匿名類相對而言有用得多,在解耦合和事件回調注冊中很常見,大家應該對它的運用融會貫通.

          posted @ 2008-03-03 22:30 和風細雨 閱讀(322) | 評論 (0)編輯 收藏

          在JavaScript中使用正則表達式驗證表單字段

          JavaScript中對正則表達式的支持
          正則表達式在JS的最大用處就是驗證表單字段,如驗證數(shù)字,驗證郵件和驗證漢字等。
          JavaScript中對正則表達式的支持是通過RegExp類實現(xiàn)的。你可以以如下方式建立一個正則表達式:
          var regex=new RegExp("^[1-9]+\\d*$");
          而驗證的方法是regex.test(str),它返回str是否符合regex的結果。

          JS中正則表達式和Java中的異同。
          JavaScript
          1.建立:
          var regex=new RegExp("^[1-9]+\\d*$");
          2.驗證
          return regex.test(str);
          3.寫法上,要驗證字符串,JS中必須把起始符號^和結束符號$寫全,否則就是包含驗證而不是全匹配驗證.除此外其它部分都是一致的.

          Java
          1.建立:
          String regex="\\d*";
          2.驗證:
          return Pattern.matches(regex,text);
          3.寫法上,JAVA中進行全匹配驗證不需寫全起始符號^和結束符號$.

          一個完整的驗證過程

          表單元素:
          <input type="text" name="positiveinteger"
          value="1" />

          表單提交之前的驗證函數(shù):
          var positiveinteger=$("positiveinteger").value;
          if(isPositiveInteger(positiveinteger)==false){
               $("positiveinteger").focus();
               $("checkMsg").innerHTML="正整數(shù)驗證不通過";
               return false;
          }
          else{
               $("checkMsg").innerHTML="正整數(shù)驗證通過";
          }

          驗證函數(shù):
          function isPositiveInteger(str){
               var regex=new RegExp("^[1-9]+\\d*$");
               return regex.test(str);
          }


          常用驗證函數(shù)

          /**
          * 正整數(shù)驗證*/
          function isPositiveInteger(str){
            var regex=new RegExp("^[1-9]+\\d*$");
            return regex.test(str);
          }

          /**
          * 負整數(shù)驗證
          */
          function isNegativeInteger(str){
            var regex=new RegExp("^-{1}\\d+$");
            return regex.test(str);
          }

          /**
          * 非負整數(shù)驗證
          */
          function isNonnegativeInteger(str){
            var regex=new RegExp("^\\d+$");
            return regex.test(str);
          }

          /**
          * 整數(shù)驗證
          */
          function isInteger(str){
            var regex=new RegExp("^-?\\d+$");
            return regex.test(str);
          }

          /**
          * 有理數(shù)驗證
          */
          function isRationalNumber(str){
            var regex=new RegExp("^-?\\d+(\\.*)(\\d*)$");
            return regex.test(str);
          }

          /**
          * 英語字母驗證
          */
          function isLetter(str){
            var regex=new RegExp("^[a-zA-Z]+$");
            return regex.test(str);
          }

          /**
          * 英數(shù)字驗證
          */
          function isLetterOrInteger(str){
            var regex=new RegExp("^[a-zA-Z0-9]+$");
            return regex.test(str);
          }

          /**
          * 郵件驗證
          */
          function isEmail(str){
            var regex=new RegExp("^\\w+([-+.]\\w+)*@\\w+([-.]\\w+)*\\.\\w+([-.]\\w+)*$");
            return regex.test(str);
          }

          /**
          * 漢字驗證
          */
          function isCharacter(str){
            var regex=new RegExp("^[\u4E00-\u9FA5]+$");
            return regex.test(str);
          }

          /**
          * 貨幣驗證
          */
          function isCurrency(str){
            return str.search("^\\d+(\\.\\d{0,2})*$")==0;
          }

          posted @ 2008-03-02 16:00 和風細雨 閱讀(2014) | 評論 (2)編輯 收藏

          僅列出標題
          共10頁: 上一頁 1 2 3 4 5 6 7 8 9 下一頁 Last 
          主站蜘蛛池模板: 宜兰市| 穆棱市| 当涂县| 呼图壁县| 台江县| 乌拉特中旗| 邓州市| 泾川县| 鸡西市| 龙海市| 漳州市| 蚌埠市| 许昌县| 开化县| 福安市| 望都县| 彭阳县| 麻江县| 色达县| 余江县| 苗栗县| 神农架林区| 濮阳县| 丰镇市| 延安市| 遂宁市| 梁山县| 庆城县| 寻乌县| 越西县| 张北县| 滕州市| 中江县| 任丘市| 浙江省| 夏津县| 库车县| 同仁县| 普兰店市| 方正县| 黑山县|