2009年12月23日

          [ -a FILE ] 如果 FILE 存在則為真。
          [ -b FILE ] 如果 FILE 存在且是一個塊特殊文件則為真。
          [ -c FILE ] 如果 FILE 存在且是一個字特殊文件則為真。
          [ -d FILE ] 如果 FILE 存在且是一個目錄則為真。
          [ -e FILE ] 如果 FILE 存在則為真。
          [ -f FILE ] 如果 FILE 存在且是一個普通文件則為真。
          [ -g FILE ] 如果 FILE 存在且已經設置了SGID則為真。
          [ -h FILE ] 如果 FILE 存在且是一個符號連接則為真。
          [ -k FILE ] 如果 FILE 存在且已經設置了粘制位則為真。
          [ -p FILE ] 如果 FILE 存在且是一個名字管道(F如果O)則為真。
          [ -r FILE ] 如果 FILE 存在且是可讀的則為真。
          [ -s FILE ] 如果 FILE 存在且大小不為0則為真。
          [ -t FD ] 如果文件描述符 FD 打開且指向一個終端則為真。
          [ -u FILE ] 如果 FILE 存在且設置了SUID (set user ID)則為真。
          [ -w FILE ] 如果 FILE 如果 FILE 存在且是可寫的則為真。
          [ -x FILE ] 如果 FILE 存在且是可執行的則為真。
          [ -O FILE ] 如果 FILE 存在且屬有效用戶ID則為真。
          [ -G FILE ] 如果 FILE 存在且屬有效用戶組則為真。
          [ -L FILE ] 如果 FILE 存在且是一個符號連接則為真。
          [ -N FILE ] 如果 FILE 存在 and has been mod如果ied since it was last read則為真。
          [ -S FILE ] 如果 FILE 存在且是一個套接字則為真。
          [ FILE1 -nt FILE2 ] 如果 FILE1 has been changed more recently than FILE2, or 如果 FILE1FILE2 does not則為真。 exists and
          [ FILE1 -ot FILE2 ] 如果 FILE1 比 FILE2 要老, 或者 FILE2 存在且 FILE1 不存在則為真。
          [ FILE1 -ef FILE2 ] 如果 FILE1 和 FILE2 指向相同的設備和節點號則為真。
          [ -o OPTIONNAME ] 如果 shell選項 “OPTIONNAME” 開啟則為真。
          [ -z STRING ] “STRING” 的長度為零則為真。
          [ -n STRING ] or [ STRING ] “STRING” 的長度為非零 non-zero則為真。
          [ STRING1 == STRING2 ] 如果2個字符串相同。 “=” may be used instead of “==” for strict POSIX compliance則為真。
          [ STRING1 != STRING2 ] 如果字符串不相等則為真。
          [ STRING1 < STRING2 ] 如果 “STRING1” sorts before “STRING2” lexicographically in the current locale則為真。
          [ STRING1 > STRING2 ] 如果 “STRING1” sorts after “STRING2” lexicographically in the current locale則為真。
          [ ARG1 OP ARG2 ] “OP” is one of -eq, -ne, -lt, -le, -gt or -ge. These arithmetic binary operators return true if “ARG1” is equal to, not equal to, less than, less than or equal to, greater than, or greater than or equal to “ARG2”, respectively. “ARG1” and “ARG2” are integers.

          posted @ 2011-09-27 16:23 xsong 閱讀(1312) | 評論 (0)編輯 收藏

               摘要: Code highlighting produced by Actipro CodeHighlighter (freeware)http://www.CodeHighlighter.com/-->//源代碼class TT{       static int tt = 5;&nb...  閱讀全文

          posted @ 2011-09-23 13:55 xsong 閱讀(345) | 評論 (0)編輯 收藏

          #include <stdio.h>

          int main(int argc, char **argv) {

              
          /**
               * sizeof  關鍵字
               
          */
              
          int i=0;
              printf(
          "sizeof int %lu \n",sizeof(i)); // 4

              
          int *p=NULL;
              printf(
          "sizeof point %lu \n" ,sizeof(p) )    ; // 8
              printf("sizeof *p %lu \n",sizeof *p); // 4

              
          int a[100];
              printf(
          "sizeof array %lu \n"sizeof(a));// 100*4
              printf("sizeof a[100] %lu \n",sizeof(a[100])); // 4
              printf("sizeof &a %lu \n"sizeof(&a)); // 8  &a 是指針

              
          return 0;
          }

          posted @ 2011-09-16 15:04 xsong 閱讀(232) | 評論 (0)編輯 收藏

          #include <stdio.h>
          #include 
          <stdlib.h>
          #include 
          <event.h>
          #include 
          <evhttp.h>

          void generic_request_handler(struct evhttp_request *req, void *arg) {

              
          struct evbuffer *return_buffer=evbuffer_new();

              evbuffer_add_printf(return_buffer,
          "welcome");
              evhttp_send_reply(req,HTTP_OK,
          "Client",return_buffer    );
              evbuffer_free(return_buffer);
          }

          int main(int argc, char **argv) {
              
          short http_port =8082;
              
          char *http_addr="127.0.0.1";
              
          struct evhttp *http_serv=NULL;
              event_init();

              http_serv
          = evhttp_start(http_addr,http_port);
              evhttp_set_gencb(http_serv,generic_request_handler,NULL);
              event_dispatch();
              
          return 0;
          }

          posted @ 2011-08-05 14:51 xsong 閱讀(1356) | 評論 (0)編輯 收藏

          enum Action {Start, Stop, Rewind, Forward};

          // Special type of class 
          enum Status {
            Flunk(
          50), Pass(70), Excel(90);
            
          private final int value;
            Status(
          int value) { this.value = value; }
            
          public int value() { return value; } 
          };

          Action a 
          = Action.Stop;
          if (a != Action.Start)
            System.out.println(a);               
          // Prints "Stop"

          Status s 
          = Status.Pass;
          System.out.println(s.value());      
          // Prints "70"

          posted @ 2011-08-01 16:20 xsong 閱讀(221) | 評論 (0)編輯 收藏

          posted @ 2011-07-04 15:44 xsong 閱讀(301) | 評論 (0)編輯 收藏

          安裝  編輯 ~/.vimrc

          syntax on
          set tabstop=4
          set softtabstop=4
          set shiftwidth=4
          set autoindent
          set cindent
          set nu

          if &term=="xterm"
            set t_Co=8
            set t_Sb=^[[4%dm
            set t_Sf=^[[3%dm
          endif

          let g:neocomplcache_enable_at_startup = 1 


          "括號補全功能,

          :inoremap ( ()<ESC>i
                  :inoremap ) <c-r>=ClosePair(')')<CR>
          :inoremap { {}<ESC>i
              :inoremap } <c-r>=ClosePair('}')<CR>
              :inoremap [ []<ESC>i
              :inoremap ] <c-r>=ClosePair(']')<CR>
              :inoremap < <><ESC>i
              :inoremap > <c-r>=ClosePair('>')<CR>

              function ClosePair(char)
              if getline('.')[col('.') - 1] == a:char
              return "\<Right>"
              else
              return a:char
              endif
              endf

          posted @ 2011-06-11 12:58 xsong 閱讀(742) | 評論 (0)編輯 收藏

              c 提供了 atoi atof 等函數實現了字符串轉化數值的函數。使用方法簡單。
          但是如果轉化 "123ss"等字符串里包含非數值的字符串時,則會自動轉化為 123,不會拋出異常。
          想要驗證 字符串是否是數值格式  可使用
          strtol (__const char *__restrict __nptr, char **__restrict __endptr, int __base)
           nptr指向的字符串, 
          strtol()函數檢測到第一個非法字符時,立即停止檢測,其后的所有字符都會被當作非法字符處理。合法字符串會被轉換為long int, 作為函數的返回值。非法字符串,即從第一個非法字符的地址,被賦給*endptr**endptr是個雙重指針,即指針的指針。strtol()函數就是通過它改變*endptr的值,即把第一個非法字符的地址傳給endptr

              char *str1="1231",*endptr1;
              
          char *str2="123sss",*endptr2;

              printf(
          "atoi str2 is %i\n",atoi(str1));
              
          int i,j;//atoi(str);
              i=strtol(str1,&endptr1,10);
              
          if(*endptr1!=NULL){
                  printf(
          "endptr1 is %s\n",endptr1);
              }
              printf(
          "str1 auto int %i\n",i);
              j
          =strtol(str2,&endptr2,10);
              
          if(*endptr2!=NULL){
                  printf(
          "endptr2 is %s\n",endptr2);
              }
              printf(
          "str2 auto long int %i\n",j);

          posted @ 2011-05-30 15:13 xsong 閱讀(597) | 評論 (0)編輯 收藏

          系統中的瀏覽器都是由在/usr/bin中的與瀏覽器同名的腳本文件啟動的.你可以對其進行編輯加入環境變量進行連接庫文件進行預載.對firefox瀏覽器,用sudo權限編輯/usr/bin/firefox,將
          export LD_PRELOAD=/usr/lib/libc/memcpy-preload.so(不行就改為export LD_PRELOAD=/usr/lib/x86_64-linux-gnu/libc/memcpy-preload.so)加入文件的第一行就可以了

          posted @ 2011-05-26 13:37 xsong 閱讀(483) | 評論 (0)編輯 收藏

          /*
           ============================================================================
           Name        : test.c
           Author      : xsong
           Version     :
           Copyright   : Your copyright notice
           Description : Hello World in C, Ansi-style
           ============================================================================
           
          */

          #include 
          <stdio.h>
          #include 
          <stdlib.h>
          #include
          <string.h>

          int main(void) {

              
          char buffer[] = "buffer example";
              
          //  memset 填充字符串
              printf("buffer size %i \n"sizeof(buffer));
              printf(
          "before memsetd -> %s \n", buffer);
              
          int mpoint = memset(buffer, '*'sizeof(buffer));
              printf(
          "memset return point -> %i \n", mpoint);
              printf(
          "after memsetd -> %s \n", buffer);
              
          //strlen 取得字符串長度
              int buffer_length = strlen(buffer);
              printf(
          "buffer size -> %i \n", buffer_length);
              
          //字符串連接
              char d[10= "foo";
              
          char s[10= "bar";
              strcat(d, s);
              printf(
          "%s %s\n", d, s);

              
          //字符串分割
              char str[] = "root:x::0:root:/root:/bin/bash:";
              
          char *token;
              token 
          = strtok(str, ":");

              
          do {
                  printf(
          "%s \n", token);
              } 
          while ((token = strtok(NULL, ":")) != NULL);

              
          return EXIT_SUCCESS;
          }

          posted @ 2011-05-18 15:38 xsong 閱讀(268) | 評論 (0)編輯 收藏

          #include <stdio.h>
          #include 
          <stdlib.h>
          #include
          <string.h>

          typedef 
          struct{
              
          int number;
              
          char *msg;
          } unit_t;

          int main(void) {
              
          // 使用 malloc 分配內存, 使用free釋放內存,并設置為NULL 杜絕野指針
              unit_t *p=malloc(sizeof(unit_t));
              p
          ->number=10;
              p
          ->msg=malloc(10);
              strcpy(p
          ->msg,"hello");
              printf(
          "number is %i \n",p->number);
              printf(
          "msg is %s \n",p->msg);
              
          //如果先free(p),p成了野指針,就不能再通過p->msg訪問內存
              free(p->msg);
              free(p);
              
          //如果 free(p)  兩次, 則會引發系統錯誤,
              p=NULL;

              
          if(p==NULL){
                  printf(
          "p point is empty");
                  exit(
          -1);
              }

              
          return EXIT_SUCCESS;
          }

          posted @ 2011-05-16 13:42 xsong 閱讀(173) | 評論 (0)編輯 收藏

          /*數組和指針
          * 在函數原型中,如果參數是數組,則等價于參數是指針的形式,例如:
          void func(int a[10])
          {

          }
          等價于:

          void func(int *a)
          {

          }
          第一種形式方括號中的數字可以不寫,仍然是等價的:

          void func(int a[])
          {

          }
          */

          int a[]={5,6,7,8};
          // int *p=&a[0]; 一般簡寫為
          int
           *p=a;
          printf(
          "p address %p \n",p);
          printf(
          "p value %i \n"*p);
          //指針自加 p++  p=a[1]
          p++;
          printf(
          "p++ value %i \n",*p);

          // 指針的比較運算,比較的是兩個指針的地址, 但只有一個數組內的指針比較才有意義。
          //如果為true  輸出 1, 如果為 false 輸出0  ,c 語言中沒有 boolean 類型
          printf(" complete p %i \n", p+2>p);
          printf(
          " complete p %i \n", p+2<p);
          //指針相減表示兩個指針之間相差的元素個數, C語言也規定兩個指針不能相加
          printf(" p-1 value %i",*(p-1));

          posted @ 2011-05-13 11:57 xsong 閱讀(178) | 評論 (0)編輯 收藏

          //使用指針訪問結構體

          struct unit{
          char c;
          int num;
          };

           
          struct unit u;
          struct unit *p=&u;
          //可使用 (*p).c=‘a'  通過指針訪問結構體里的數據, c提供了 ->運算符 簡化指針對結構體的訪問 p->c='c'
          (*p).c='a';
          (
          *p).num=2;
          p
          ->c='c';
          p
          ->num=1;

          printf(
          "p->c is %c \n",p->c);
          printf(
          "p->i is %i \n",p->num);

          posted @ 2011-05-13 11:57 xsong 閱讀(195) | 評論 (0)編輯 收藏

          結構體
              *


          struct Complex{ 
               
          double x,y;
          } z1;

          //或者
          struct Complex{
               
          double x,y;
          };
          struct Complex z1;


          //聲明時初始化
          struct Stu{
          char name;
          }s1
          ={'s'};

          //先聲明,后初始化
          struct Stu{
               
          char name;
          };
          struct Stu s1={s};

          //結構體賦值 ,copy s1的內容給s2

          struct Stu s2=s1;
          s2.name
          ='m'

          printf(
          "s1.name %c",s1.name); // print s
          printf("s2.name %c",s2.name); //print m

          //結構體嵌套
          struct dog{
          char run;
          };
          struct cat{
          char run;
          };
          struct animal{
          struct dog dd;
          struct cat cc;
          };


           
          //嵌套的結構體分別初始化
          struct dog dd={'d'};
          struct cat cc={'c'};
          struct animal a1={dd ,cc};
          printf(
          "dog-dd run is %c \n",a1.dd.run);
          printf(
          "cat-cc run is %c",a1.cc.run);



          posted @ 2011-05-13 11:55 xsong 閱讀(203) | 評論 (0)編輯 收藏

          聲明一個字符串,其實也就是一個char的數組
          char str[20] = "Hello, world";
          printf("str is %s",str);
          如果定義數組的大小 小于字符串字面值“Hello ,world"; 則編譯器會發出警告信息。所以最好定義不定長度的數組
          char str[ ]="hello, world";

          posted @ 2011-05-13 11:55 xsong 閱讀(172) | 評論 (0)編輯 收藏

          deb http://mirrors.163.com/debian/ testing main non-free contrib
          deb-src http://mirrors.163.com/debian/ testing main non-free contrib

          deb http://mirrors.163.com/debian-security testing/updates main
          deb-src http://mirrors.163.com/debian-security testing/updates main

          posted @ 2011-05-13 11:52 xsong 閱讀(2141) | 評論 (0)編輯 收藏

               摘要: java 證書公鑰加密 生成xml 使用http post發送到servl et , servlet私鑰解密 xml格式 1 :消息格式: XML 消息格式如下: <?xml version="1.0" encoding="UTF-8"> <Requ...  閱讀全文

          posted @ 2011-05-13 11:50 xsong 閱讀(1694) | 評論 (0)編輯 收藏

          1.OutputStream寫入String

          ByteArrayOutputStream baos 
          = new ByteArrayOutputStream();  
          //向OutPutStream中寫入,如 message.writeTo(baos);  
          String str = baos.toString();  

          2.字符串轉inputStream

          String string;  
          //  
          InputStream is = new ByteArrayInputStream(string.getBytes());

          3.InputStream轉字符串

          ByteArrayOutputStream baos 
          = new ByteArrayOutputStream();  
          int i;  
          while ((i = is.read()) != -1) {  
              baos.write(i);  
          }  
          String str 
          = baos.toString();  
          System.out.println(str);  


          4.String寫入OutputStream

          OutputStream os 
          = System.out;  
          os.write(string.getBytes());

          posted @ 2011-05-13 11:48 xsong 閱讀(4921) | 評論 (0)編輯 收藏

          import sun.misc.BASE64Decoder;
          import sun.misc.BASE64Encoder;

          import javax.crypto.*;
          import javax.crypto.spec.DESKeySpec;
          import javax.crypto.spec.IvParameterSpec;
          import java.io.UnsupportedEncodingException;
          import java.security.InvalidAlgorithmParameterException;
          import java.security.InvalidKeyException;
          import java.security.NoSuchAlgorithmException;
          import java.security.spec.InvalidKeySpecException;

          /**
           * User: fengxuesong
           * Date: 11-3-30
           * Time: 下午4:48
           * 使用 DES 加密解密
           
          */
          public class DesTest {

              
          static final byte[] IV = new byte[]{-29105540-94-98-113-100};
              
          static final String priKey="11111111111";
              
          static final String data="admin11";

              
          public static void main(String args[]) throws Exception {

                  
          //加密
                  String encrypt  = encodeDesWithBase64(priKey,data);
                  
          //輸出加密的字符串
                  System.out.println(encrypt );

                  String decrypt 
          =decodeDesWithBase64(priKey,encrypt );
                  System.out.println(decrypt );
              }

              
          private static String encodeDesWithBase64(String priKey,String data) throws InvalidKeyException, NoSuchAlgorithmException, InvalidKeySpecException, NoSuchPaddingException, InvalidAlgorithmParameterException, IllegalBlockSizeException, BadPaddingException, UnsupportedEncodingException {
                  DESKeySpec desKS 
          = new DESKeySpec(priKey.getBytes());
                  SecretKeyFactory skf 
          = SecretKeyFactory.getInstance("DES");
                  SecretKey sk 
          = skf.generateSecret(desKS);
                  Cipher cip 
          = Cipher.getInstance("DES/CBC/PKCS5Padding");
                  cip.init(Cipher.ENCRYPT_MODE, sk, 
          new IvParameterSpec(IV));
                  
          byte bb [] =cip.doFinal(data.getBytes());
                  
          return new BASE64Encoder().encode(bb);
              }
              
          private static String decodeDesWithBase64(String priKey,String data) throws Exception{
                  DESKeySpec desKS 
          = new DESKeySpec(priKey.getBytes());
                  SecretKeyFactory skf 
          = SecretKeyFactory.getInstance("DES");
                  SecretKey sk 
          = skf.generateSecret(desKS);
                  Cipher cip 
          = Cipher.getInstance("DES/CBC/PKCS5Padding");
                  cip.init(Cipher.DECRYPT_MODE, sk, 
          new IvParameterSpec(IV));
                  
          byte bb [] =cip.doFinal(new BASE64Decoder().decodeBuffer(data));
                  
          return new String(bb);
              }
          }

          posted @ 2011-05-13 11:46 xsong 閱讀(270) | 評論 (0)編輯 收藏

          Tomcat Server在啟動的時候將構造一個ClassLoader樹,以保證模塊的類庫是私有的
          Tomcat Server的ClassLoader結構如下:

          其中:
          - Bootstrap - 載入JVM自帶的類和$JAVA_HOME/jre/lib/ext/*.jar
          - System - 載入$CLASSPATH/*.class
          - Common - 載入$CATALINA_HOME/common/...,它們對TOMCAT和所有的WEB APP都可見
          - Catalina - 載入$CATALINA_HOME/server/...,它們僅對TOMCAT可見,對所有的WEB APP都不可見
          - Shared - 載入$CATALINA_HOME/shared/...,它們僅對所有WEB APP可見,對TOMCAT不可見(也不必見)
          - WebApp? - 載入ContextBase?/WEB-INF/...,它們僅對該WEB APP可見

          posted @ 2011-05-13 11:44 xsong 閱讀(184) | 評論 (0)編輯 收藏

          假設來自客戶的請求為:
          http://localhost:8080/wsota/wsota_index.jsp

          1) 請求被發送到本機端口8080,被在那里偵聽的Coyote HTTP/1.1 Connector獲得
          2) Connector把該請求交給它所在的Service的Engine來處理,并等待來自Engine的回應
          3) Engine獲得請求localhost/wsota/wsota_index.jsp,匹配它所擁有的所有虛擬主機Host
          4) Engine匹配到名為localhost的Host(即使匹配不到也把請求交給該Host處理,因為該Host被定義為該Engine的默認主機)
          5) localhost Host獲得請求/wsota/wsota_index.jsp,匹配它所擁有的所有Context
          6) Host匹配到路徑為/wsota的Context(如果匹配不到就把該請求交給路徑名為""的Context去處理)
          7) path="/wsota"的Context獲得請求/wsota_index.jsp,在它的mapping table中尋找對應的servlet
          8) Context匹配到URL PATTERN為*.jsp的servlet,對應于JspServlet類
          9) 構造HttpServletRequest對象和HttpServletResponse對象,作為參數調用JspServlet的doGet或doPost方法
          10)Context把執行完了之后的HttpServletResponse對象返回給Host
          11)Host把HttpServletResponse對象返回給Engine
          12)Engine把HttpServletResponse對象返回給Connector
          13)Connector把HttpServletResponse對象返回給客戶browser

          posted @ 2011-05-13 11:44 xsong 閱讀(169) | 評論 (0)編輯 收藏

          Bootstrap 的 init 方法中 通過反射動態調用 Catalina.start() 
          Catalina 類 負責開始或者停止服務
           Class<?> startupClass = catalinaLoader.loadClass("org.apache.catalina.startup.Catalina");
           Object startupInstance 
          = startupClass.newInstance();
          Catalina 完成了3個任務 
          •  處理xml文件, load 方法中使用 Digester 處理server.xml文件,轉化為java對象
          if (getServer() == null) {
                      load();
                  }
          •     實例化一個server  

           getServer().start();
          •      給jvm 注冊一個關閉 的Hook(鉤子)
          Runtime.getRuntime().addShutdownHook(shutdownHook);
          • 線程等待
           await();  調用 StandardServer 的 await()   StandardServer 處理 Server相關的操作,
               /**
               * Wait until a proper shutdown command is received, then return.
               * This keeps the main thread alive - the thread pool listening for http
               * connections is daemon threads.
               */
               StandardServer.await() 處理 當前的主線程,即 啟動 tomcat 的主線程

              
          try {
                  awaitSocket 
          = new ServerSocket(port, 1,
                          InetAddress.getByName(address));
              }

              
          catch( IOException e ) {
                  log.error(
          "StandardServer.await: create[" + address + ":" + port + "]: ", e);
                  
          return;
              }

              
          try {
                  awaitThread 
          = Thread.currentThread();

          // Loop waiting for a connection and a valid command
                  while (!stopAwait) {
                      ServerSocket serverSocket 
          = awaitSocket;

                      
          if (serverSocket == null) {
                          
          break;
                      }
          // Wait for the next connection
                      Socket socket = null;
                      StringBuilder command 
          = new StringBuilder();
                      
          try {
                          InputStream stream;
                          
          try {
                              socket 
          = serverSocket.accept();
                              socket.setSoTimeout(
          10 * 1000);  // Ten seconds
                              stream = socket.getInputStream();
                          } 
          catch (AccessControlException ace) {
                              log.warn(
          "StandardServer.accept security exception: " + ace.getMessage(), ace);
                              
          continue;
                          } 
          catch (IOException e) {
                              
          if (stopAwait) {
          // Wait was aborted with socket.close()
                                  break;
                              }
                              log.error(
          "StandardServer.await: accept: ", e);
                              
          break;
                          }
          // Read a set of characters from the socket
                          int expected = 1024// Cut off to avoid DoS attack
                          while (expected < shutdown.length()) {
                              
          if (random == null)
                                  random 
          = new Random();
                              expected 
          += (random.nextInt() % 1024);
                          }
                          
          while (expected > 0) {
                              
          int ch = -1;
                              
          try {
                                  ch 
          = stream.read();
                              } 
          catch (IOException e) {
                                  log.warn(
          "StandardServer.await: read: ", e);
                                  ch 
          = -1;
                              }
                              
          if (ch < 32)  // Control character or EOF terminates loop
                                  break;
                              command.append((
          char) ch);
                              expected
          --;
                          }
                      } 
          finally {
          // Close the socket now that we are done with it
                          try {
                              
          if (socket != null) {
                                  socket.close();
                              }
                          } 
          catch (IOException e) {
          // Ignore
                          }
                      }

          // Match against our command string
                      boolean match = command.toString().equals(shutdown);
                      
          if (match) {
                          log.info(sm.getString(
          "standardServer.shutdownViaPort"));
                          
          break;
                      } 
          else
                          log.warn(
          "StandardServer.await: Invalid command '"
                                  
          + command.toString() + "' received");
                  }
              }

              
          finally {
                  ServerSocket serverSocket 
          = awaitSocket;
                  awaitThread 
          = null;
                  awaitSocket 
          = null;
          // Close the server socket and return
                  if (serverSocket != null) {
                      
          try {
                          serverSocket.close();
                      } 
          catch (IOException e) {
          // Ignore
                      }
                  }
              }

          posted @ 2011-05-13 11:31 xsong 閱讀(533) | 評論 (0)編輯 收藏

           

          class A {
            
          void call() {}  
          }
            
          class B extends A {
            
          void call() {}  
          }
            
          class C {
            
          void call() {}  
          }
           
          void foo(A a){
          }

          A a
          =new A();
          foo(a); 

          C c
          =new C();
          foo(c);
          java編譯器無法通過, 因為C不是A或者A的子類 雖然 C 中也有 call 方法。

          scala 中可以通過 結構類型(Structural)實現
          class A {
            def call() 
          {
              println(
          "a class")
            }

          }

          class B extends A {override def call() {}}
          class C {
            def call() 
          {
              println(
          "c class")
            }

          }


          object Call 
          {
            def main(args: Array[String]) 
          {
              def foo[T 
          <{ def call() }](a : T) {
                a.call()
              }

              val a 
          = new A()
              val c 
          = new C()
              foo(a)
              foo(c)
              println()
            }

          }

          不過覺得  def foo[T <: { def call() }](a : T)  這樣的寫法 不如動態語言(ruby, groovy..)看起來自然。

          posted @ 2010-01-12 18:02 xsong 閱讀(136) | 評論 (0)編輯 收藏

              java中的泛型:
          List<String> s1=new ArrayList<String>();
                  s1.add(
          "hello");
          當在s1中添加 String 類型以外的對象時,編譯器會報錯。
          s1.add(new Date());
          scala 中是用 [] 代替 java 中的<> 表達泛型。scala 在new ArrayList時,不需要指定String類型,得益與scala 的類型推斷。
          val strs : List[String]=new ArrayList()
          scala 中定義泛型列表,和java中類似
          class Link[T](val head: T, val tail: Link[T]) 
          協變的定義:    假設有類G(或者接口和特征) 和類型T1,T2  。 在T1是T2的子類的情況下, 如果G<T1> 也是G2<T2>的子類,則類G是協變的。

          當我定義一個列表對象li,并定義一個ln為li 的別名
           List<Integer> li=new ArrayList<Integer>();
                  li.add(
          1);
                  List
          <Number> ln=li;

          這樣的方式,編譯器不能通過。
          通過協變,可以實現上訴功能
          class Link[+T](val head : T, val tail: Link[T]) {}

          def main(args : Array[String])
          {
                val ln : Link[Integer]
          =new Link[Integer](1,null)
                val lnn : Link[Number]
          =ln
                println(lnn.head)
          }


          但是如果試圖加入一個方法,追加一個參數,并返回Link, 則會產生編譯錯誤
          class Link[+T](val head : T, val tail: Link[T]) {

           def prepend(newHead: T): Link[T] 
          = new Link(newHead, this)
          }

           
          實際上,范型變為協變之后就不能把類型參數不加修改的放在成員方法的參數上(這里是newHead)了。但是,通過將成員方法定義為范型,并按照如下所示描述后就可以避免該問題了

          class Link[+T](val head: T, val tail: Link[T]) {  
              def prepend[U 
          >: T](newHead: U): Link[U] = new Link(newHead, this)  
          }
           
          scala 逆變,類似協變
          假設有類 G 和類型T1,T2, 在T1 是T2的子類的情況,如果G[T2]是G[T1]的子類, 則G為逆變。
          假設含有 apply的類 LessThan(apply 的邏輯 當a<b 時,返回true 否則返回false)
          abstract class LessThan[T] {
            def apply(a: T, b: T): Boolean
          }
          val hashCodeLt: LessThan[Any] = new LessThan[Any] {
                def apply(a: Any, b: Any): Boolean 
          = a.hashCode < b.hashCode
              }


              val strLt: LessThan[String] 
          = hashCodeLt

              
          assert(true ,strLt("a","b"))
          在非變的情況 編譯器會報錯:Error:Error:line (18)error: type mismatch;
          found   : xxx.LessThan[Any]
          required: xxx.LessThan[String]
          val strLt: LessThan[String] = hashCodeLt
          在需要LessThan[Any]的地方使用了LessThan[String],由此看來LessThan不是逆變的,也不是協變,可以成為非變。
          但是在類的定義前加一個 - 符號,使用逆變, 代碼則可編譯過去了。
          abstract class LessThan[-T] {
            def apply(a: T, b: T): Boolean
          }



          posted @ 2010-01-12 17:20 xsong 閱讀(708) | 評論 (0)編輯 收藏

          java 有很龐大的類庫資源,但是 被聲明成 final 的類不允許繼承 例如 String , 怎樣擴展java及第三方類庫 scala提供了很靈活的方式

          當 scala 使用 implicit 隱式轉化時 ,  scala 編輯器發現對象的類型不匹配時,不會直接報錯,而會在代碼中嘗試匹配implicit聲明的object, 當然,相同方法簽名的類必須唯一。
          舉個小例子,實現在字符串前后 添加 "**" 的操作。

          當然 例子本事無實際意義, 只是說明implicit的用法而已 
           1object implicits {
           2
           3  implicit  def strWrapper(s : String)={
           4    new {
           5      def wrap= "**"+s+"**"
           6    }

           7  }

           8  def main(args: Array[String]) {
           9    val s = "hello"
          10    println(s.wrap)  // **hello**
          11  }

          12}

          當scala的編譯器 編譯 s.wrap 時,因為 String 類中沒有 wrap方法,編譯器會尋找代碼中方法簽名相同的 strWrapper(s :String),
          輸出  **hello**

          另外一種寫法 :

           1object implicits {
           2
           3  class StrWrapper(s : String){
           4    def wrap="**"+s+"**"
           5  }

           6  def main(args: Array[String]) {
           7    implicit def wrapper(s :String)=new StrWrapper(s)
           8    val s = "hello" 
           9    println(s.wrap) // print **hello**
          10  }

          11}

          posted @ 2009-12-23 17:17 xsong 閱讀(4145) | 評論 (0)編輯 收藏

          主站蜘蛛池模板: 永州市| 岗巴县| 南汇区| 辉县市| 汕尾市| 禹城市| 酉阳| 鹤庆县| 安陆市| 阳城县| 内丘县| 翁源县| 泸西县| 永登县| 泾源县| 天镇县| 宁武县| 黄山市| 福安市| 友谊县| 阳高县| 丰镇市| 吴旗县| 和龙市| 南木林县| 两当县| 绥阳县| 东海县| 喀喇| 宽甸| 晋江市| 德昌县| 河北区| 枞阳县| 思茅市| 布尔津县| 土默特左旗| 桃园市| 灌南县| 获嘉县| 武胜县|