2015年12月29日 星期二

[Tomcat]處理編碼問題

一般來說serlet的post請求可以使用filter或是用request.setCharacterEncoding("UTF-8");
來處理編碼
但是當使用Get方法時,Tomcat沒有用正確的編碼來處理querystring,資料就會變成亂碼。

解決方法是修改tomcat資料夾下的
server.xml檔案,找到Connector標籤,加入URIEncoding="UTF-8"即可。


Ex:
<Connector port="8080" protocol="HTTP/1.1"
 URIEncoding="UTF-8"
 connectionTimeout="30000"
 redirectPort="8443" />

2015年12月27日 星期日

Visual Studio 快速鍵

首先一些常用的快速鍵可以在編輯→進階裡找到
有些快速鍵是用","隔開,
舉例來說註解是Crtl+K,Ctrl+C
那麼你就要先按下Ctrl+K,此時畫面的左下角會顯示這個訊息
然後再按下Ctrl+C就可以把選取範圍註解

還有一些常用的快速鍵如下

快速鍵 效果
CTRL + G 移動到指定行號位置
CTRL + F4 關閉程式頁籤
CTRL + F 尋找
CTRL + SHIFT + F 在檔案中尋找
CTRL + H 取代
CTRL + SHIFT + H 在檔案中取代
CTRL + ALT + L 檢視方案總管
CTRL + ALT + X 檢視工具列
F5 開始偵錯
CTRL + F5 啟動但不偵錯
CTRL + SHIFT + W 在瀏覽器中顯示


2015年12月14日 星期一

[Spring]web.xml簡易設置

再SpringMVC中,控制前端的class為
org.springframework.web.servlet.DispatcherServlet
DispatcherServlet負責將客戶的請求分派給對應於請求的控制物件
DispatcherServlet需要設定在web.xml中

以下是web.xml設定

<?xml version="1.0" encoding="UTF-8"?>

<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" id="WebApp_ID" version="3.0">

  <display-name>Website</display-name>

     <servlet>

      <servlet-name>Website</servlet-name>

      <servlet-class>

         org.springframework.web.servlet.DispatcherServlet

      </servlet-class>

      <init-param>

            <param-name>contextConfigLocation</param-name>

            <param-value>/WEB-INF/mvc-config.xml</param-value>

        </init-param>

      <load-on-startup>1</load-on-startup>

   </servlet>

    <servlet-mapping>

        <servlet-name>Website</servlet-name>

        <url-pattern>*.do</url-pattern>

    </servlet-mapping>

  <welcome-file-list>

    <welcome-file>/WEB-INF/jsp/login.jsp</welcome-file>

  </welcome-file-list>



  <listener>

    <listener-class>org.springframework.web.util.Log4jConfigListener</listener-class>

  </listener>

</web-app>






其中init-param有個屬性contextConfigLocation是用來設定讀取的xml放哪個位置
預設是/WEB-INF/(servlet-name)-servlet.xml
這邊設定是/WEB-INF/mvc-config.xml
servlet-mapping mapping中設定了spring管理的網頁路徑
此範例設定將所有路徑為.do的交給spring mvc管理

以下為mvc-config.xml的範例

<?xml version="1.0" encoding="UTF-8"?>



<beans xmlns="http://www.springframework.org/schema/beans"

 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

 xmlns:context="http://www.springframework.org/schema/context"

 xmlns:aop="http://www.springframework.org/schema/aop"

 xmlns:tx="http://www.springframework.org/schema/tx"

 xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd

      http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd

      http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd

      http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd">



 <aop:aspectj-autoproxy />

 <context:component-scan base-package="website" />

 

 <!-- viewResolver setup -->

 <context:component-scan base-package="website.controller" />

    <bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter" />



    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">

          <property name="prefix" value="/WEB-INF/jsp/" />

          <property name="suffix" value=".jsp" />

    </bean>



</beans>


ViewResolver是管理view的工具
prefix(此範例值為/WEB-INF/jsp/)表示的是view存放的路徑
suffix(此範例值為.jsp)表示的是檔案的副檔名
若是你的java程式有這段程式碼

   @RequestMapping("/test.do")

    public ModelAndView test(HttpServletRequest req,

            HttpServletResponse resp) throws Exception {

        return new ModelAndView("demo");

    }


那麼/test.do這隻程式就會將網頁導向/WEB-INF/jsp/demo.jap
(檔名式依照ModelAndView內的參數決定)

2015年12月2日 星期三

[雜談]程式效能(二)

之前看到某個系統把陣列轉成字串的功能
臨時想到了關於功能的效能問題
所以就稍微記了一下
他大概的程式碼如下

 public String arrayToString(String[] input){

  StringBuffer result = new StringBuffer();

  if(input!=null){

   boolean isFirstElement = true;

   for(int i = 0; i<input.length; i++){

    if(isFirstElement){

     result.append(input[i]);     

    } else {

     result.append(", ");

     result.append(input[i]);

    }    

   }   

  }      

  return result.toString();

 }





這段大概的意思是將一個陣列轉成字串
第一個字以後都要用", "分開,所以需要用isFirstElement來判斷是不是第一筆資料
可是我覺得這個寫法除了多了一個暫存值以外
每個迴圈都要判斷一次是不是第一個感覺效能不是很好
於是我就思考如何把那個if去掉
後來想到的方法如下


 public String arrayToString(String[] input){

  StringBuffer result = new StringBuffer();

  if(input!=null && input.length>0){

   result.append(input[0]);

   

   for(int i = 1; i<input.length; i++){

    result.append(", ");

    result.append(input[i]);
       

   }  

  }      

  return result.toString();

 }




把for迴圈的i=0,  i<input.length(這句相當於input.length>0)拿掉
將這判斷式移到input!=null的後面
這樣除了把isFirstElement移掉以外
也不會多做if判斷,執行時間跟記憶體空間都能節省到
可讀性的問題也可以用,提供給大家參考!

2015年11月23日 星期一

[程式風格]Guard Clause

Guard Clause是一種程式的風格,通常會至少滿足其中一種以下的行為
1.檢查傳入的參數,如果檢驗不通過就回傳錯誤訊息
2.檢查物件的狀態,如果不符合function使用的物件就
3.簡單快速的處理明顯的邏輯

舉個例子像是以下的程式碼

  if(username!=null){

   if(password!=null){

    System.out.println("do something");
    //這邊是要處理的邏輯
   }else {

    System.out.println("password is null");

   }

  }else {

   System.out.println("username is null");

  }


我們可以知道username跟password皆不為null時才會執行程式
這邊我們可以閱讀是因為巢狀的條件還只有兩層,而且有進行縮排,要是越來越多層
或是程式碼一常,我們不見得可以閱讀程式的執行條件是什麼
以這個例子做出Guard Clause的話大概是長這個樣子

  if(username!=null && password!=null){

   System.out.println("do something");
   //這邊是要處理的邏輯
  }else if(password==null){

   System.out.println("password is null");

  }else{

   System.out.println("username is null");

  }


把要處理的邏輯直接表現出來,這樣是否感覺比較容易明白想要執行的邏輯呢?
我自己覺得還是看每個人習慣,不過這種程式風格就給各位當做參考了


參考資料:http://c2.com/cgi/wiki?GuardClause

2015年11月4日 星期三

[雜談]程式效能(一)

前幾天在FB上看到有大學生在某社團問作業:1加到10的程式怎麼做
然後看到一些很有趣的解答
剛好趁機談談程式的效能
由1加到n這個運算
很直觀的做法就是1+2+3+4+5+6.+..+n
用for迴圈表示就是i=1到n,result= result+i;
但是這樣你數字越大他要跑的迴圈就越常
同樣的計算結果你用高斯方法就是n*(n+1)/2
不管你的n有多大,程式永遠做一次加法,一次乘法,一次除法
這就是所謂好的演算法
那對效能有什麼影響呢,以下我們拿這個範例程式
第一個呼叫的是for迴圈的方法
第二個呼叫的是高斯方法
我使用了結果程式的時間減掉程式開始時間來計算每一個方法使用了多少毫秒
程式碼如下


import java.util.Date;



public class SumTest {



 public static void main(String[] args) {

  

  useForLoop(10000000);

  useGaussMethod(10000000);

 }



 public static void useForLoop(long input){

  long result = 0;

  long startTime = new Date().getTime();

  for(long i = 1;i<=input;i++){

   result = result + i;

  }

  System.out.println(result);

  long endTime = new Date().getTime();

  long totalTime = endTime-startTime;

  System.out.println(totalTime);

 }

 

 public static void useGaussMethod(long input){

  long startTime = new Date().getTime();

  long result = input*(input+1)/2;

  System.out.println(result);

  long endTime = new Date().getTime();

  long totalTime = endTime-startTime;

  System.out.println(totalTime);

 }

 

}



然後實驗開始啦,首先是n等於一萬
看起來兩個花的時間都是0毫秒沒什麼差別,於是我將n值放大到十萬
似乎有點差別了,不過可能是誤差,再放大n到100萬看看

差距來到了三毫秒,最後我們再放大n到1000萬
for回圈的消耗時間增加到了25毫秒
所以我們可以知道
在資料量小的時候,我們不一定能感覺出演算法的好壞
但是好的演算法在輸入的值越大的時候,節省的效能會越明顯
雖然一般來講先完成功能就好,但是當功能完成之後應該要去思考如何提升程式效能提高使用品質

之後會不會繼續這個主題就看我有沒有時間囉~_~+

2015年10月30日 星期五

[Java]複製陣列的方法(System.arraycopy)

有時候需要建立一個新陣列,這個新陣列跟舊的陣列前面都一樣
只有最後幾個值不同或是加了幾個值

或是有兩個陣列,我們需要合併這兩個陣列的時候
除了用for迴圈把陣列一個一個倒進去以外
我們可以使用System的arraycopy方法

文件方法如下
arraycopy(Object src, int srcPos, Object dest, int destPos, int length)

第一個src要放入的是被複製的陣列
srcPos是指定被複雜的陣列從第幾項開始複製

dest放入的是要複製的陣列
destPos是指定要複製的陣列從第幾項開始寫入

length放入的是你總共要複製幾項資料
以下是最常用的兩個範例


public class copyArrayDemo {



 public static void main(String[] args) {

  System.out.println("This is demo 1");

  int[] arr1 = {1,2,3};

  int[] arr2 = new int[arr1.length+1];

  System.arraycopy(arr1, 0, arr2, 0, arr1.length);

  arr2[arr1.length]= 4;

  // arr2 == {1,2,3,4}

  for(int item:arr2){

   System.out.println(item);

  }

  System.out.println("This is demo 2");



  

  String[] array1 = {"item1","item2","item3"};  

  String[] array2 = {"demo1","demo2","demo3"};

  

  

  String[] sum = new String[array1.length+array2.length];

  System.arraycopy(array1, 0, sum, 0, array1.length);

  System.arraycopy(array2, 0, sum, array1.length, array2.length);

  // sum =={"item1","item2","item3","demo1","demo2","demo3"}

  for(String item:sum){

   System.out.println(item);

  }    

 }

}

2015年10月26日 星期一

[Java]StringTokenizer

今天介紹一個除了split()方法以外,分割String的方法
StringTokenizer的方法主要有下列幾個

countTokens():可以知道你的String被Tokenizer分成幾段
hasMoreTokens():檢查StringTokenizer是否還有Token
nextToken():將StringTokenizer的下一個Token用String表示

以下是簡單的範例:



import java.util.StringTokenizer;



public class StringDemo {


 public static void main(String[] args) {

  String demo = "String,int,long,double";



  StringTokenizer st = new StringTokenizer(demo,",");

 

  System.out.println("st has "+st.countTokens()+"tokens");

 

  while(st.hasMoreTokens()){

   System.out.println();

  }

 }

}

2015年10月15日 星期四

[Java面試考題]Map處理

今天去松凌科技面試時遇到的考題
限時30分鐘
做出來後我問了一下面試官說能不能把考題公佈
面試官很慷慨的答應了,表示說他們也希望大家都能夠會處理map
於是我回家後馬上將這題題目重現
中文的註解可能有些誤差,以下是題目跟參考解答
題目詳細內容請見註解




import java.util.HashMap;
import java.util.Map;

public class RightLeft {

Map<String, Integer> left;
Map<String, Integer> right;

public void setUp(){
left = new HashMap<String, Integer>();
left.put("a", 1);
left.put("b", 2);
left.put("c", 3);

right = new HashMap<String, Integer>();
right.put("b", 2);
right.put("c", 4);
right.put("d", 5);

}

/*
* <pre>
* 備住:有兩個Map left right,請在Test()內完成程式碼輸出以下內容
*
* 1.key一樣value不一樣的內容
* 2.key一樣value一樣的內容
* 3.key只存在left不存在right的內容
* 4.key只存在right不存在left的內容
*
*/

public void Test(){

//answer of 1
System.out.println("1.");
for(Object key:left.keySet()){
if(right.get(key)!=null){
if(!right.get(key).equals(left.get(key))){
System.out.println("left key="+key+", value="+left.get(key));
System.out.println("right key="+key+", value="+right.get(key));
}
}
}

//answer of 2
System.out.println("2.");
for(Object key:left.keySet()){
if(right.get(key)!=null){
if(right.get(key).equals(left.get(key))){
System.out.println("left: key="+key+", value="+left.get(key));
System.out.println("right: key="+key+", value="+right.get(key));
}
}
}

//answer of 3
System.out.println("3.");
for(Object key:left.keySet()){
if(right.get(key)==null){
System.out.println("left: key="+key+", value="+left.get(key));
}
}

//answer of 4
System.out.println("4.");
for(Object key:right.keySet()){
if(left.get(key)==null){

System.out.println("right: key="+key+", value="+right.get(key));

}
}


}



public static void main(String[] args) {
RightLeft demo = new RightLeft();
demo.setUp();
demo.Test();

}

}

2015年10月11日 星期日

[Java]如何求N個整數的最大公因數

這個問題我認為原理非常的簡單...我在學Java的第一週就可以把他做出來
不過後來時間久了就忘記要把這個問題的解法丟上來

趁著現在比較有空的時間把教學簡單的打一下


首先從兩個整數的最大公因數開始
整數的最大公因數就是能夠同時整除他們的最大整數
求最大公因數的方法有很多種,其中一種方法叫做輾轉相除法
我們直接拿30跟18這兩個整數做例子
30/18=1餘12
18/12=1餘6
12/6=2

由於6整除了,所以30跟18的最大公因數就是6

從例子我們知道做法就是如果兩數沒有整除,就把原來的除數當做被除數,把餘數當做除數繼續除下去,直到兩數整除為止

於是我們可以知道求a,b兩數的最大公因數,相當於求b與a,b的餘數的最大公因數
以下就是簡單的範例,我們用一般的while迴圈展示輾轉相除法的演算法
另外使用遞迴當做參考

public class Gcd {



 public static void main(String[] args) {  

  //demo1

  System.out.println(gcd(18,12));

    

  //demo2

  System.out.println(gcd2(30,18));  



 }



 public static int gcd(int m, int n){

  int result = 1;

  while(m%n!=0){

   result=n;   

   n=m%n;

   m=result;

  }

  result=n;

  

  return result;

 }

 

 public static int gcd2(int m, int n){

  if(m%n==0){

   return n;

  } else {

   return gcd2(n,m%n);

  }  

 } 

}


接下來三個整數的最大公因數就是將前兩個最大公因數跟第三個數字做最大公因數
四個整數的最大公因數則是將三個整數的最大公因數與第四個數字做最大公因數...
以此類推
以下程式碼就只用while迴圈當範例,遞迴的寫法請自情參考兩個整數的程式碼


public class Gcd {



 public static void main(String[] args) {

  

  //demo1

  int[] x = new int[] {18,12,30};  

  System.out.println(dogcd(x));  

  

  //demo2 

  int[] y = new int[] {15,18,30,42,9};

  System.out.println(dogcd(y));

 }

 

 public static int dogcd(int[] input){

  for(int i=0;i<input.length-1;i++){

   input[i+1] = gcd(input[i],input[i+1]);

      

  }  

  return input[input.length-1];

 }



 public static int gcd(int m, int n){

  int result = 1;

  while(m%n!=0){

   result=n;   

   n=m%n;

   m=result;

  }

  result=n;

  

  return result;

 }
  

}

2015年10月7日 星期三

[雜談]由數學學習談程式語言學習

最近跟人聊天發現有人學程式的方法
發現其實跟人學數學的方法有異曲同工的感覺

數學其實跟程式是非常相似的東西,常常有人講說數學重理解
也有人覺得數學就是背公式多解題就學會了
當然不同職業需求的人需要學到的程度會有一些差別
但是我覺得學數學的人有幾個程度的差別
比如說求三角型面積好了

知道底乘以高除以二的公式的人至少比不知道公式的人學的好

了解到因為平行四邊型面積是底乘以高
兩個三角型的面積剛好等於平行四邊型面積的人又可以不用死背造成公式的誤用

但是學數學還有一種能力也很重要
你有沒有辦法在不知道三角型面積怎麼算的時候
發現說你只要能會算平行四邊型的面積就能夠求三角型的面積
最後發現由長方型的面積是長乘與寬,然後推得平型四邊型的面積是底乘以高

若是可以學得分解問題以及將未知問題與已知的知識連結的能力的話
學習程式就相對的簡單了
應該要把大功能拆成小步驟
比如說現在要按一個按紐後將三個網頁上輸入的數字做運算後顯示在畫面上
那麼你至少可以知道說
1.按紐需要一個onclick事件
2.onclick事件裡面的function需要抓三個變數
3.再來把三個變數做運算
4.最後將某個div的值改成運算的結果

這些事情每一步都不難,問題講成一個需求時為什麼做不出來?
就是因為沒有去把需求分解成好幾個做的出來的步驟,然後一步步把每個步驟完成

當然,你對程式語言越熟你就越能夠把程式做出來,因為你拆解步驟的同時你也會思考這個
解決方案到底程式做不做的出來,所以除了學習如何拆解問題以外
多學習程式語言裡面的函式庫怎麼用是一定有幫助的

2015年10月6日 星期二

[Java]費氏數列

費氏數列(fibonacci sequence)是程式語言中常見的遞迴範例
他的每一項分別是:
A0=0
A1=1
AN=A(N-1)+A(N-2)
也就是A2以後,每一項的值就是前兩項的值相加
使用遞迴的方法可以把費式數列的值做出來
以下是遞迴的範例


public class FibonacciTest {

  

 public static void main(String[] args) {
    
   System.out.println(fibonacci(50));    

 }

  

 public static long fibonacci(int x){

  if(x==1||x==2){

   return 1;

  }else {

   return fibonacci(x-1)+fibonacci(x-2);

  }  

 }  

}




但是使用遞迴的效能很差
所以如果有人提出這個問題
又沒有特別規定要用遞迴做出來的話
建議使用一般的迴圈來解決這個問題
效能會有明顯的改善
以下是範例


public class FibonacciDemo {



 public static void main(String[] args) {

  

  FibonacciDemo demo = new FibonacciDemo();

  System.out.println(demo.fibonacci(50));  

 }

 

 public long fibonacci(int n){

  if(n==0){

   return 0;

  } else {

   long x_1 = 0;

   long x_2 = 1;

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

    if(i>0){

     x_2 = x_2 + x_1;

     x_1 = x_2 - x_1;

    }
   
   }

   return x_2;

  }

 }


}


2015年9月26日 星期六

[JSP]圖片或檔案上傳進資料庫的方法

要做出上傳圖片的form表單,首先必須要在表單的標籤上增加一個enctype
如下圖



表單的enctype分為三種
  1. application/x-www-form-urlencoded
  2. multipart/form-data
  3. text/plain
預設是第一種編碼
第二種編碼在需要上傳檔案時使用
第三種是不對特殊字元進行邊碼

詳情的說明可以去查form的enctype屬性

再來要接收multipart/form-data時,servlet需要定義xml或用annotation定義
主要的屬性有:
  1. location: 上傳之表單資料與檔案暫時存放在Server端之路徑。
  2. fileSizeThreshold: 檔案的大小臨界值,超過的話檔案會被寫入上傳文件裡
  3. maxFileSize: 上傳單一檔案之長度限制
  4. maxRequestSize: 上傳所有檔案之總長度限制

3跟4的屬性預設是-1,表示不設限制

我習慣是用annotation定義,如下圖


最後你可以用
Part part = request.getPart("image");
或是
Collection<Part> parts = request.getParts(); 
來獲得part物件處理上傳的檔案資料

part物件可以使用getSize()與getInputStream()這些方法將圖片寫入資料庫
或是使用write()將資料寫入資料庫

詳細的方法文件請詳見java文件的java.servlet.http.part這隻class


以下是我將多張圖片寫入資料庫的程式片段

最後將list傳進dao裡呼叫資料庫就能進行多張圖片的存取

2015年9月22日 星期二

[雜談]學習程式的方法

常常有人網路上的教學都看不懂,老師上課聽不懂
範例程式也看不懂
老實講不管學那個程式語言都一樣
程式是邊想邊做來學習的,絕對不是用眼睛看程式碼跟他大眼瞪小眼你就會學會的
除非你已經相當有經驗看的懂那些程式碼在編譯執行後會怎麼樣運作
不然你初學時絕對100%不可能光用看的就學的會

就跟你不可能拿著數學課本用看的就可以學會數學一樣
你至少要想過並且算過或證明你想的是對的
或至少證明事情不是你想的那樣

像是下面的範例
Timer的範例

範例的程式碼有時就算看註解也不是很懂怎麼辦
很簡單,照個做一遍看看是怎麼回事


首先依照那範例的class名稱取的名字一樣的class建立起來



然後無腦的把程式碼整段複製貼上
如果有紅字看看是不是沒有附上需要的jar檔
不過這篇範例很棒一貼上一個錯誤都沒有

因為這是個計時器的程式,我想要看他怎麼運作的
於是我在run方法跟main方法下開始加點料
如果有讀點書的話
至少會知道main方法是程式起始點,所以在main方法的最前面new Date去看現在時間
然後在run方法裡面也system.out.println 時間一下看看他怎麼運作的

最後程式執行起來長這個樣子

我們就會知道說這個範例第二個參數的5000是從timer執行start()方法5秒後執行第一次
第三個參數的2000表示的是每次執行的間格是2秒

多數的程式註解或說明在初學時期都不是很清楚
想要建立觀念正確的方法就是去想並且去做
很多東西,看了不會懂,做下去就懂了

2015年9月13日 星期日

[Java]StringBuilder與StringBuffer常用的方法簡介

這兩個class主要是在字串串接很多字的時候,
由於String字串池的關係會生出很多字串物件,
為了節省記憶體就會使用使用StringBuilder跟StringBuffer

StringBuilder跟StringBuffer的方法幾乎一模一樣
關於兩者的差別請見右邊連結:連結在此
常用的方法有:

append() :這個方法是將字串接在字串的最後方
insert():這個方法可以將字串接在你指定的位置
indexOf():這個方法是尋找某個字串在現在這段字的那個位置,可以拿來搭配insert使用
reverse():可以將整個字串反轉順序,雖然我幾乎用不到
toString():就是將串好的字轉成字串輸出
length():現有的字串長度

以下就是簡單的範例



public class StringBuilderDemo {

 public static void main(String[] args) {
  
  StringBuilder sb = new StringBuilder();

  sb.append("This is ");

  sb.append("a star");

  System.out.println(sb.toString());//This is a star

  System.out.println(sb.length());//14

  System.out.println(sb.indexOf("star"));//10

  sb.insert(sb.indexOf("star"), "new ");

  System.out.println(sb.toString());//This is a new star

  System.out.println(sb.reverse().toString());//rats wen a si sihT

 }

}

2015年9月7日 星期一

[Java]&&, || 與 &,| 運算子的不同

在Java上有&&跟||這個運算子與 & 跟 | 這個運算子

雖然&&跟&都是and運算
||和 | 都是or運算
不過實際運作起來是有差別的
&&跟||運算時如果結果已經確定運算結果
他們就不會再撿查下一個敘述是否為真

比如說 A&&B
如果A已經是false了,那麼不管B是true or false,結果都是false
所以就不會去檢查B

像是下面的程式碼可以運作

public class Demo {



 public static void main(String[] args) {

  String a = null;

  String b = "a";



  System.out.println(a==null||a.equals(b));//true

  System.out.println(a!=null&&a.equals(b));//false

 }

}


然後&跟|不管如何兩個序述都會檢查
所以下面的程式碼就會跳nullpoint

 public static void main(String[] args) {

  String a = null;

  String b = "a";



  System.out.println(a==null|a.equals(b));//true

  System.out.println(a!=null&a.equals(b));//false

 }

}

[教學]如何在Eclipse中使用Github(Dynamic project)(後記)

有鑑於用之前的設定方式在共通作業時classpath常常會跳出問題
所以我試著去把跟eclipese有關的檔案全部ignore的方法
方法大致上跟前面兩篇一樣,請自行參閱前兩篇
上篇
下篇
不過設定的時候.ignore檔設定改成這樣

因為多設定了一些ignore檔案
所以拉下來的方法稍微不一樣



請務必在project explorer上右鍵不是點下面的Repository不然之後拉下來會長的很怪
Repository拉到本地端後不要點Repository右鍵
改成在project explorer右鍵來import


找到Git裡面的Projects from Git


再來選Existing local repository


下一步到這邊點Import as general project
並且把選擇你要的專案資料夾
下一步後按finish


資料夾還是一樣看不懂,沒關係按右鍵選擇Properties


與之前方法不同的是Project Facets畫面不一樣
點畫面中的Convert to faceted from...


這時會出現跟之前方法差不多的畫面
點選Dynamic web modile跟Java還有把Runtime的Server打勾
版本記得先跟團隊確認好不要選錯,按下ok就完成了


(‧ω‧‵)將將將將~~完成啦



2015年9月4日 星期五

[教學]如何在Eclipse中使用Github(Dynamic project)(下)

本篇要示範的是怎麼將已經推上去的檔案拉回本機端
如果要看怎麼將專案推上去請去看上一篇
文章的上篇內容請點此

首先點選Clone a Git repository,並且貼上你要拉下來專案的連結
如果在這一步出現 「Internal error; consult Eclipse error log.」
請到使用者user目錄下的「.eclipse\org.eclipse.equinox.security」資料夾內刪除「secure_storage」這個檔案,然後重新啟動eclipse。


如果你專案推了很多奇怪的支線進去你就要知道你要拉下來的是那一枝了
不過一般來說看到這畫面應該都是直接下一步才對


這個路逕是以後你要找檔案的地方,選個你方便找檔案的路徑


再來要複製專按,點你拉下來的Repository右鍵→Import Projects



選Import exsting projects並且點你要的專案內容後按下一步


然後按Finish後將專案拉下來


接著你點開專案會發現這專案完全看不懂
不過不要緊張這個可以解決


點選專案右鍵→Properties


選到Project Facets,先點到Runtimes那邊將你的server打勾
這邊我用的是Tomcat 8.0、接著Dynamic Web Module、Java、JavaScript打勾後按OK
剩下的設定也要跟將專案推上來的人同步
像是Java編碼跟Html或Xml的編碼等等


然後按ok後就會發現親愛的專案他回來了

[教學]如何在Eclipse中使用Github(Dynamic project)(上)

因為有人反應說Eclipse使用Github相當複雜
稍微整理一下後說一點簡單的設定說明

本篇介紹的是將專案上傳,下篇會介紹怎麼將上傳的檔案拉下來
如何將推上去的專案拉下來請看這篇
首先要把Git的repository打開

點選window→showview→other


然後在GIT選項找到Git Repositories,找不到Git選項上面直接打Git搜尋關鍵字


點選你要上傳的專案右鍵→Team→Share Project


選擇Git


然後挑選一個你比較好找到的位置放你的Git檔案,最後按Finish


複製你Git的連結


因為把.classpath跟.project也設成ignore時Eclipse專案設定會很困難
所以建議在團隊都使用Eclipse時
將Working Directory/Demo/.gitignore下的設定成這樣
只忽略/build/跟/.settings/資料夾
/.classpath跟 /.project就不設定,之後比較好拉檔案下來


再來將檔案commit上去


因為這是範例commit的內容沒有很認真寫,以後不認真寫內文你就知道發現bug要回溯到想要的時間超難找的


然後把剛剛複製的連結貼上來
下方是Git帳號密碼


推的時候把master add上去按finish


如果看到這個畫面沒有挑出錯就表示資料推上去了
要詳細之道怎麼拉資料的請點選下面連結

這是下篇的連結

2015年9月1日 星期二

[Java]Sting、StringBuffer與StringBuilder

String因為字串池的關係,當你做出下面的運算時

Sting x = "a"+"b"+"c"+"d";
JVM會產生四個String物件,所以當你有字要串起來時為了節省記憶體通常不會使用String
而會使用StringBuffer與StringBuilder
那麼StringBuffer與StringBuilder到底要選什麼用呢?首先要了解兩者的不同
StringBuffer與StringBuilder第一個不同在於兩者的效能有明顯的差距
如下面範例

public class Test {

    public static void main(String[] args) {

        int N = 77777777;

        long t;

        {

            StringBuffer sb = new StringBuffer();

            t = System.currentTimeMillis();

            for (int i = N; i --> 0 ;) {

                sb.append("");

            }

            System.out.println(System.currentTimeMillis() - t);

        }

        {

            StringBuilder sb = new StringBuilder();

            t = System.currentTimeMillis();

            for (int i = N; i --> 0 ;) {

                sb.append("");

            }

            System.out.println(System.currentTimeMillis() - t);

        }

    }

}


那麼要建立String就用StringBuilder囉?
其實不見得
StringBuffer是synchronized,也就是在多執行緒上他比較不會發生錯誤
StringBuilder在多執行緒的程式上就必須注意Thread safe的問題

2015年8月29日 星期六

[JAVA]Java物件使用 == 與 .equals方法的差別

在Java基礎資料形別(byte,short,int,long,boolean,char,float,double)的==判斷式就是檢查兩個資料的值是否相等,但是到物件參考形別是==表示的是兩個物件參考的記憶體位置是否一樣

比如說
Object A = new Object();
Object B = new Object();

A==B的時候就是false


Object A = new Object();
Object B = ObjectA;

A==B的時候結果是true

在這邊要檢查兩個物件裡面的參數是否一樣的時候就需要要用到.equals方法
這個方法是java.lang.Object的方法
所以在編寫class時可以被覆寫
你可以自行定義什麼情況下兩個class內容是相等的
就可以使用 A.equals(B)這種語法來判斷兩個物件是不是你定義的相同

String雖然是物件,但是因為字串池的關係

String A ="abc";
String B ="abc";
兩個字串物件會指到同一個記憶體位置
A==B的結果會是true

但是如果想要程式用一些method撈值用String存的話
A==B兩個字串即使值是一樣的結果也會顯示false
這時使用A.equals(B);
比較不會發生問題造成維護上的困擾

2015年8月19日 星期三

[Android]把輸入的值傳到下一個畫面的方法

這個範例只是簡單的把帳號資料傳到下一個畫面
中間並沒有經過資料庫跟資料驗證
有興趣可以做個資料驗證,就可以做個簡單的登入程式

在專案裡的res/layout資料夾新增兩個xml檔如下:

login.xml:

<?xml version="1.0" encoding="utf-8"?>

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"

    android:layout_width="match_parent"

    android:layout_height="match_parent" >



    <TextView

        android:id="@+id/textView01"

        android:layout_width="wrap_content"

        android:layout_height="wrap_content"

        android:layout_alignParentLeft="true"

        android:layout_alignParentTop="true"

        android:layout_marginTop="18dp"

        android:text="帳號" />



    <TextView

        android:id="@+id/textView02"

        android:layout_width="wrap_content"

        android:layout_height="wrap_content"

        android:layout_alignParentLeft="true"

        android:layout_below="@+id/textView01"

        android:layout_marginTop="14dp"

        android:text="密碼" />



    <EditText

        android:id="@+id/editText01"

        android:layout_width="wrap_content"

        android:layout_height="wrap_content"

        android:layout_alignTop="@+id/textView01"

        android:layout_toRightOf="@+id/textView01"

        android:ems="10"

        android:inputType="textPersonName" >



        <requestFocus />

    </EditText>



    <EditText

        android:id="@+id/editText02"

        android:layout_width="wrap_content"

        android:layout_height="wrap_content"

        android:layout_alignTop="@+id/textView02"

        android:layout_toRightOf="@+id/textView02"

        android:ems="10"

        android:inputType="textPassword" />



    <Button

        android:id="@+id/button01"

        android:layout_width="wrap_content"

        android:layout_height="wrap_content"

        android:layout_alignRight="@+id/editText02"

        android:layout_below="@+id/editText02"

        android:layout_marginTop="16dp"

        android:text="送出" />



</RelativeLayout>

result.xml:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >
    <TextView
        android:id="@+id/textView00"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentLeft="true"
        android:layout_alignParentTop="true"
        android:text="Large Text"
        android:textAppearance="?android:attr/textAppearanceLarge" />
</RelativeLayout>

然後編寫MainActivity.java檔如下

public class MainActivity extends Activity {
TextView textView00 = null;
EditText editText01 = null;
EditText editText02 = null;
Button button01 =null;
public void onCreate(Bundle savedInstanceState){
setContentView(R.layout.login);
editText01 = (EditText) findViewById(R.id.editText01);
button01 = (Button) findViewById(R.id.button01);
button01.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
String name = editText01.getText().toString();
setContentView(R.layout.result);
textView00 = (TextView) findViewById(R.id.textView00);
textView00.setText("你好:"+name);
}
});
}
}

2015年8月13日 星期四

[SQL Server2012]將資料庫複製到別的資料庫-產生指令碼

首先點選要複製的資料庫滑鼠右鍵後選工作→產生指令碼


接著會出現摘要的畫面,不想看說明就不要理他直接按下一步
再來是選擇要匯出資料庫的內容,如果想全部複製就用預設值,
因為我不想複製預存程序我使用了自訂內容

再來這個畫面請按進階做一些進階設定


首先是Script DROP and CREATE屬性,
若是你要複製過去的Database有同名的資料的話,
只編寫CREATE指令資料就有可能放不進去
但是使用DROP指令要小心,你要確定那邊同名的資料庫沒有重要的資料
不然一執行那邊的資料可能就會毀掉,除非你確定另一邊沒有重要資料不然建議
不要使用 DROP and CREATE這個功能


指令碼很貼心的提供了舊的版本,有需要的話可以自行設定

若資料是要複製到Microsoft Azure的資料庫,請將屬性改為SQL Azure資料庫
如果是一般電腦上的資料庫就直接選獨立執行個體
這個選項要看你需要複製什麼出來
因為有時候你只是要抽出這些DataBase的結構來研究,並不需要裡面的資料
連資料一起抽出來的話檔案會很大
只要複製Table不要複製裡面的資料的話只要選擇僅限結構可以有限節省空間
預設是僅限結構描述,如果需要連資料一起複製出來的話
這個選項的屬性必須改成結構描述和資料

都設定完成後記得更改匯出的檔名與路徑方便尋找,
接著就是下一步&下一步

完成後就可以在剛剛的路徑找到對應的Sql檔了